o xg@sdZddlZddlZddlZddlZddlZddlZddlmZm Z ddl m Z m Z ddl mZmZmZddlmZddlmZmZddlmZmZmZdd lmZdd lmZdd lmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%dd l&m'Z'dd l(m)Z)ddl*m+Z+ddl,m-Z-m.Z.m/Z/ddl0m1Z1m2Z2m3Z3m4Z4m5Z5ddl6m7Z7m8Z8m9Z9m:Z:ddl;mZ>m?Z?m@Z@ddlAmBZBddlCmDZDddlEmFZFddlGmHZHddgZIeFdZJeFdZKddZLddZMe dd ZNGd!ddZOGd"ddeZPd,d$d%ZQd&d'ZRd(d)ZSGd*d+d+ZTdS)-aW Create SQL statements for QuerySets. The code in here encapsulates all of the SQL construction so that QuerySets themselves do not have to (and could be backed by things other than SQL databases). The abstraction barrier only works one way: this module has to know all about the internals of models in order to get the information it needs. N)Counter namedtuple)IteratorMapping)chaincountproduct)ascii_uppercase)FieldDoesNotExist FieldError)DEFAULT_DB_ALIASNotSupportedError connections)Count) LOOKUP_SEP)BaseExpressionColExistsFOuterRefRefResolvedOuterRef)Field)MultiColSource)Lookup)Qcheck_rel_lookup_compatibilityrefs_expression)INNERLOUTER ORDER_DIR ORDER_PATTERNSINGLE) BaseTableEmptyJoin MultiJoin)ANDOR ExtraWhere NothingNode WhereNode)RemovedInDjango40Warning)cached_property)_lazy_re_compile)NodeQueryRawQueryz['`\"\]\[;\s]|--|/\*|\*/z[\w\-]+cCsttdd|DS)Ncss*|]}|jr |j|jfn|jfVqdSN)concretenameattname.0fr9;s  z,get_field_names_from_opts..)setr from_iterable get_fields)optsr9r9r:get_field_names_from_opts:s  r@ccs2|jD]}t|trt|EdHq|VqdSr2)children isinstancer/get_children_from_q)qchildr9r9r:rCAs   rCJoinInfo) final_fieldtargetsr?joinspathtransform_functionc@s^eZdZdZdddZddZddZd d Zd d Zd dZ e ddZ ddZ ddZ dS)r1zA single raw SQL query.r9cCs4||_||_||_d|_d\|_|_i|_i|_dS)NrN)paramssqlusingcursorlow_mark high_mark extra_selectannotation_select)selfrNrOrMr9r9r:__init__Rs  zRawQuery.__init__cCs ||Sr2clonerUrOr9r9r:r^s zRawQuery.chaincCst|j||jdS)N)rM)r1rNrMrYr9r9r:rXazRawQuery.clonecs6|jdur |t|jjjfdd|jjDS)Ncsg|]}|dqSrr9)r7 column_meta converterr9r: hsz(RawQuery.get_columns..)rP_execute_queryrrO introspectionidentifier_converter descriptionrUr9r]r: get_columnsds  zRawQuery.get_columnscCs6|t|jjjst|j}t|S|j}t|Sr2)r`rrOfeaturescan_use_chunked_readslistrPiter)rUresultr9r9r:__iter__ks  zRawQuery.__iter__cCsd|jj|fS)Nz<%s: %s>) __class____name__rdr9r9r:__repr__wszRawQuery.__repr__cCs"|jdurdSt|jtrtStSr2)rMrBrdicttuplerdr9r9r: params_typezs zRawQuery.params_typecCs"|jdur|jS|j||jSr2)rqrNrMrdr9r9r:__str__s zRawQuery.__str__cst|j}|j}|jj|turtfdd|jD}n|tur.fdd|jD}n |dur5d}nt d|| |_ |j |j |dS)Nc3s|]}|VqdSr2r9)r7valadapterr9r:r;z*RawQuery._execute_query..csi|] \}}||qSr9r9)r7keyrsrtr9r: sz+RawQuery._execute_query..zUnexpected params type: %s) rrOrqopsadapt_unknown_valuerprMroitems RuntimeErrorrPexecuterN)rU connectionrqrMr9rtr:r`s   zRawQuery._execute_queryN)r9)rm __module__ __qualname____doc__rVrrXrerkrnpropertyrqrrr`r9r9r9r:r1Os     c@s`eZdZdZdZeegZdZedfddZ e ddZ e d d Z e d d Zd dZddZddZdddZddZddZdddZddZddZd d!Zd"d#Zd$d%Zd&d'Zdd(d)Zd*d+Zdd,d-Zd.d/Zd0d1Z dd3d4Z!d5d6Z"dd8d9Z#d:d;Z$dd?Z&d@dAZ'dBdCZ(dDdEZ)dFdGZ*ddHdIZ+dJdKZ,dLdMZ-ddNdOZ.dPdQZ/dRdSZ0ddTdUZ1dVdWZ2dXdYZ3dZd[Z4d\d]Z5d^d_Z6d`daZ7dbdcZ8dddeZ9 2  ddfdgZ:dhdiZ;djdkZddpdqZ?drdsZ@ddtduZA  2ddvdwZBdxdyZCeDddzd{ZEeDd|d}ZFdd~dZGddZHddZIddZJdddZKddZLe ddZMddZNddZOddZPddZQddZRddZSddZTdddZUddZVdddZWdddZXddZYddZZddZ[ddZ\ddZ]ddZ^ddZ_ddZ`ddZaddZbddZce ddZde ddZeddZfddZgdS)r0zA single SQL query.T SQLCompilerTcCs||_i|_i|_||_i|_i|_d|_d|_d|_t |_ d|_ d|_ d|_ ||_||_d|_d|_d\|_|_d|_d|_d|_d|_d|_d|_d|_d|_d|_d|_i|_d|_d|_ d|_!d|_"d|_#i|_$d|_%d|_&d|_'d|_(t)df|_*i|_+d|_,d|_-i|_.dS)NTFr9rL)/modelalias_refcount alias_map alias_colsexternal_aliases table_map default_colsdefault_orderingstandard_orderingr< used_aliasesfilter_is_stickysubqueryselectwhere where_classgroup_byorder_byrQrRdistinctdistinct_fieldsselect_for_updateselect_for_update_nowaitselect_for_update_skip_lockedselect_for_update_ofselect_for_no_key_updateselect_related max_depth values_select annotationsannotation_select_mask_annotation_select_cache combinatorcombinator_allcombined_queriesextraextra_select_mask_extra_select_cache extra_tablesextra_order_by frozensetdeferred_loading_filtered_relations explain_queryexplain_formatexplain_options)rUrrrr9r9r:rVsX   zQuery.__init__cCsPt|jdkr|jd}t|ddp|jSt|jdkr&tt|jjSdS)Nrtarget) lenrgetattrfieldrTnextrivalues output_field)rUrr9r9r:rs  zQuery.output_fieldcCst|jp |jp |jSr2)boolrrrrdr9r9r:has_select_fieldszQuery.has_select_fieldscCs|jD]}|SdSr2)rrUaliasr9r9r: base_tables zQuery.base_tablecCs|\}}||S)a( Return the query as a string of SQL with the parameter values substituted in (use sql_with_params() to see the unsubstituted string). Parameter values won't necessarily be quoted correctly, since that is done by the database interface at execution time. )sql_with_params)rUrNrMr9r9r:rr s z Query.__str__cCs|tS)zw Return the query as an SQL string and the parameters that will be substituted into the query. ) get_compilerr as_sqlrdr9r9r:rszQuery.sql_with_paramscCs|}||t|<|S)z4Limit the amount of work when a Query is deepcopied.)rXid)rUmemorjr9r9r: __deepcopy__s zQuery.__deepcopy__NcCs:|dur |dur td|rt|}|j|j|||S)NzNeed either using or connection) ValueErrorrrycompiler)rUrOr~r9r9r:r"s zQuery.get_compilercCs|jjS)z Return the Options instance (the model._meta) from which to start processing. Normally, this is self.model._meta, but it can be changed by subclasses. )r_metardr9r9r:get_meta)zQuery.get_metacCsJt}|j|_|j|_|j|_|j|_|j|_|j|_|j |_|j |_ |j dur:d|_ n|j |_ t dd|j D|_ d|_|j|_|jdur]d|_n|j|_|jdurld|_n|j|_|jdur~t|j|_d|jvr|j|_|j|_|j|_z|`W|StyY|Sw)zi Return a copy of the current Query. A lightweight alternative to to deepcopy(). Ncss|]}|VqdSr2rW)r7queryr9r9r:r;ErvzQuery.clone..F subq_aliases)r$rl__dict__copyrrrrrrXrrrprrrrrrdeepcopyrrrrAttributeError)rUobjr9r9r:rX1sD                    z Query.clonecCsF|}|r|j|kr||_|jst|_d|_t|dr!||S)z Return a copy of the current Query that's ready for another operation. The klass argument changes the type of the Query, e.g. UpdateQuery. F _setup_query)rXrlrr<rhasattrr)rUklassrr9r9r:rds z Query.chaincCs|}|||Sr2)rXchange_aliases)rU change_maprXr9r9r:relabeled_cloness zQuery.relabeled_clonecCs|jsd}|||Sr2rget_col)rUrrrr9r9r:_get_colxs zQuery._get_colc Cs|}g}|D]h}t|tr||qt|ttfr*|||\}}||q|jD]\}}||ur>t||}n-q/t|t sJ|j rc|j sc|d7}d|}||j |<| |gt||}n|||\}}||q||||fS)Nrz__col%d)get_source_expressionsrBrappendr+r rewrite_colsrTr{rcontains_aggregate is_summaryrappend_annotation_maskset_source_expressions) rU annotationcol_cnt orig_exprs new_exprsexprnew_expr col_aliasselected_annotationr9r9r:r}s.          zQuery.rewrite_colscs|jsiSfdd|jD}t|jts"|js"|s"|js"|jrddl m }| }d|_ ||j |}d|_d|_||j|jdd|jsgtdd |D}|jrd|rd|j jj|f|_d|_d d |jD}d |d <d} t|jD])\} } |j} | jr|| | \} } | ||j| <|j| =| | ||jq||jdkr|js|js|j jj|f|_n |}d|_d|_i|_ |jdd|!d|_d|_|"|} | #t$}|d urd gt%|j}| &|j'}t(| )|f|}t*t+|j|S)zU Return the dictionary with the values of the existing aggregations. csg|] \}}|vr|qSr9r9)r7rradded_aggregate_namesr9r:r_s z)Query.get_aggregation..r)AggregateQueryTFforcecss |] }t|ddr|VqdS)rTN)r)r7rr9r9r:r;s  z(Query.get_aggregation..cSsi|]}|dqS)rr9r7tr9r9r:rxz)Query.get_aggregation..rNr9),rTrr{rBrrp is_slicedrrdjango.db.models.sql.subqueriesrrXrrrrset_annotation_maskclear_orderinganyrrpkrget_initial_aliasrrhrrrrremoverr clear_limitsr execute_sqlr"rget_convertersrrapply_convertersrozip)rUrOrexisting_annotationsr inner_query outer_query"has_existing_aggregate_annotationsrelabelsrr expressionrrrj convertersr9rr:get_aggregationsl          zQuery.get_aggregationcCs>|}|jtdddd||dgd}|durd}|S)zO Perform a COUNT() query using the current filter constraints. *__countT)rrNr)rXadd_annotationrr)rUrOrnumberr9r9r: get_count s zQuery.get_countcCs|jSr2)rrdr9r9r: has_filtersszQuery.has_filterscs|}|js$|jdur |dd|jjjDd|jdd||j r@|j dkr@t j j tfdd|j D|_ |jdd|rN|jd d |d d iddddd|d g|S) NTcs|]}|jVqdSr2r5r6r9r9r:r;zQuery.exists..F allow_aliasesunionc3s|] }|jdVqdS))limitN)exists)r7combined_querylimit_combinedrOr9r:r;"  rr)higha)rXrr add_fieldsrrconcrete_fields set_group_byclear_select_clauserrrrf%supports_slicing_ordering_in_compoundrpr set_limits add_extraset_extra_mask)rUrOrrDr9rr:rs"      z Query.existscCs||}|j|d}|S)NrO)rr has_results)rUrOrDrr9r9r:r$-s  zQuery.has_resultscKs`|}|D]}t|rd|vrtd|dqd|_||_||_|j|d}d|S)Nz--zInvalid option name: .Tr# ) rXEXPLAIN_OPTIONS_PATTERN fullmatchrrrrrjoin)rUrOformatoptionsrD option_namerr9r9r:explain2s z Query.explainc s*j|jks JdjrJdj|jksJdj|jks%Jdi|tk}|r0tntj}t|dd}| fddjDt}t |jd d }|D]4}|j|} | } j | |d } | j tkrw|| || || kr| |<|j|s| qZ| ||j|jO_|j} | j| ||jrÈfd d |jDnd_|tkrԈjr|jrtdj|jt} jd ur| j|jd ur| |j| r| j |j 7_ |j!p j!_!|j"pj"_"d S)aN Merge the 'rhs' query into the current one (with any 'rhs' effects being applied *after* (that is, "to the right of") anything in the current query. 'rhs' is not modified during a call to this function. The 'connector' parameter describes how to connect filters from the 'rhs' query. z4Cannot combine queries on two different base models.z3Cannot combine queries once a slice has been taken.z6Cannot combine a unique query with a non-unique query.z6Cannot combine queries with different distinct fields.Fc3s$|] }j|jtkr|VqdSr2r join_typer)r7jrdr9r:r;gsz Query.combine..rN)reusecg|]}|qSr9rr7colrr9r:r_z!Query.combine..r9zSWhen merging querysets using 'or', you cannot have extra(select=...) on both sides.)#rrrrr'r<rr JoinPromoter add_votesrhrr)r0radddiscardr unref_aliasupdate_join_typesrrrXrelabel_aliasesr set_selectr(rrupdaterr"rrr) rUrhs connector conjunctionr2 joinpromoter rhs_votes rhs_tablesrr) new_aliaswrr9)rrUr:combine@sr                   z Query.combinecCs|j\}}|s dS|}i}|j|jhi}|D]u}|t} |jjj} |} | ddD]5} | } | |jvr;|j| j } | | }t |rH|j } n|j j} | j} t |sZ|| |t|| | jq,| | d}|joo|j }|ru|j n|j}|jj}|| jkr| }t |st|||q|ri}|D]\}}|jjD]}||vr|jjj}t|||qq|D]\}}||vr|||q|D] \}}||||qdS|D]\}}||vr|||q|||<q|D] }||tq|D] \}}||||qdS)a Convert the self.deferred_loading data structure to an alternate data structure, describing the field that *will* be loaded. This is used to compute the columns to select from the database and also by the QuerySet class to work out which fields are being initialized on each model. Models that have all their fields included aren't mentioned in the result, only those that have field restrictions in place. The "target" parameter is the instance that is populated (in place). The "callback" is a function that is called whenever a (model, field) pair need to be added to "target". It accepts three parameters: "target", and the model and list of fields being added for that model. N)rrconcrete_modelrsplitrrrr relation_name get_fieldis_reverse_o2o related_model remote_fieldr; add_to_dict auto_createdr3r{ local_fieldsrAget_parent_list setdefaultr<)rUrcallback field_namesdefer orig_optsseen must_include field_nameparts cur_modelr?r4 old_modelsourceris_reverse_objectrworksetrmr9r9r:deferred_to_datasp             zQuery.deferred_to_dataFcCs|j|}|s|r|d}|j|d7<|dfS|r/d|jt|jdf}||n|dur6|jn|}|g|j|<d|j|<|dfS)a Return a table alias for the given table_name and whether this is a new alias or not. If 'create' is true, a new alias is always created. Otherwise, the most recently created alias for the table (if one exists) is reused. rrF%s%dNT)rgetr alias_prefixrrrr)rU table_namecreatefiltered_relation alias_listrr9r9r: table_aliass    zQuery.table_aliascCs|j|d7<dS)z-Increases the reference count for this alias.rNrrr9r9r: ref_aliasrzQuery.ref_aliasrcCs|j||8<dS)z-Decreases the reference count for this alias.Nro)rUramountr9r9r:r=rzQuery.unref_aliascstr]djjdurqjjdusJjj}|o-j|jtk}jjtk}jjs>|rY|sYjj<fddjDsdSdS)a  Promote recursively the join type of given aliases and its children to an outer join. If 'unconditional' is False, only promote the join if it is nullable or the parent join is an outer join. The children promotion is done to avoid join chains that contain a LOUTER b INNER c. So, if we have currently a INNER b INNER c and a->b is promoted, then we must also promote b->c automatically, or otherwise the promotion of a->b doesn't actually change anything in the query results. rNc3s,|]}j|jkr|vr|VqdSr2)r parent_alias)r7r)raliasesrUr9r:r;=sz&Query.promote_joins..) rhpoprr0rrrnullablepromoteextend)rUrtrr parent_louteralready_louterr9rsr: promote_joins s"    zQuery.promote_joinscCslt|}|r4|d}|j|jtkr0|j||j|<|j|j}|j|jtkr0|||sdSdS)a Change join type from LOUTER to INNER for all joins in aliases. Similarly to promote_joins(), this method must ensure no join chains containing first an outer, then an inner join are generated. If we are demoting b->c join in chain a LOUTER b LOUTER c then we must demote a->b automatically, or otherwise the demotion of b->c doesn't actually change anything in the query results. . rN) rhrurr0rdemoterrrr)rUrtrrrr9r9r: demote_joinsBs     zQuery.demote_joinscCs8|jD]\}}|||d}|||qdS)zp Reset reference counts for aliases so that they match the value passed in `to_counts`. rN)rrr{rhr=)rU to_countsr cur_refcount unref_amountr9r9r:reset_refcountsUszQuery.reset_refcountscs*ts J|jt|jtr$tfdd|jD|_tfdd|jD|_|j o?fdd|j D|_ D]@\}}||j vrOqE|j | }||j |<|j ||j |<|j |=|j |=|j|j}t|D]\}}||kr|||<nqvqEfdd|j D|_dS)z Change the aliases in change_map (which maps old-alias -> new-alias), relabelling any references to them in select columns and the where clause. cr3r9r4r5r7r9r:r_jr8z(Query.change_aliases..cr3r9r4r5r7r9r:r_kr8csi|] \}}||qSr9r4)r7rwr6r7r9r:rxlsz(Query.change_aliases..cs&i|]\}}|||p|vqSr9rh)r7raliasedr7r9r:rxsN)r< isdisjointrrr?rBrrprrr{rrrrrj enumerater)rUr old_aliasrH alias_data table_aliasesposrr9r7r:r^s4       zQuery.change_aliasescsfdd}j|jkrdStd}t|D]\}}|jvr'|_n ||kr/tdqjjg_|jj|_fddtjDdS)a Change the alias prefix to the next letter in the alphabet in a way that the outer query's aliases and this query's aliases will not conflict. Even tables that previously had no alias will get an alias after this call. c3slt}ttjd}|VtdD] }|r |||dn|}t||dD]}d|Vq(d}qdS)a Generate a sequence of characters in alphabetical order: -> 'A', 'B', 'C', ... When the alphabet is finished, the sequence will continue with the Cartesian product: -> 'AA', 'AB', 'AC', ... rN)repeat)r chrordririndexrr))alphabetprefixnseqsrdr9r: prefix_gens  z%Query.bump_prefix..prefix_genNz6Maximum recursion depth exceeded: too many subqueries.cs i|] \}}|dj|fqS)rg)ri)r7rrrdr9r:rxsz%Query.bump_prefix..) risysgetrecursionlimitrrRecursionErrorrrr)rUrrlocal_recursion_limitrrr9rdr: bump_prefixs$     zQuery.bump_prefixcCs4|jr |j}|||S|t|jd}|S)zf Return the first alias for this query, after increasing its reference count. N)rrrpr)r#rdb_tablerr9r9r:rs  zQuery.get_initial_aliascCstdd|jDS)z Return the number of tables in this query with a non-zero reference count. After execution, the reference counts are zeroed, so tables added in compiler will not be seen by this method. cSsg|]}|rdqSrr9)r7rr9r9r:r_z-Query.count_active_tables..)rrrrdr9r9r:count_active_tablesszQuery.count_active_tablesc s|rrfdd|jD}n fdd|jD}|r5j|vr*j}n|d}|||S|jjdjd\}}jrX|jjjtksPj rSt}nt }|_|_|j|<|S)a Return an alias for the 'join', either reusing an existing alias for that join or creating a new one. 'join' is either a sql.datastructures.BaseTable or Join. The 'reuse' parameter can be either None which means all joins are reusable, or it can be a set containing the aliases that can be reused. The 'reuse_with_filtered_relation' parameter is used when computing FilteredRelation instances. A join is always created as LOUTER if the lhs alias is LOUTER to make sure chains like t1 LOUTER t2 INNER t3 aren't generated. All new joins are created as LOUTER if the join is nullable. cs*g|]\}}|vr|jddr|qS)F)with_filtered_relation)equalsr7rr1r)r2r9r:r_s zQuery.join..cs,g|]\}}dus|vr|kr|qSr2r9rrr9r:r_s rKT)rkrl) rr{rnrprjrlr0rrrrvr) rUr)r2reuse_with_filtered_relation reuse_aliases reuse_aliasr_r0r9rr:r)s,     z Query.joinc Cs||vr||S||}|s|S|}|D]1}||vr#|j}||}q|j|s,|j}q||}||jg||} |j}| jd}||<q|pL|dS)a} Make sure the given 'model' is joined in the query. If 'model' isn't a parent of 'opts' or if it is None this method is a no-op. The 'alias' is the root alias for starting the join, 'seen' is a dict of model -> alias of existing joins. It must also contain a mapping of None -> some alias. This will be returned in the no-op case. rKN)get_base_chainrparentsget_ancestor_link setup_joinsr4rI) rUr?rrr\r curr_opts int_model link_field join_infor9r9r:join_parent_models&     zQuery.join_parent_modelcCst|r tddS)NzbColumn aliases cannot contain whitespace characters, quotation marks, semicolons, or SQL comments.)FORBIDDEN_ALIAS_PATTERNsearchrrr9r9r: check_aliass zQuery.check_aliascCsT|||j|dd|d}|r||gn |t|j|h||j|<dS)z0Add a single annotation expression to the Query.TN) allow_joinsr2 summarize)rresolve_expressionrrr<rT differencer)rUrrrrr9r9r:r "s  zQuery.add_annotationc Os|}||d|_|jdkr"|jdur"|js"|js"|jdd|jj |g|Ri||j D]!\}}|j |g|Ri|}t |drP|j |j ||j |<q4|j D]\}} t| trl| jjjj|kpvt| tov| j| jk|j |<q[|S)NTrrr)rXrrrQrRrrrrrrr{rrrArrBr% join_fieldrQrrr#rjrn) rUrargskwargsrXrwvalueresolvedrtabler9r9r:r-s(     zQuery.resolve_expressioncs0tjjj}fddj|ddDS)Ncsg|] }|jjvr|qSr9)rrr5rdr9r:r_Hs  z+Query.get_external_cols..Tinclude_external)rrrrrA _gen_cols)rUexprsr9rdr:get_external_colsFs  zQuery.get_external_colscCs4|rt||gS|}tdd|Dr|gS|S)Ncsr r2)possibly_multivaluedr5r9r9r:r;Qrz*Query.get_group_by_cols..)rrr)rUr external_colsr9r9r:get_group_by_colsMs  zQuery.get_group_by_colscCs*|j|d\}}|jrd|}||fS)N)r~z(%s))rrr)rUrr~rNrMr9r9r:rUsz Query.as_sqlcsht|dr|jd}|St|ttfr2fdd|D}t|}t|dr.||S||S|S)Nr)r2rc3s|] }|VqdSr2)resolve_lookup_value)r7 sub_valuer can_reuserUr9r:r;crz-Query.resolve_lookup_value.._make)rrrBrhrptype)rUrrrrtype_r9rr:r[s  zQuery.resolve_lookup_valuec Cs|t}|jrt||j\}}|r|d|fS|||\}}}}|dt|t|}t|dkrC|sCtd||jj f||dfS)zX Solve the lookup type from the lookup (e.g.: 'foobar__id__icontains'). r9rrz"Invalid lookup "%s" for model %s".F) rMrrr names_to_pathrrr rrm) rUlookuplookup_splittedrexpression_lookupsrr lookup_parts field_partsr9r9r:solve_lookup_typems   zQuery.solve_lookup_typecCs4t|drt|jj||std||jfdSdS)z Check whether the object passed while querying is of the correct type. If not, raise a ValueError specifying the wrong object. rz)Cannot query "%s": Must be "%s" instance.N)rrrrr object_name)rUrr?rr9r9r:check_query_object_types zQuery.check_query_object_typecCs|jr=t|tr|jst|j||std|jjj|jft |dr,| |||dSt |dr?|D] }| |||q3dSdSdS)z3Check the type of object passed to query relations.z6Cannot use QuerySet for "%s": Use a QuerySet for "%s".rrkN) is_relationrBr0rrrrrrrr)rUrrr?vr9r9r:check_related_objectss"   zQuery.check_related_objectscCsPt|drt|ddst|jjdt|dr$|D] }||qdSdS)z>Raise an error if expression cannot be used in a WHERE clause.r filterableTz$ is disallowed in the filter clause.rN)rrr rlrmrcheck_filterable)rUrrr9r9r:rs     zQuery.check_filterablec Cs|pdg^}}|D]}|||}q ||}|s6|jjr%td||||}d}||}|s6dS|||}|jdurS|jsS|dvrKtd|d|dSt t j j rj|dkrj|jdkrj|d|dS|S) a1 Try to extract transforms and lookup from given lhs. The lhs value is something that works like SQLExpression. The rhs value is what the lookup is going to compare against. The lookups is a list of names to extract using get_lookup() and get_transform(). exact$Related Field got invalid lookup: {}N)riexactz Cannot use None as a query valueisnullTr) try_transform get_lookuprrr r*rBcan_use_none_as_rhsrrr rf!interprets_empty_strings_as_nulls) rUlookupslhsrB transforms lookup_namer4 lookup_classrr9r9r: build_lookups*      zQuery.build_lookupcCsZ||}|r ||S|jj}t||}|r!dd|}nd}td||j|f)z Helper method for build_lookup(). Try to fetch and initialize a transform for name parameter from lhs. z, perhaps you meant %s?z or r%zCUnsupported lookup '%s' for %s or join on the field not permitted%s) get_transformrrldifflibget_close_matches get_lookupsr)r rm)rUrr4transform_classrsuggested_lookups suggestionr9r9r:rs  zQuery.try_transformc  st|tr tdt|tr|j|||||||dSt|drDt|dds)td|dg|j ||dd } | } | | t | gfS|\} } | sPtd | | | \} }}|r_|||skt|d krktd |j|| ||} fd d|jD}|r|| | } |r|| || } | | t | gfS|}|}| p| }z#|j||||||d}t| trt| } ||j| |j|j|_Wnty}z||||j WYd}~Sd}~ww|!|j|"|j#|j|j$\}}}|dur |!||jj%r=t| }|d kr!td&| dt|d kr3|'|d|j|}nt(|||j#|j}n |'|d|j|}|| || } | j)}| | t |dkod| j*d uod| }|r|dkss| j*dur| j*durd }|dkr|+|ds|j,|dj-t.kr|d/d}|'|d|j#d|}| ||dt t| t0r|+| j1r| j1/d}| || dt | |s|fSdfS)a Build a WhereNode for a single filter clause but don't add it to this Query. Query.add_q() will then add this filter to the where Node. The 'branch_negated' tells us if the current branch contains any negations. This will be used to determine if subqueries are needed. The 'current_negated' is used to determine if the current filter is negated or not and this will be used to determine if IS NULL filtering is needed. The difference between current_negated and branch_negated is that branch_negated is set on first negation, but current_negated is flipped for each negation. Note that add_filter will not do any negating itself, that is done upper in the code by add_q(). The 'can_reuse' is a set of reusable joins for multijoins. If 'reuse_with_filtered_relation' is True, then only joins in can_reuse will be reused. The method will create a filter clause that can be added to the current query. However, if the filter isn't added to the query then the caller is responsible for unreffing the joins used. z"Cannot parse keyword query as dict)branch_negatedcurrent_negatedrr split_subqrr conditionalFz3Cannot filter against a non-conditional expression.rrTzCannot parse keyword query %rr7Joined field references are not permitted in this querycs$h|]\}}||dkr|qSr[rr7kr pre_joinsr9r: .s$z%Query.build_filter..)r allow_manyrNrrrrKr9)2rBror r_add_qrr TypeErrorrrrr;r'rrrrrrr{rrrrrhrrGr?rI _lookup_joinsr& split_excludenames_with_pathrA trim_joinsrHrJrr*rrrrB is_nullablerr0rrrr)rU filter_exprrrrrrrr conditionclauseargrrr_reffed_expression used_joinsr?rrrerH join_list num_lookupsr6 lookup_type require_outerrr9rr: build_filters                   (   zQuery.build_filtercCs$|tdi|d|didS)Nrrr9)add_qr)rU filter_clauser9r9r: add_filters$zQuery.add_filtercsFfddjD}|j\}}|rj|t|dS)zo A preprocessor for the internal _add_q(). Responsible for doing final join promotion. cs h|] }j|jtkr|qSr9r/)r7rrdr9r:rs zQuery.add_q..N)rrrrr;r'r})rUq_objectexisting_innerrrr9rdr:rs  z Query.add_qcCs|j|dddS)NFrr)r )rUrr9r9r: build_whererZzQuery.build_wherec Cs|j}||jA}|p |j}|j||jd} t|jt|j|} |jD]} |j| ||||||d\} } | | | r?| | |q"| |} | | fS)z%Add a Q-object to the current filter.rCnegated)rrrrrr) rCrrr9rrAr r:r;r>)rUrrrrrrrrC target_clauserErE child_clause needed_innerr9r9r:rs&      z Query._add_qc Cs|j}||jN}|p |j}|j||jd}|jD]%}t|tr)|j||||d}n|j||||dddd\}} |||q|S)z4Add a FilteredRelation object to the current filter.r)r2rrTF)rrrrrr) rCrrrArBr/build_filtered_relation_qr r;) rUrr2rrrCrrErrr9r9r:rs$     zQuery.build_filtered_relation_qcCs||_tt|j}||j\}}}|rtd|jt|D]>}||\}} }|s.dnd} | d| } t| D]"\} } t || krU|| | krTtd|j|fq;td||jfq ||j |j<dS)NzAFilteredRelation's relation_name cannot contain lookups (got %r).r.rzOFilteredRelation's condition doesn't support relations outside the %r (got %r).zlFilteredRelation's condition doesn't support nested relations deeper than the relation_name (got %r for %r).) rrorCrrrNrrrrr)rUrlrrrelation_lookup_partsrelation_field_partsrrrlookup_field_partsshiftlookup_field_pathidxlookup_field_partr9r9r:add_filtered_relations:    zQuery.add_filtered_relationc Csgg}}t|D];\}}|gf} |dkr|jj}d} d} z||} WnJtyo||jvr8|j|j} n5||jvrm|dkrm|j|} t| j vrg| j t} | | |||\} } }}| | ddn|| j } Ynw| dur| j r| jstd|z| jjj}Wn0tyd}Yn&w|d8}|dks|rtgt||j|j}td|d|fn||jur||}|r| || d ||dj}t| d r(| | }|s t|D]!\}}|jr| d |d|d|| t|d|q|d}| ||j}|j}|j}| d ||| q | }| f}|rE|dt |krEtd ||d|f|||||ddfS) a Walk the list of names and turns them into PathInfo tuples. A single name in 'names' can generate multiple PathInfos (m2m, for example). 'names' is the path of names to travel, 'opts' is the model Options we start the name resolving from, 'allow_many' is as for setup_joins(). If fail_on_missing is set to True, then a name that can't be resolved will generate a FieldError. Return a list of PathInfo tuples. In addition return the final field (the last used join field) and target (which is a field guaranteed to contain the same value as the final field). Finally, return those names that weren't found (which are likely transforms and the final lookup). rNrrKzField %r does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.rz7Cannot resolve keyword '%s' into field. Choices are: %s, get_path_infozACannot resolve keyword %r into field. Join on '%s' not permitted.)!rrr4rOr rTrrrrNrMrrxrrQr rrrLrsortedr@r)get_path_to_parentto_optsrr#m2mrr&r target_fieldsr)rUnamesr?rfail_on_missingrJrrr4cur_names_with_pathrrlr_filtered_relation_pathrr availablepath_to_parent pathinfos inner_posplastrGrHr9r9r:rs                     zQuery.names_to_pathc sn|g}fdd}dtt|ddD]5} zj|d| ||dd\} } } WntyA} z | dkr5| WYd} ~ qd} ~ ww|| d}|D]}fd d }tj|||d }qK| D]M}|jrn|j}|j}nd}d}|j }|j r |j }nd}t |j||t|j ||d }|js|r|nd}j|||d }|||r|dd|_q`t| ||| |S)a Compute the necessary table joins for the passage through the fields given in 'names'. 'opts' is the Options class for the current model (which gives the table we are starting from), 'alias' is the alias for the table to start the joining from. The 'can_reuse' defines the reverse foreign key joins we can reuse. It can be None in which case all joins are reusable or a set of aliases that can be reused. Note that non-reverse foreign keys are always reusable when using setup_joins(). The 'reuse_with_filtered_relation' can be used to force 'can_reuse' parameter and force the relation on the given connections. If 'allow_many' is False, then any reverse foreign key seen will generate a MultiJoin exception. Return the final field involved in the joins, the target field (used for any 'where' constraint), the final 'opts' value, the joins, the field path traveled to generate the joins, and a transform function that takes a field and alias and is equivalent to `field.get_col(alias)` in the simple case but wraps field transforms if they were included in names. The target field is the field containing the concrete value. Final field can be something different, for example foreign key pointing to that value. Final field is needed for example in some value conversions (convert 'obj' in fk__id=obj to pk val using the foreign key field for example). csjsd}||Sr2r)rrrdr9r:final_transformerms z,Query.setup_joins..final_transformerNrrKT)r*rcs<z |||}||WStyttrrwr2)rr rBr)rrr4previouswrappedrGlast_field_exceptionrUr9r: transforms  z$Query.setup_joins..transform)r4r4)rl)r2r)rangerrr functoolspartialrlrXrr&directrrr%rrr'r)rrJrF)rUr)r?rrrrrIr3pivotrJrHrestexcrr4r8r)rlrnrvr~r2r9r6r:rGsV     zQuery.setup_joinscs|dd}tt|D]H\}}t|dks|jsn:|jr n5dd|jjD}dd|D|s7nfdd|jjDt fdd |D}| | q ||d |fS) a The 'target' parameter is the final field being joined to, 'joins' is the full list of join aliases. The 'path' contain the PathInfos used to create the joins. Return the final target field and table alias and the new active joins. Always trim any direct join if the target column is already in the previous table. Can't trim reverse joins as it's unknown if there's anything on the other side of the join. NrcSh|]}|jqSr9columnrr9r9r:rrz#Query.trim_joins..cSr@r9rArr9r9r:rrcs*i|]}|djvr|dj|dqS)rrrAr7r) cur_targetsr9r:rxs*z$Query.trim_joins..c3s|]}|jVqdSr2rAr) targets_dictr9r:r;z#Query.trim_joins..rK) rreversedrr<rlrforeign_related_fieldsissubsetrelated_fieldsrpr=ru)rUrHrIrJrinfo join_targetsr9)rErFr:rs  zQuery.trim_joinsccs^|D])}t|tr|Vq|r tt|ddr |EdHq|j||dEdHqdS)Nrr)rBrcallablerrrr)clsrrrr9r9r:rs zQuery._gen_colsccs dd||DEdHdS)Ncsr r2r)r7rr9r9r:r;rz)Query._gen_col_aliases..)r)rOrr9r9r:_gen_col_aliasesszQuery._gen_col_aliasesc Cs:|j|}|dur8|s!||gD]}t|j|tr tdq|r6||jvr.td|t||j|S|S| t }|j|d}|durZ|ddD]}| ||}qO|S|j || ||d} || j| j| j\} } } |st| dkrtdt| dkrtd| | d| }|dur|| |S)NrzCCannot aggregate over the '%s' alias. Use annotate() to promote it.rr)rz?Referencing multicolumn fields with F() objects isn't supported)rrhrQrBrr%r rTrrMrrrrrrrHrIrJrrKrA) rUr4rr2rrr field_listr8rrH final_aliasr r9r9r: resolve_refsD     zQuery.resolve_refcCsN|\}}t|tr|t|f}n t|tr|t|jf}t|j}|j|_|||jdd| |\}}|j d} | j } | j } | |vrp| jj j} ||| d} | | |j dj | | }|j|td|j| <| d} | | t|}|j|t|t|\}}|r|jd|dfdd|d\}}||t||fS)a When doing an exclude against any kind of N-to-many relation, we need to use a subquery. This method constructs the nested query, given the original exclude filter (filter_expr) and the portion up to the first N-to-many relation field. For example, if the origin filter is ~Q(child__name='foo'), filter_expr is ('child__name', 'foo') and can_reuse is a set of joins usable for filters in the original query. We will turn this into equivalent of: WHERE NOT EXISTS( SELECT 1 FROM child WHERE name = 'foo' AND child.parent_id = parent.id LIMIT 1 ) Trrrz %s__isnull)rrr)rBrrr4r0rrrr trim_startrrrrrrrrrr;r'rrr rr()rUrrr filter_lhs filter_rhsrtrimmed_prefixcontains_louterr6 select_fieldrrrrrror_null_conditionrr9r9r:rsB             zQuery.split_excludecCs(|jtt|jD]}|q dSr2)rr;r*r'r set_empty)rUrr9r9r:r\Ks  zQuery.set_emptycCstdd|jjDS)Ncss|]}t|tVqdSr2)rBr*)r7cr9r9r:r;QrGz!Query.is_empty..)rrrArdr9r9r:is_emptyPszQuery.is_emptycCs|dur|jdurt|j|j||_n|j||_|dur4|jdur.t|j|j||_n|j||_|j|jkr@|dSdS)a Adjust the limits on the rows retrieved. Use low/high to set these, as it makes it more Pythonic to read and write. When the SQL query is created, convert them to the appropriate offset and limit values. Apply any limits passed in here to the existing constraints. Add low to the current low value and clamp both to any existing high value. N)rRminrQr\)rUlowrr9r9r:r Ss      zQuery.set_limitscCsd\|_|_dS)zClear any existing limits.rLNrQrRrdr9r9r:rjzQuery.clear_limitscCs|jdkp |jduS)Nrrardr9r9r:rnszQuery.is_slicedcCs|jduo |j|jdkS)Nr)rRrQrdr9r9r: has_limit_onerszQuery.has_limit_onecCs|j S)z Return True if adding filters to this instance is still possible. Typically, this means no limits or offsets have been put on the results. )rrdr9r9r: can_filterurzQuery.can_filtercCs*d|_d|_d|_|d|ddS)z%Remove all fields from SELECT clause.r9FN)rrrr"rrdr9r9r:r}s  zQuery.clear_select_clausecCsd|_d|_dS)z Clear the list of fields to select (but not extra_select columns). Some queryset types completely replace any existing list of select columns. r9Nrrrdr9r9r:clear_select_fieldss zQuery.clear_select_fieldscCs$|j|f7_|j|f7_dSr2re)rUr6r4r9r9r:add_select_colszQuery.add_select_colcCsd|_t||_dSNF)rrpr)rUcolsr9r9r:r@szQuery.set_selectcGs||_d|_dS)zW Add and resolve the given fields to the query's "distinct on" clause. TN)rr)rUrYr9r9r:add_distinct_fieldss zQuery.add_distinct_fieldsc Cs|}|}z;g}|D])}|j|t|||d}||j|j|j\}} } |D] } | | | | q*q |rA| |WdSWdSt yPt d|t yt|vr[||jvrft d|tgt||j|j|j} t d|d| fw)zu Add the given (model) fields to the select set. Add the field names in the order specified. )rzInvalid field name: '%s'z;Cannot select the '%s' alias. Use annotate() to promote it.z5Cannot resolve keyword %r into field. Choices are: %sr"N)rrrrMrrrHrIrJrrKr@r&r rr$r@rrTrr)) rUrY allow_m2mrr?rir4rrHrSrIrr)r9r9r:rsR      zQuery.add_fieldscGsg}|D]\}t|trJd|vrt|rtjd|tddq|dkr$q|dr/|dd}||jvr5q|j r>||j vr>q| | t |j jn t|d sT||t|d d r`td |q|ritd ||rt|j|7_dSd |_dS)a8 Add items from the 'ordering' sequence to the query's "order by" clause. These items are either field names (not column names) -- possibly with a direction prefix ('-' or '?') -- or OrderBy expressions. If 'ordering' is empty, clear all ordering from the query. r%z~Passing column raw column aliases to order_by() is deprecated. Wrap %r in a RawSQL expression before passing it to order_by().)category stacklevel?-rNrrFz[Using an aggregate in order_by() without also including it in annotate() is not allowed: %szInvalid order_by arguments: %s)rBstrr!matchwarningswarnr, startswithrrrrMrrrrrrr rr)rUorderingerrorsitemr9r9r: add_orderingsF          zQuery.add_orderingcCs8|s |js |js |jr dSd|_d|_|rd|_dSdS)a Remove any ordering settings if the current query allows it without side effects, set 'force' to True to clear the ordering regardless. If 'clear_default' is True, there will be no ordering in the resulting query (not even the model's default). Nr9F)rrrrrr)rUr clear_defaultr9r9r:rs zQuery.clear_orderingc Cs|r/t}t}t|jddD]}|jj}||vr.|dd|jjD| |qt|j }|j rv|j D]9\}}t |j} d| jvrb|j} d| j| jf} tj| td|} n|rh||vrjd}|j|d} || q.rzI`alias=None` must be added to the signature of %s.%s.get_group_by_cols().)rmrP)r<rhrrrrQrArlocal_concrete_fieldsr;rrTr{inspect signaturer parametersrlrrrsrtr,rxrpr) rUr column_names seen_modelsr)rrrrr}annotation_classmsg group_by_colsr9r9r:rs6           zQuery.set_group_bycCsLt|jtr i}n|j}|D]}|}|tD]}||i}qq||_dS)z Set up the select_related data structure so that we only select certain related models (as opposed to all models, when self.select_related=True). N)rBrrrMrrW)rUfields field_dictrdpartr9r9r:add_select_related-s  zQuery.add_select_relatedc Cs|rWi}|r t|}ntg}|D]=\} } || t| } g} | d} | dkrJ| dks7| | ddkr>| t|| d| d} | dks+| | f|| <q|j||s[|re|j t ||t |rp|j t|7_ |rw||_dSdS)zm Add data to the various extra_* attributes for user-created additions to the query. z%srKrr%r.N)rir{rrqfindrrrrArr;r)r'rrpr) rUr select_paramsrrMtablesr select_pairs param_iterr4entry entry_paramsrr9r9r:r!=s0     zQuery.add_extracCstdf|_dS)z0Remove any fields from the deferred loading set.TN)rrrdr9r9r:clear_deferred_loading^rbzQuery.clear_deferred_loadingcCs6|j\}}|r||df|_dS||df|_dS)aj Add the given list of model field names to the set of fields to exclude from loading from the database when automatic column selection is done. Add the new field names to any existing field names that are deferred (or removed from any existing field names that are marked as the only ones for immediate loading). TFN)rrrrUrYexistingrZr9r9r:add_deferred_loadingbs zQuery.add_deferred_loadingcCs`|j\}}t|}d|vr|d||jj|r'||df|_dSt|df|_dS)a  Add the given list of model field names to the set of fields to retrieve when the SQL is executed ("immediate loading" fields). The field names replace any existing immediate loading field names. If there are field names already specified for deferred loading, remove those names from the new field_names before storing the new names for immediate loading. (That is, immediate loading overrides any existing immediate values, but respects existing deferrals.) rFN) rr<rr;rrr4rrrr9r9r:add_immediate_loadingvs  zQuery.add_immediate_loadingcCs8z|jWStyi}|||j||_|YSw)aF If any fields are marked to be deferred, return a dictionary mapping models to a set of names in those fields that will be loaded. If a model is not in the returned dictionary, none of its fields are deferred. If no fields are marked for deferral, return an empty dictionary. )_loaded_field_names_cacherrfget_loaded_field_names_cb)rU collectionr9r9r:get_loaded_field_namess  zQuery.get_loaded_field_namescCsdd|D||<dS)z,Callback used by get_deferred_field_names().cSr@r9rr6r9r9r:rrz2Query.get_loaded_field_names_cb..Nr9)rUrrrr9r9r:rrzQuery.get_loaded_field_names_cbcC$|durd|_nt||_d|_dS)z@Set the mask of annotations that will be returned by the SELECT.N)rr<rrUr)r9r9r:rs  zQuery.set_annotation_maskcCs$|jdur||j|dSdSr2)rrrrr9r9r:rs zQuery.append_annotation_maskcCr)z Set the mask of extra select items that will be returned by SELECT. Don't remove them from the Query since they might be used later. N)rr<rrr9r9r:r"s  zQuery.set_extra_maskc Csxd|_|||r^|D]}||qg}g}g}|js(|js(t|}n#d|_|D]}||jvr:| |q-||j vrE| |q-| |q-| || |t |||}ndd|jjjD}t |}|jdur|dd|jjjDd|jdd|n%|jrg}|jD]} t| tr| j|vr|j| j} | | qt||_t||_||ddS)NFcSsg|]}|jqSr9rr6r9r9r:r_rz$Query.set_values..Tcsr r2rr6r9r9r:r;rz#Query.set_values..r)rrrfrrrrhrrSrrTr"rrrrrrrrrBrrefsrpr) rUrrrY extra_namesannotation_namesr8selectedrrr9r9r: set_valuessH                  zQuery.set_valuescsJjdurjSjs iSjdur"fddjD_jSjS)z Return the dictionary of aggregate columns that are not masked and should be used in the SELECT clause. Cache this result for performance. Nc i|] \}}|jvr||qSr9)rrrdr9r:rx  z+Query.annotation_select..)rrrr{rdr9rdr:rTs   zQuery.annotation_selectcsJjdurjSjs iSjdur"fddjD_jSjS)Ncrr9)rrrdr9r:rx rz&Query.extra_select..)rrrr{rdr9rdr:rS s   zQuery.extra_selectcsg}|D] \}}||qd}fddjD}t|D] \}}|jr'nj||djtkr5d}||} | q|jj} |} g} |D]\} }| t |dkrWn | | | t |8} qI| | j dj t | } j||d}|jtkr|jsdd| jD}||d||| jd||d}|rj|tn d d| jD}||jD]}j|dkrtj|j|j|<nqfd d|D| |fS) a Trim joins from the start of the join path. The candidates for trim are the PathInfos in names_with_path structure that are m2m joins. Also set the select column so the start matches the join. This method is meant to be used for generating the subquery joins & cols in split_exclude(). Return a lookup usable for doing outerq.filter(lookup=self) and a boolean indicating if the joins in the prefix contain a LEFT OUTER join. _Fcs$g|]}|jvs|jkr|qSr9)rrrrdr9r:r_% s z$Query.trim_start..rTrcSg|]}|dqSr[r9rCr9r9r:r_E rNcSrrr9rCr9r9r:r_P rcr3r9)rr6) select_aliasr9r:r_X r8)rxrrr'r0rr=rrrrrIr4rr)rlrKget_extra_restrictionrrr;r'rr#rjr@)rUr all_pathsrpathsrY lookup_tables trimmed_pathsrJrrpaths_in_prefixrXr4 first_join select_fieldsextra_restrictionrr9)rrUr:rU s\          zQuery.trim_startcCsttjjo|jp |jS)a Check if the given field should be treated as nullable. Some backends treat '' as null and Django treats such fields as nullable for those backends. In such situations field.null can be False even if we should treat the field as nullable. )rr rfrempty_strings_allowednull)rUrr9r9r:r[ s zQuery.is_nullable)NNr2)T)FNrrh)FT)FFNTTFT)FFTTT)FF)TF)NTF)F)TNF)hrmrrrrirrrr+rVrrrr-rrrrrrrrXrrrrrr r rr$r-rJrfrnrpr=r{r}rrrrrr)rrr rrrrrrrrrrrr rrrrrr!rrr classmethodrrQrTrr\r^r rrrcrdrrfrgr@rjrryrrrr!rrrrrrrr"rrTrSrUrr9r9r9r:r0s X      34X  i V " '1 0!    -   g h   ,C    + . )! 3   JASCcCs4t|}|ddkr|dd|dfS||dfS)a Return the field name and direction for an order specification. For example, '-foo' is returned as ('foo', 'DESC'). The 'default' param is used to indicate which way no prefix (or a '+' prefix) should sort. The '-' prefix always sorts the opposite way. rrprN)r )rdefaultdirnr9r9r: get_order_dirn s  rcCs(||vr |||dS|h||<dS)z^ Add "value" to the set of values for "key", whether or not "key" already exists. N)r;)datarwrr9r9r:rS| srScCs|jo |jo |j S)z Check if the given field is reverse-o2o. The field is expected to be some sort of relation field or related object. )r one_to_oner3)rr9r9r:rP srPc@s(eZdZdZddZddZddZdS) r9z] A class to abstract away join promotion problems for complex filter conditions. cCsD||_||_|jr|tkrt|_nt|_n|j|_||_t|_dSr2)rCrr'r(effective_connector num_childrenrvotes)rUrCrrr9r9r:rV s zJoinPromoter.__init__cCs|j|dS)z` Add single vote per item to self.votes. Parameter can be any iterable. N)rrA)rUrr9r9r:r: szJoinPromoter.add_votescCs~t}t}|jD]'\}}|jdkr||jkr|||jdks-|jdkr2||jkr2||q |||||S)a Change join types so that the generated query is as efficient as possible, but still correct. So, change as many joins as possible to INNER, but don't make OUTER joins INNER if that could remove results from the query. r(r')r<rr{rrr;r{r})rUr to_promote to_demoterrr9r9r:r> s     zJoinPromoter.update_join_typesN)rmrrrrVr:r>r9r9r9r:r9 s  r9)r)Urrrr:r|rrs collectionsrrcollections.abcrr itertoolsrrrstringr django.core.exceptionsr r django.dbr r rdjango.db.models.aggregatesrdjango.db.models.constantsrdjango.db.models.expressionsrrrrrrrdjango.db.models.fieldsr'django.db.models.fields.related_lookupsrdjango.db.models.lookupsrdjango.db.models.query_utilsrrrdjango.db.models.sql.constantsrrr r!r"#django.db.models.sql.datastructuresr#r$r%r&django.db.models.sql.wherer'r(r)r*r+django.utils.deprecationr,django.utils.functionalr-django.utils.regex_helperr.django.utils.treer/__all__rr'r@rCrFr1r0rrSrPr9r9r9r9r:sv   $       J f