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.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to