
v^/                 @   s  d  Z  d d l Z d d l Z d d l Z d d l m Z d d l m Z d d l m	 Z	 e d d  Z
 Gd d	   d	 e  Z d
 d   Z Gd d   d  Z Gd d   d e	 j  Z Gd d   d  Z Gd d   d  Z d d d  Z d d   Z d d   Z Gd d   d  Z d S)z
Various data structures used in query construction.

Factored out from django.db.models.query to avoid making the main module very
large and/or so that they can be used by other modules without getting into
circular import difficulties.
    N)
namedtuple)
LOOKUP_SEP)treePathInfozGfrom_opts to_opts target_fields join_field m2m direct filtered_relationc               @   s   e  Z d  Z d Z d S)InvalidQueryz?The query passed to raw() isn't a safe query to use with raw().N)__name__
__module____qualname____doc__ r   r   >/tmp/pip-build-8lau8j11/django/django/db/models/query_utils.pyr      s   r   c             c   s/   |  Vx# |  j    D] } t |  Ed  Hq Wd  S)N)__subclasses__
subclasses)clssubclassr   r   r   r      s    r   c               @   s:   e  Z d  Z d Z d Z d d   Z d d d d  Z d S)QueryWrapperz
    A type that indicates the contents are an SQL fragment and the associate
    parameters. Can be used to pass opaque data to a where-clause, for example.
    Fc             C   s   | t  |  f |  _ d  S)N)listdata)selfZsqlparamsr   r   r   __init__(   s    zQueryWrapper.__init__Nc             C   s   |  j  S)N)r   )r   compiler
connectionr   r   r   as_sql+   s    zQueryWrapper.as_sql)r   r   r	   r
   Zcontains_aggregater   r   r   r   r   r   r   !   s   r   c                   s   e  Z d  Z d Z d Z d Z e Z d Z d d d d   f d	 d
  Z d d   Z	 d d   Z
 d d   Z d d   Z d d d d d d d  Z d d   Z   S)Qze
    Encapsulate filters as objects that can then be combined logically (using
    `&` and `|`).
    ANDORT
_connectorN_negatedFc               s5   t    j d | t | j     d | d |  d  S)Nchildren	connectornegated)superr   sorteditems)r   r   r   argskwargs)	__class__r   r   r   :   s    z
Q.__init__c             C   s}   t  | t  s t |   | s. t j |   S|  sA t j |  St |     } | | _ | j |  |  | j | |  | S)N)
isinstancer   	TypeErrorcopydeepcopytyper    add)r   otherconnobjr   r   r   _combine=   s    	z
Q._combinec             C   s   |  j  | |  j  S)N)r1   r   )r   r.   r   r   r   __or__N   s    zQ.__or__c             C   s   |  j  | |  j  S)N)r1   r   )r   r.   r   r   r   __and__Q   s    z	Q.__and__c             C   s0   t  |     } | j |  |  j  | j   | S)N)r,   r-   r   negate)r   r0   r   r   r   
__invert__T   s    
zQ.__invert__c          	   C   s;   | j  |  | d | d d d d \ } } | j |  | S)Nallow_joinsZ
split_subqFZcheck_filterable)Z_add_qZpromote_joins)r   queryr6   reuseZ	summarizeZfor_saveZclauseZjoinsr   r   r   resolve_expressionZ   s
    zQ.resolve_expressionc             C   s   d |  j  j |  j  j f } | j d  r= | j d d  } f  i  } } t |  j  d k r t |  j d t  r |  j d } | d | d i } n0 t	 |  j  } |  j
 |  j k r d |  j
 i } |  j r d | d <| | | f S)	Nz%s.%szdjango.db.models.query_utilszdjango.db.models   r   r   Tr   )r'   r   r   
startswithreplacelenr   r(   r   tupler    defaultr!   )r   pathr%   r&   childr   r   r   deconstructd   s    ,	
zQ.deconstruct)r   r   r	   r
   r   r   r?   Zconditionalr   r1   r2   r3   r5   r9   rB   r   r   )r'   r   r   /   s   
r   c               @   s=   e  Z d  Z d Z d d   Z d d d  Z d d   Z d S)	DeferredAttributez
    A wrapper for a deferred-loading field. When the value is read from this
    object the first time, the query is executed.
    c             C   s   | |  _  d  S)N)field)r   rD   r   r   r   r   z   s    zDeferredAttribute.__init__Nc             C   s   | d k r |  S| j  } |  j j } | j | |   |  k r |  j |  } | d k rz | j d | g  t | |  } | | | <| | S)zx
        Retrieve and caches the value from the datastore on the first lookup.
        Return the cached value.
        Nfields)__dict__rD   attnameget_check_parent_chainZrefresh_from_dbgetattr)r   instancer   r   
field_namevalr   r   r   __get__}   s    	
zDeferredAttribute.__get__c             C   sM   | j  } | j |  j j  } |  j j rI |  j | k rI t | | j  Sd S)z
        Check if the field value can be fetched from a parent field already
        loaded in the instance. This can be done if the to-be fetched
        field is a primary key field.
        N)_metaZget_ancestor_linkrD   modelprimary_keyrJ   rG   )r   rK   optsZ
link_fieldr   r   r   rI      s
    	z%DeferredAttribute._check_parent_chain)r   r   r	   r
   r   rN   rI   r   r   r   r   rC   u   s   rC   c               @   s   e  Z d  Z e d d    Z e e j d d  d d     Z d d   Z d	 d
   Z	 e
 d d    Z e d d    Z e d d d   Z e d d d   Z d S)RegisterLookupMixinc             C   s   |  j    j | d   S)N)get_lookupsrH   )r   lookup_namer   r   r   _get_lookup   s    zRegisterLookupMixin._get_lookupmaxsizeNc             C   s)   d d   t  j |   D } |  j |  S)Nc             S   s%   g  |  ] } | j  j d  i    q S)class_lookups)rF   rH   ).0parentr   r   r   
<listcomp>   s   	 z3RegisterLookupMixin.get_lookups.<locals>.<listcomp>)inspectZgetmromerge_dicts)r   rX   r   r   r   rT      s    zRegisterLookupMixin.get_lookupsc             C   sn   d d l  m } |  j |  } | d  k rJ t |  d  rJ |  j j |  S| d  k	 rj t | |  rj d  S| S)Nr   )Lookupoutput_field)django.db.models.lookupsr^   rV   hasattrr_   
get_lookup
issubclass)r   rU   r^   foundr   r   r   rb      s    zRegisterLookupMixin.get_lookupc             C   sn   d d l  m } |  j |  } | d  k rJ t |  d  rJ |  j j |  S| d  k	 rj t | |  rj d  S| S)Nr   )	Transformr_   )r`   re   rV   ra   r_   get_transformrc   )r   rU   re   rd   r   r   r   rf      s    z!RegisterLookupMixin.get_transformc             C   s.   i  } x! t  |   D] } | j |  q W| S)z
        Merge dicts in reverse to preference the order of the original list. e.g.,
        merge_dicts([a, b]) will preference the keys in 'a' over those in 'b'.
        )reversedupdate)ZdictsZmergeddr   r   r   r]      s    zRegisterLookupMixin.merge_dictsc             C   s(   x! t  |   D] } | j j   q Wd  S)N)r   rT   cache_clear)r   r   r   r   r   _clear_cached_lookups   s    z)RegisterLookupMixin._clear_cached_lookupsc             C   sH   | d  k r | j  } d |  j k r- i  |  _ | |  j | <|  j   | S)NrX   )rU   rF   rX   rk   )r   lookuprU   r   r   r   register_lookup   s    		
z#RegisterLookupMixin.register_lookupc             C   s#   | d k r | j  } |  j | =d S)zn
        Remove given lookup from cls lookups. For use in tests only as it's
        not thread-safe.
        N)rU   rX   )r   rl   rU   r   r   r   _unregister_lookup   s    	z&RegisterLookupMixin._unregister_lookup)r   r   r	   classmethodrV   	functools	lru_cacherT   rb   rf   staticmethodr]   rk   rm   rn   r   r   r   r   rS      s   !			rS   Fc             C   s   |  j  s d S|  j  j r$ | r$ d S| r` | rF |  j   | k rF d S| r` |  j | k r` d S| rt |  j rt d S| r |  j | k r | r |  j | k r t d |  j j j	 |  j f   d S)au  
    Return True if this field should be used to descend deeper for
    select_related() purposes. Used by both the query construction code
    (sql.query.fill_related_selections()) and the model instance creation code
    (query.get_klass_info()).

    Arguments:
     * field - the field to be checked
     * restricted - a boolean field, indicating if the field list has been
       manually restricted using a requested clause)
     * requested - The select_related() dictionary.
     * load_fields - the set of fields to be loaded on this model
     * reverse - boolean, True if we are checking a reverse select related
    FzXField %s.%s cannot be both deferred and traversed using select_related at the same time.T)
Zremote_fieldZparent_linkZrelated_query_namenamenullrG   r   rP   rO   Zobject_name)rD   Z
restricted	requestedZload_fieldsreverser   r   r   select_related_descend   s"    	rw   c             C   su   xh t  d t |   d  D]M } t j |  d |   } | | k r | | r | | |  | d  f Sq Wd f  f S)z
    Check if the lookup_parts contains references to the given annotations set.
    Because the LOOKUP_SEP is contained in the default annotation names, check
    each prefix of the lookup_parts for a match.
    r:   r   NF)ranger=   r   join)Zlookup_partsZannotationsnZlevel_n_lookupr   r   r   refs_expression  s
     r{   c                s@     f d d   } | |  p? t  | d d  o? | | j j  S)z
    Check that self.model is compatible with target_opts. Compatibility
    is OK if:
      1) model and opts match (where proxy inheritance is removed)
      2) model is parent of opts' model or the other way around
    c                s=     j  j |  j k p< |  j   j  j   k p<   |  j   k S)N)rO   Zconcrete_modelZget_parent_list)rR   )rP   r   r   check  s    z-check_rel_lookup_compatibility.<locals>.checkrQ   F)rJ   rP   rO   )rP   Ztarget_optsrD   r|   r   )rP   r   check_rel_lookup_compatibility  s    r}   c               @   s[   e  Z d  Z d Z d e   d d  Z d d   Z d d   Z d	 d
   Z d d   Z	 d S)FilteredRelationz7Specify custom filtering in the ON clause of SQL joins.	conditionc            C   sU   | s t  d   | |  _ d  |  _ t | t  s? t  d   | |  _ g  |  _ d  S)Nzrelation_name cannot be empty.z*condition argument must be a Q() instance.)
ValueErrorrelation_namealiasr(   r   r   r@   )r   r   r   r   r   r   r   0  s    			zFilteredRelation.__init__c             C   sF   t  | |  j  oE |  j | j k oE |  j | j k oE |  j | j k S)N)r(   r'   r   r   r   )r   r.   r   r   r   __eq__:  s    zFilteredRelation.__eq__c             C   s>   t  |  j d |  j } |  j | _ |  j d  d   | _ | S)Nr   )r~   r   r   r   r@   )r   cloner   r   r   r   B  s    zFilteredRelation.clonec             O   s   t  d   d S)zz
        QuerySet.annotate() only accepts expression-like arguments
        (with a resolve_expression() method).
        z0FilteredRelation.resolve_expression() is unused.N)NotImplementedError)r   r%   r&   r   r   r   r9   H  s    z#FilteredRelation.resolve_expressionc             C   s7   | j  } | j |  j d t |  j  } | j |  S)Nr8   )r7   Zbuild_filtered_relation_qr   setr@   compile)r   r   r   r7   wherer   r   r   r   O  s    	!zFilteredRelation.as_sqlN)
r   r   r	   r
   r   r   r   r   r9   r   r   r   r   r   r~   -  s   
r~   )r
   r*   rp   r\   collectionsr   Zdjango.db.models.constantsr   Zdjango.utilsr   r   	Exceptionr   r   r   Noder   rC   rS   rw   r{   r}   r~   r   r   r   r   <module>   s"   F(C$