On Sep 25, 2013, at 10:11 AM, Ladislav Lenart <[email protected]> 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 [email protected].
> To post to this group, send email to [email protected].
> 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
