On Sep 25, 2013, at 10:11 AM, Ladislav Lenart <lenart...@volny.cz> wrote:
> Hello. > > Would it be possible to make these two forms > > session.query(cls).options( > subqueryload(cls.foos), > subqueryload(cls.foos, Foo.bar), > ) > > and > > session.query(cls).options( > subqueryload_all(cls.foos, Foo.bar) > ) > > completely equivalent, i.e. subqueryload_all being just a shortcut of the > former > if the paths have the above pattern (i.e. if one subqueryload is subsumed by > another)? unless there's some bug I'm unaware of, those two forms are exactly equivalent. XYZload_all("a.b.c") is a shortcut to XYZload("a"), XYZLoad("a.b"), XYZLoad("a.b.c"). In 0.9 I'm working out a new system backing the loader options that will allow more intuitive patterns, e.g. load(cls).subqueryload("foos").subqueryload("bar"). > > My motivation: I have a rather complex function (see below) used in several > contexts that returns Query.options for class Subject. The code is written to > eliminate duplication, but the current 'suboptimal' behaviour of subqueryload > (when compared to subqueryload_all) forces me to implement (and maintain) > several independent versions of this function. > > Or am I missing something that could help me (perhaps rephrase the loads > differently)? im not really sure. the API of this function seems a little complex to me, it's exposing details of the persistence mechanism while at the same time trying to hide part of it. > > The function (on class Subject) currently looks like this: > > @classmethod > def fetch_options( > cls, > prefix=None, alias=None, > fetch_name=True, > fetch_personal=True, fetch_corporate=True, > use_joinedload=True, use_innerjoin=True, > fetch_address=False, > fetch_tags=False, > fetch_all=False > ): > """Fetch subject info. Basic usage (note the '*'!): > session.query(Subject).options(*Subject.fetch_options()) > Arguments: > * prefix - Use if Subject is not queried directly, e.g.: > session.query(Partner).options( > *Subject.fetch_options(prefix=[Partner.subject]) > ) > * alias - Specify if necessary, e.g.: > subj_alias = aliased(Subject) > session.query(subj_alias).options( > *Subject.fetch_options(alias=subj_alias) > ) > * fetch_name - Fetch everything for Subject.display_name(partner). This > is the default. > * fetch_address - Fetch addresses-related info. Implies fetch_name. > * fetch_tags - Fetch tag-related info. Can be used on its own. > * fetch_personal - Set to False to supress fetching of any info about > persons. > * fetch_corporate - Set to False to supress fetching of any info about > corporations. > * fetch_all - Shortcut that implies all above. > * use_joinedload - joinedload() is used by default to fetch all 1:1 > relationships. If prefix contains 1:N relationship(s), set this to > False and subqueryload() will be used instead. > * use_innerjoin - One of fetch_personal or fetch_corporate MUST be > True. If only one is set, all joinedload() will be INNER by default. > Set this to False to force the use of OUTER. > """ > from zfp.model.contact import Contact, ContactPersonal, > ContactCorporate > from zfp.model.tag import TagSubject > if fetch_all: > fetch_name = True > fetch_personal = True > fetch_corporate=True > fetch_address=True > fetch_tags=True > elif fetch_address: > fetch_name = True > assert fetch_personal or fetch_corporate > use_innerjoin = use_innerjoin and not(fetch_personal and > fetch_corporate) > if use_joinedload: > def load_op(*args): > return joinedload(*args, innerjoin=use_innerjoin) > else: > def load_op(*args): > return subqueryload(*args) > if prefix is None: > prefix = [] > if alias is None: > alias = cls > options = [] > if fetch_name: > options.extend([ > subqueryload(*prefix + [alias.contacts]), > ]) > if fetch_personal: > options.extend([ > load_op(*prefix + [alias.subject_personal]), > subqueryload(*prefix + [alias.contacts, > Contact.contact_personal]), > ]) > if fetch_corporate: > options.extend([ > load_op(*prefix + [alias.subject_corporate]), > subqueryload(*prefix + [alias.contacts, > Contact.contact_corporate]), > ]) > if fetch_address: > if fetch_personal: > options.extend([ > load_op(*prefix + [alias.subject_personal, > SubjectPersonal.address]), > subqueryload(*prefix + [alias.contacts, > Contact.contact_personal, ContactPersonal.contact_address]), > subqueryload(*prefix + [alias.contacts, > Contact.contact_personal, ContactPersonal.permanent_address]), > ]) > if fetch_corporate: > options.extend([ > load_op(*prefix + [alias.subject_corporate, > SubjectCorporate.address]), > subqueryload(*prefix + [alias.contacts, > Contact.contact_corporate, ContactCorporate.address]), > ]) > if fetch_tags: > options.extend([ > subqueryload_all(*prefix + [alias.tag_subjects, > TagSubject.tag]), > ]) > if fetch_all: > options.extend([ > subqueryload(*prefix + [alias.contacts, Contact.phones]), > subqueryload(*prefix + [alias.contacts, Contact.emails]), > ]) > return options > > > Thank you, > > Ladislav Lenart > > -- > 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 http://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/groups/opt_out.
signature.asc
Description: Message signed with OpenPGP using GPGMail