every case is now listed out for improved error reporting in:

https://github.com/sqlalchemy/sqlalchemy/issues/4433


On Wed, Jan 9, 2019 at 12:21 AM Mike Bayer <mike...@zzzcomputing.com> wrote:
>
> On Tue, Jan 8, 2019 at 4:16 PM Gmoney <grgg...@gmail.com> wrote:
> >
> > Unable to limit the columns returned from a query using .load_only or 
> > .with_entities.  I feel like I'm missing a key concept here, and could use 
> > some guidance.
> >
> > One column of interest is a relationship - which I'm guessing is my problem.
> > class Task(Base):
> >     __tablename__ = 'TASK'
> >     id = Column('ID', VARCHAR2(250), primary_key=True)
> >     subject = Column('SUBJECT', VARCHAR2(250))
> >     comments =relationship('Comment', back_populates='task', lazy='joined')
> >
> > class Comment(Base):
> >     __tablename__ = 'COMMENT'
> >     id = Column('ID', Integer, primary_key=True)
> >     msg_id = Column('MSG_ID', VARCHAR2(250), ForeignKey(Task.id))
> >     comment_given_by = Column('COMMENT_GIVEN_BY', VARCHAR2(250))
> >     task = relationship('Task', back_populates='comments', lazy='joined')
> >
> > Running the query without any attempt to limit columns works fine (ie. the 
> > Classes/models seem OK)
> > query = session.query(Task)
> >
> > But now I tried .with_entities.
> > If you ONLY request actual Columns, and not relationships, it lists the 
> > columns and tables in the select, but does not add the ON clause (cartesian 
> > join)
> > If I request the relationship, it generates invalid SQL:
> > query = session.query(Task).with_entities(Task.id, Task.comments)
> >     # SELECT
> >     # "TASK"."ID",
> >     # "TASK"."ID" = "COMMENT"."MSG_ID" AS comments
> >     # FROM
> >     # "TASK",
> >     # "COMMENT"
> >
> >
> > So trying with .load_only:
> > No luck many ways, all failing... every random thing I try results in a 
> > different exception - I feel like I'm getting farther and just guessing now
>
> The documentation for what you are trying to do is at:
>
> https://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#deferred-loading-with-multiple-entities
>
> When there are multiple entities, the Query never jumps between two
> entities without you specifying how you get there.    in this case,
> the way you navigate between them is via Task.comments, so that
> navigation must be stated:
>
> session.query(Task).options(load_only(Task.id),
> defaultload(Task.comments).load_only(Comment.comment_given_by))
>
> You in fact did pretty much the same query at the end of your attempts
> and I think you probably relied upon print(query) to determine if it
> was "working" or not, because your query with subqueryload() works,
> you just would not be able to see this by print(query) alone because
> subqueryload() emits a second query only when the objects are loaded.
>
>
> >
> > query = session.query(Task, Comment).options(load_only(Task.id, 
> > Comment.comment_given_by))
> > ---->sqlalchemy.exc.ArgumentError: Wildcard loader can only be used with 
> > exactly one entity.  Use Load(ent) to specify specific entities.
>
> load_only means, defer('*') + undefer(Task.id) +
> undefer(Comment.comment_given_by).     But the wildcard doesn't know
> how to do Task, Comment together, you would need to say
> Load(Task).load_only(Task.id),
> Load(Comment).load_only(Comment.comment_given_by), but again this is
> not what you want because you are asking for a cartesian product in
> the above query.   Error message is not great here because it comes
> from the defer('*') that you can't see happening here, so that should
> be improved.
>
>
>
> > query = session.query(Task).options(load_only('id', 'comments'))
> > ----> Exception: can't locate strategy for <class 
> > 'sqlalchemy.orm.relationships.RelationshipProperty'> (('deferred', False), 
> > ('instrument', True))
>
> load_only() does not apply to relationships like "comments', only to
> columns.   again not a great error message here, that could be
> improved.
>
>
> >
> > query = session.query(Task).options(load_only(Task.id, 
> > Comment.comment_given_by))
> > ----> sqlalchemy.exc.ArgumentError: Can't find property 'comment_given_by' 
> > on any entity specified in this Query.  Note the full path from root 
> > (Mapper|Task|TASK) to target entity must be specified.
>
> Task has nothing to do with Comment unless you state this in terms of
> Task.comments, which is what "full path" means
>
>
> >
> > query = session.query(Task, Comment).options(load_only(Task.id, 
> > Comment.comment_given_by))
> > ----> sqlalchemy.exc.ArgumentError: Wildcard loader can only be used with 
> > exactly one entity.  Use Load(ent) to specify specific entities.
>
> you already tried this one above
>
>
> >
> > query = session.query(Task).options(load_only(Task.id, Task.comments))
> > ----> Exception: can't locate strategy for <class 
> > 'sqlalchemy.orm.relationships.RelationshipProperty'> (('deferred', False), 
> > ('instrument', True))
>
> this is the same thing as the other one you did, string attribute
> names or Object.attrname, same thing
>
> >
> > query = session.query(Task).options(load_only(Task.comments), 
> > subqueryload("comments").load_only('comment_given_by'))
> > ----> No exception but only generates:  "SELECT "TASK"."ID" FROM "TASK"
>
> I'm not sure you tested this correctly, this one actually works - the
> subqueryload("comments") cancels out the load_only(Task.comments) that
> would normally raise an error.  Subqueryload is emitted as a second
> query, so if you just said print(query), you would not have seen it.
>
> Here is what it emits if I run on a model like this:
>
> s.query(A).options(load_only(A.bs), 
> subqueryload(A.bs).load_only(B.data)).all()
>
> output:
>
> SELECT a.id AS a_id
> FROM a
>
> SELECT b.id AS b_id, b.data AS b_data, anon_1.a_id AS anon_1_a_id
> FROM (SELECT a.id AS a_id
> FROM a) AS anon_1 JOIN b ON anon_1.a_id = b.a_id ORDER BY anon_1.a_id
>
>
>
> >
> > --
> > SQLAlchemy -
> > The Python SQL Toolkit and Object Relational Mapper
> >
> > http://www.sqlalchemy.org/
> >
> > To post example code, please provide an MCVE: Minimal, Complete, and 
> > Verifiable Example. See http://stackoverflow.com/help/mcve for a full 
> > description.
> > ---
> > You received this message because you are subscribed to the Google Groups 
> > "sqlalchemy" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to sqlalchemy+unsubscr...@googlegroups.com.
> > To post to this group, send email to sqlalchemy@googlegroups.com.
> > Visit this group at https://groups.google.com/group/sqlalchemy.
> > For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to