Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLService models missing fields that are visible to a plain SQLAlchemy query #39

Open
mathrick opened this issue Sep 9, 2023 · 0 comments

Comments

@mathrick
Copy link

mathrick commented Sep 9, 2023

Hi, apologies for a lot of the details missing in this report; I've run into this issue while working on a unit test layer for a proprietary project at work, and I don't know how to reduce it to a small reproducible example, nor can I easily share a setup for you to access where the bug occurs. I'll be happy to provide any additional information you might need, if you can guide me in getting it for you.

I've run into a weird issue where query results are missing some, but not all fields when using reflected models based on SQLService declarative base, even though the database very much has them, and they're returned correctly when using a plain SQLAlchemy Table for the same query. This is the basic reflection setup we're using:

from sqlalchemy import MetaData, make_url, text
from sqlalchemy.ext.automap import automap_base
from sqlservice import Database, ModelBase, declarative_base


@contextmanager
def get_reflected_db(args):
    url = get_db_url(args)

    # Set up SQLService's enhanced declarative base together with Automap
    # for reflection of existing tables
    # See https://sqlservice.readthedocs.io/en/latest/model.html
    # and https://docs.sqlalchemy.org/en/20/orm/extensions/automap.html
    logger.info("Reflecting database {}", url)
    metadata = MetaData()
    Model = automap_base(declarative_base(ModelBase, metadata=metadata))
    db = Database(url, model_class=Model)
    try:
        db.reflect()
        # Invoke Automap
        Model.prepare(autoload_with=db.engine)
        yield db
    finally:
        db.close()

This is for a DB unit testing framework (not sure if that matters, but including it here for completeness), where in one of the tests, I'm exercising a stored procedure for adding users, and it fails the verification step to confirm that the results when querying it back match what was passed in. That's where the weirdness begins:

(Pdb++) usermodel
>>> <class 'sqlservice.model.users'>
(Pdb++) input_row
{'userid': None, 'secid': 1829, 'firstname': 'Dawn', 'lastname': 'Lopez', 'emailaddress': '[email protected]', 'positionid': None, 'accreditationnum': 526, ...}

(Pdb++) q = select(usermodel).where(usermodel.secid == input_row["secid"])
(Pdb++) print(q)
SELECT users.userid, users.secid, users.firstname, users.lastname, users.emailaddress, users.positionid, users.accreditationnum, ...
FROM users 
WHERE users.secid = :secid_1
(Pdb++) db.execute(q).scalar_one()
users(userid=1127, secid=1829, firstname='Dawn', lastname='Lopez', emailaddress='[email protected]', positionid=None, accreditationnum=None, ...)

(Pdb++) q2 = select(usermodel.accreditationnum).where(usermodel.secid == input_row["secid"])
(Pdb++) print(q2)
SELECT users.accreditationnum 
FROM users 
WHERE users.secid = :secid_1
(Pdb++) db.execute(q2).scalar_one()
526

(Pdb++) q3 = select(usermodel.__table__).where(usermodel.secid == input_row["secid"])
(Pdb++) str(q) == str(q3)
True
(Pdb++) db(q3).one()._mapping
{'userid': 1127, 'secid': 1829, 'firstname': 'Dawn', 'lastname': 'Lopez', 'emailaddress': '[email protected]', 'positionid': None, 'accreditationnum': 526, ...}

As you can see, the value for accreditationnum is missing when querying through the model, even though it's definitely visible if I ask for it explicitly, or drop down to the raw Table object. The query SQL generated is identical, and manually querying the DB confirms that the results are there.

Environment used:

$ python --version
Python 3.10.12

$ pip freeze
attrs==23.1.0
certifi==2023.7.22
charset-normalizer==3.2.0
click==7.1.2
exceptiongroup==1.1.2
Faker==19.2.0
fancycompleter==0.9.1
Flask==1.1.4
greenlet==2.0.2
idna==3.4
iniconfig==2.0.0
itsdangerous==1.1.0
Jinja2==2.11.3
loguru==0.7.0
MarkupSafe==2.1.3
packaging==23.1
pdbpp==0.10.3
pkginfo==1.9.6
pluggy==1.2.0
psycopg==3.1.9
Pygments==2.15.1
PyJWT==2.8.0
pyrepl==0.9.0
pytest==7.4.0
pytest-azurepipelines==1.0.4
pytest-loguru==0.2.0
pytest-nunit==1.0.3
python-dateutil==2.8.2
-e git+ssh://[email protected]/private/private.git@22fc3b6527726f8b55edce4fab5ee6a72ea318a4#egg=private&subdirectory=test
requests==2.31.0
six==1.16.0
SQLAlchemy==2.0.19
sqlservice==2.0.1
tomli==2.0.1
typing_extensions==4.7.1
urllib3==2.0.4
Werkzeug==1.0.1
wmctrl==0.4
@mathrick mathrick changed the title SQLService models missing fields that are visible when to a plain SQLAlchemy query SQLService models missing fields that are visible to a plain SQLAlchemy query Sep 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant