U
    Ha*"                     @   sp   d Z ddlmZ ddlmZ ddlmZ dZdZG dd dej	Z
G d	d
 d
ZG dd dZG dd dZdS )zG
Code to manage the creation and SQL rendering of 'where' constraints.
    EmptyResultSet)tree)cached_propertyANDORc                   @   s   e Zd ZdZeZdZdZd'ddZdd Z	d(d	d
Z
dd Zdd Zdd Zdd Zdd Zdd Zedd Zedd Zedd Zedd Zedd  Zed!d" Zed#d$ Zd%d& ZdS ))	WhereNodea  
    An SQL WHERE clause.

    The class is tied to the Query class that created it (in order to create
    the correct SQL).

    A child is usually an expression producing boolean values. Most likely the
    expression is a Lookup instance.

    However, a child could also be any class with as_sql() and either
    relabeled_clone() method or relabel_aliases() and clone() methods and
    contains_aggregate attribute.
    FTc                 C   s   | j s| dfS || jA }|r&| jtkp4| o4| jtk}|rH| j rHd| fS g }g }| jD ]^}t|dr||\}}|dk	r|| |dk	r|| qV|j r|| qV|| qV|r| 	|| j| jnd}	|r| 	|| j| jnd}
|
|	fS )z
        Return two possibly None nodes: one for those parts of self that
        should be included in the WHERE clause and one for those parts of
        self that must be included in the HAVING clause.
        Nsplit_having)
contains_aggregatenegated	connectorr   r   childrenhasattrr	   append	__class__)selfr   Z
in_negatedZmay_need_splitZwhere_partsZhaving_partscZ
where_partZhaving_partZhaving_nodeZ
where_node r   >/tmp/pip-unpacked-wheel-3jxiddxt/django/db/models/sql/where.pyr	       s.    




zWhereNode.split_havingc              	   C   s"  g }g }| j tkr$t| jd }}ndt| j }}| jD ]}z||\}}	W n tk
rl   |d8 }Y n$X |r|| ||	 n|d8 }|dkr| jrdg f  S t|dkr:| jrtq:dg f  S q:d| j  }
|
	|}|r| j rd| }nt|dks| j
rd| }||fS )a  
        Return the SQL version of the where clause and the value to be
        substituted in. Return '', [] if this node matches everything,
        None, [] if this node is empty, and raise EmptyResultSet if this
        node can't match anything.
           r    z %s zNOT (%s)(%s))r   r   lenr   compiler   r   extendr   joinresolved)r   compiler
connectionresultZresult_paramsZfull_neededZempty_neededchildsqlparamsconnZ
sql_stringr   r   r   as_sqlA   s<    





zWhereNode.as_sqlNc                 C   s"   g }| j D ]}||  q
|S N)r   r   get_group_by_cols)r   aliascolsr    r   r   r   r&   u   s    
zWhereNode.get_group_by_colsc                 C   s   | j d d  S r%   )r   r   r   r   r   get_source_expressions{   s    z WhereNode.get_source_expressionsc                 C   s    t |t | jkst|| _d S r%   )r   r   AssertionError)r   r   r   r   r   set_source_expressions~   s    z WhereNode.set_source_expressionsc                 C   sH   t | jD ]8\}}t|dr(|| q
t|dr
||| j|< q
dS )z
        Relabel the alias values of any children. 'change_map' is a dictionary
        mapping old (current) alias values to the new values.
        relabel_aliasesrelabeled_cloneN)	enumerater   r   r-   r.   )r   
change_mapposr    r   r   r   r-      s
    

zWhereNode.relabel_aliasesc                 C   sN   | j jg | j| jd}| jD ],}t|dr<|j|  q|j| q|S )z
        Create a clone of the tree. Must only be called on root nodes (nodes
        with empty subtree_parents). Childs must be either (Constraint, lookup,
        value) tuples, or objects supporting .clone().
        )r   r   r   clone)r   Z_new_instancer   r   r   r   r   r2   )r   r2   r    r   r   r   r2      s      

zWhereNode.clonec                 C   s   |   }|| |S r%   )r2   r-   )r   r0   r2   r   r   r   r.      s    
zWhereNode.relabeled_clonec                 C   s   |   S r%   )r2   r)   r   r   r   copy   s    zWhereNode.copyc                    s*   t |tjr$t fdd|jD S |jS )Nc                 3   s   | ]}  |V  qd S r%   _contains_aggregate.0r   clsr   r   	<genexpr>   s     z0WhereNode._contains_aggregate.<locals>.<genexpr>)
isinstancer   Nodeanyr   r
   r9   objr   r8   r   r5      s    zWhereNode._contains_aggregatec                 C   s
   |  | S r%   r4   r)   r   r   r   r
      s    zWhereNode.contains_aggregatec                    s*   t |tjr$t fdd|jD S |jS )Nc                 3   s   | ]}  |V  qd S r%   _contains_over_clauser6   r8   r   r   r:      s     z2WhereNode._contains_over_clause.<locals>.<genexpr>)r;   r   r<   r=   r   contains_over_clauser>   r   r8   r   rA      s    zWhereNode._contains_over_clausec                 C   s
   |  | S r%   r@   r)   r   r   r   rB      s    zWhereNode.contains_over_clausec                 C   s   t dd | jD S )Nc                 s   s   | ]}|j V  qd S r%   )
is_summary)r7   r    r   r   r   r:      s     z'WhereNode.is_summary.<locals>.<genexpr>)r=   r   r)   r   r   r   rC      s    zWhereNode.is_summaryc                 O   s    t | dr| j|f||} | S )Nresolve_expression)r   rD   )exprqueryargskwargsr   r   r   _resolve_leaf   s    
zWhereNode._resolve_leafc                 O   sr   t |dr*|jD ]}| j||f|| qt |drL| j|j|f|||_t |drn| j|j|f|||_d S )Nr   lhsrhs)r   r   _resolve_noderI   rJ   rK   )r9   noderF   rG   rH   r    r   r   r   rL      s    



zWhereNode._resolve_nodec                 O   s$   |   }|j|f|| d|_|S )NT)r2   rL   r   )r   rG   rH   r2   r   r   r   rD      s    zWhereNode.resolve_expression)F)N)__name__
__module____qualname____doc__r   defaultr   Zconditionalr	   r$   r&   r*   r,   r-   r2   r.   r3   classmethodr5   r   r
   rA   rB   propertyrC   staticmethodrI   rL   rD   r   r   r   r   r      s8   
!4







	r   c                   @   s   e Zd ZdZdZdddZdS )NothingNodezA node that matches nothing.FNc                 C   s   t d S r%   r   )r   r   r   r   r   r   r$      s    zNothingNode.as_sql)NN)rN   rO   rP   rQ   r
   r$   r   r   r   r   rV      s   rV   c                   @   s"   e Zd ZdZdd ZdddZdS )
ExtraWhereFc                 C   s   || _ || _d S r%   )sqlsr"   )r   rX   r"   r   r   r   __init__   s    zExtraWhere.__init__Nc                 C   s(   dd | j D }d|t| jp"dfS )Nc                 S   s   g | ]}d | qS )r   r   )r7   r!   r   r   r   
<listcomp>   s     z%ExtraWhere.as_sql.<locals>.<listcomp>z AND r   )rX   r   listr"   )r   r   r   rX   r   r   r   r$      s    zExtraWhere.as_sql)NNrN   rO   rP   r
   rY   r$   r   r   r   r   rW      s   rW   c                   @   s    e Zd ZdZdd Zdd ZdS )SubqueryConstraintFc                 C   s   || _ || _|| _|| _d S r%   )r'   columnstargetsquery_object)r   r'   r^   r_   r`   r   r   r   rY      s    zSubqueryConstraint.__init__c                 C   s0   | j }|| j |j|d}|| j| j|S )N)r   )r`   Z
set_valuesr_   Zget_compilerZas_subquery_conditionr'   r^   )r   r   r   rF   Zquery_compilerr   r   r   r$      s    zSubqueryConstraint.as_sqlNr\   r   r   r   r   r]      s   r]   N)rQ   Zdjango.core.exceptionsr   Zdjango.utilsr   Zdjango.utils.functionalr   r   r   r<   r   rV   rW   r]   r   r   r   r   <module>   s    G