U
    [+d(                     @   s   d Z ddlZddlmZ ddlmZ ddlmZmZ ddl	m
Z
 ddlmZ ddlmZ d	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.
    N)reduceEmptyResultSetCaseWhen)Exact)tree)cached_propertyANDORXORc                   @   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d#d$ Zed%d& Zd'd( Z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p>| r6| jtkp>| jtk}|rR| j rRd| fS g }g }| jD ]^}t|dr||\}}|dk	r|	| |dk	r|	| q`|j r|	| q`|	| q`|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   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-n7e__lmp/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 tkr|jjs| | jt}t	t
jdd | jD }td|}	| ||	gt| j||S | jD ]}
z||
\}}W n tk
r   |d8 }Y n$X |r|| || n|d8 }|dkr| jrdg f  S t|dkr| jr&tqdg f  S qd| j  }||}|r~| jr`d| }nt|dksv| 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.
           c                 s   s"   | ]}t t|d dddV  qdS )r   )Zthenr   )defaultNr   .0r   r   r   r   	<genexpr>g   s     z#WhereNode.as_sql.<locals>.<genexpr>r    z %s zNOT (%s)(%s))r   r   lenr   r   featuresZsupports_logical_xorr   r   r   operatoraddr   r   as_sqlcompiler   r   extendjoinresolved)r   compiler
connectionresultZresult_paramsZfull_neededZempty_neededlhsZrhs_sumrhschildsqlparamsconnZ
sql_stringr   r   r   r&   Q   sR    

 





zWhereNode.as_sqlNc                 C   s"   g }| j D ]}||  q
|S N)r   r(   get_group_by_cols)r   aliascolsr0   r   r   r   r5      s    
zWhereNode.get_group_by_colsc                 C   s   | j d d  S r4   )r   r   r   r   r   get_source_expressions   s    z WhereNode.get_source_expressionsc                 C   s    t |t | jkst|| _d S r4   )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posr0   r   r   r   r<      s
    

zWhereNode.relabel_aliasesc                 C   sN   | j jd| 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().
        N)r   r   r   clone)r   Z_new_instancer   r   r   r   r   rA   )r   rA   r0   r   r   r   rA      s    

zWhereNode.clonec                 C   s   |   }|| |S r4   )rA   r<   )r   r?   rA   r   r   r   r=      s    
zWhereNode.relabeled_clonec                 C   s   |   S r4   )rA   r8   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 r4   _contains_aggregater   clsr   r   r      s     z0WhereNode._contains_aggregate.<locals>.<genexpr>)
isinstancer	   Nodeanyr   r   rF   objr   rE   r   rD      s    zWhereNode._contains_aggregatec                 C   s
   |  | S r4   rC   r8   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 r4   _contains_over_clauser   rE   r   r   r      s     z2WhereNode._contains_over_clause.<locals>.<genexpr>)rG   r	   rH   rI   r   contains_over_clauserJ   r   rE   r   rM      s    zWhereNode._contains_over_clausec                 C   s
   |  | S r4   rL   r8   r   r   r   rN      s    zWhereNode.contains_over_clausec                 O   s    t | dr| j|f||} | S )Nresolve_expression)r   rO   )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   r.   r/   )r   r   _resolve_noderT   r.   r/   )rF   noderQ   rR   rS   r0   r   r   r   rU      s    



zWhereNode._resolve_nodec                 O   s$   |   }|j|f|| d|_|S )NT)rA   rU   r*   )r   rR   rS   rA   r   r   r   rO      s    zWhereNode.resolve_expressionc                 C   s   ddl m} | S )Nr   )BooleanField)Zdjango.db.modelsrW   )r   rW   r   r   r   output_field   s    zWhereNode.output_fieldc                 C   s   |j jjsd| d}||fS )Nz
CASE WHEN z THEN 1 ELSE 0 END)r,   r#   Z&supports_boolean_expr_in_select_clause)r   r+   r1   r2   r   r   r   select_format   s    
zWhereNode.select_formatc                 C   s   | j |S r4   )rX   get_db_converters)r   r,   r   r   r   rZ      s    zWhereNode.get_db_convertersc                 C   s   | j |S r4   )rX   
get_lookup)r   lookupr   r   r   r[     s    zWhereNode.get_lookup)F)N)__name__
__module____qualname____doc__r   r   r*   Zconditionalr   r&   r5   r9   r;   r<   rA   r=   rB   classmethodrD   r
   r   rM   rN   staticmethodrT   rU   rO   rX   rY   rZ   r[   r   r   r   r   r      s>   
+C






	
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 r4   r   )r   r+   r,   r   r   r   r&     s    zNothingNode.as_sql)NN)r]   r^   r_   r`   r   r&   r   r   r   r   rc     s   rc   c                   @   s"   e Zd ZdZdd ZdddZdS )
ExtraWhereFc                 C   s   || _ || _d S r4   )sqlsr2   )r   re   r2   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   )r   r1   r   r   r   
<listcomp>  s     z%ExtraWhere.as_sql.<locals>.<listcomp>z AND r   )re   r)   listr2   )r   r+   r,   re   r   r   r   r&     s    zExtraWhere.as_sql)NNr]   r^   r_   r   rf   r&   r   r   r   r   rd     s   rd   c                   @   s    e Zd ZdZdd Zdd ZdS )SubqueryConstraintFc                 C   s(   || _ || _|| _|jdd || _d S )NT)Zclear_default)r6   columnstargetsZclear_orderingquery_object)r   r6   rk   rl   rm   r   r   r   rf   !  s
    zSubqueryConstraint.__init__c                 C   s0   | j }|| j |j|d}|| j| j|S )N)r,   )rm   Z
set_valuesrl   Zget_compilerZas_subquery_conditionr6   rk   )r   r+   r,   rQ   Zquery_compilerr   r   r   r&   (  s    zSubqueryConstraint.as_sqlNri   r   r   r   r   rj     s   rj   )r`   r$   	functoolsr   Zdjango.core.exceptionsr   Zdjango.db.models.expressionsr   r   Zdjango.db.models.lookupsr   Zdjango.utilsr	   Zdjango.utils.functionalr
   r   r   r   rH   r   rc   rd   rj   r   r   r   r   <module>   s    t	