Comments (9)
this is sort of not the place to keep discussing this. if you can take this program and alter it to show an example of this "one row when there should be three" thing, start a new discussion
from sqlalchemy.
Mike Bayer has proposed a fix for this issue in the main branch:
disable col deduping inside of Bundle https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/5276
from sqlalchemy.
Mike Bayer has proposed a fix for this issue in the rel_2_0 branch:
disable col deduping inside of Bundle https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/5277
from sqlalchemy.
Mike Bayer has proposed a fix for this issue in the main branch:
revise approach for bundle deduping https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/5280
from sqlalchemy.
Mike Bayer has proposed a fix for this issue in the rel_2_0 branch:
revise approach for bundle deduping https://gerrit.sqlalchemy.org/c/sqlalchemy/sqlalchemy/+/5301
from sqlalchemy.
Hello @zzzeek ,
I'm bringing more activity to this matter as I may have found another bug.
I've updated my sqlalchemy version to latest today and worked on the feature described in the discussion.
The feature worked nicely with my initial version of the function, only handling x-to-one
(nested entities) relationships.
I went on to tackle x-to-many
(nested lists) relationships
My statement building currently looks like this:
rels = table.relationships()
nested, fields = partition(fields, lambda x: x in rels)
stmt = select(
DictBundle(
table,
*[getattr(table, f) for f in fields],
*[
DictBundle(
nes,
*[
getattr(get_declarative_class(rels[nes].target), f)
for f in [
x.name for x in rels[nes].target.columns
]
]
)
for nes in nested
],
)
)
joins = []
for rel, nes in zip(rels, nested):
# Handle x-to-many (nested lists) relationships
if rel.secondary is not None:
stmt = stmt.join_from(self.table, rel.secondary)
stmt = stmt.join_from(self.table, rel.target)
stmt = stmt.where(...)
Example
On a similar example as in the discussion, where myresource
has now tags
attached:
class Tag(Base):
name = Column(String, primary_key=True)
class MyResource(Base):
id = ...
...
tags: Mapped[Set["Tag"]] = relationship(secondary=asso_res_tag, uselist=True, lazy="joined")
asso_res_tag = Table(
"ASSO_RES_TAG",
Base.metadata,
Column("id_myresource", ForeignKey("MYRESOURCE.id"), primary_key=True),
Column("name_tag", ForeignKey("TAG.name"), primary_key=True),
)
and trying out with some test case:
curl -d '{ "name": "test", "contact": {"username": "test"}, "tags": [{"name":"bip"}, {"name":"bap"}, {"name":"bop"}],}' http://127.0.0.1:8000/myresources/
and querying my object
curl http://127.0.0.1:8000/myresources/1?name,contact,tags
query result before serialization:
{'name': 'test', 'contact': {'username': 'test', 'email': None, 'firstName': None, 'lastName': None}, 'tags': {'name': 'bap'}}
and after serialization I completely loose the tags
fields because marshmallow is expecting a list for it.
So my best guess is that somewhere in the pipeline, uselist
isn't consumed.
I've tried adding an id
to the tags table and changing the relationship/associative table accordingly hoping to help statement inferences and it didn't.
Let me know if you have a clue.
Best regards,
from sqlalchemy.
im not sure what you're doing there. uselist only has to do with loading ORM objects, and a Bundle does not load ORM objects. the join_from calls are fine but uselist has no interaction with those.
from sqlalchemy.
Good evening,
I'm sorry about bringing uselist
into this it was a bad wording inspiration on my part. I have little idea on how most of the core works, and frankly the source code is quite impressive.
For my issue,
I meant that it is only fetching a single result when querying a table object relationship column that is supposed to be a list.
It is returning only the top indexed as a single item which is then shaved at serialization step.
The snippets I've provided were describing my attempt at querying a table object with the possibility to restrict on a list of fields
(or defaults to a regular select(table)
)
- Some of those fields may be
relationship
fields
-> join those tables as well
The goal is to implement a an abstract REST GET function i.e.: /resource?field
If you want to run the code you may find it here: https://github.com/bag-cnag/biodm/tree/dev
It is still work in progress, but neatly packaged. There's a dedicated install and setup section in the Readme.
The source that I've provided are somewhat simplified examples of me tinkering with this function
I'm testing with the following command to create a dataset (replace generic myresource in my example):
curl -d '{"id": 1, "version": 1, "name": "ds_test", "contact": {"username": "test"}, "owner_group": {"name": "g"}, "tags": [{"name":"bip"}, {"name":"bap"}, {"name":"bop"}], }' http://127.0.0.1:8000/datasets/
and query it that way:
curl http://127.0.0.1:8000/datasets/1_1?fields=name,contact,tags
which yields the following sql code when I print the statement before executing it.
SELECT "DATASET".name, "USER".id, "USER".username, "USER".email, "USER"."firstName", "USER"."lastName", "TAG".id AS id_1, "TAG".name AS name_1
FROM "DATASET" JOIN "USER" ON "USER".username = "DATASET".username_user_contact JOIN "ASSO_DATASET_TAG" ON "DATASET".id = "ASSO_DATASET_TAG".id_dataset AND "DATASET".version = "ASSO_DATASET_TAG".version_dataset JOIN "TAG" ON "TAG".id = "ASSO_DATASET_TAG".id_tag
WHERE "DATASET".id = :id_2 AND "DATASET".version = :version_1
which when I run directly in my postgres DB plugging in my values for id and version (1, 1)
gets me:
name | id | username | email | firstName | lastName | id_1 | name_1
----------+----+----------+-------+-----------+----------+------+--------
ds_test | | test | | | | 1 | bip
ds_test | | test | | | | 2 | bap
ds_test | | test | | | | 3 | bop
So in principle the core gets back all my tags but doesn't make a list out of it when building my Dataset
item
c.f. result before serialization in my comment above.
Best,
from sqlalchemy.
I dont see any code here that I can run so I still dont really know what it is you're doing. is this still involving Bundle? Bundle only returns columns. you will get every row back individually. sub-bundles aren't going to be merged into lists or anything like that.
from sqlalchemy.
Related Issues (20)
- Parameter substitution fails when statement has a postgres style cast HOT 5
- reflecting oracle synonym of synonym over dblink HOT 4
- Changing decimal separator to comma using locale.setlocale causes crash on MSSQL columns of decimal type HOT 3
- Generated syntax error when using funcs in server_default in MySQL
- NoForeignKeysError and AmbiguousForeignKeysError after upgrade to 2.x HOT 5
- selectin_polymorphic does not work for multiple level joined inheritance HOT 2
- ColumnCollection.get(col, default) types as Optional even with default HOT 2
- bulk_save_objects() w/ return defaults writes incorrect identity key HOT 4
- `sqlalchemy.utils.langhelpers.TypingOnly` too rigidly prevents special dunders from appearing HOT 5
- func.count argument typing issue HOT 1
- Use of `raise NotImplementedError` instead of `NotImplemented` HOT 1
- Design a Repository pattern with sqlalchemy HOT 1
- Add `name` to `with_polymorphic ` HOT 2
- _JoinedListener can sneak into a metadata collection if Enum adapts itself, which can happen now, prohibiting serialization HOT 2
- TypeAlias cannot be found in type_annotation_map HOT 2
- Typing: of_type method not properly generic. HOT 1
- Add `insert_default` param to `Column` HOT 2
- many to many loaded relation instances partially missing reverse relation
- Add additional information to the `ReflectedColumn`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sqlalchemy.