o
    ˷eM4                     @   s   d Z ddl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
mZ ddlmZ ddlmZ edZed	d
Zdd ZG dd dejZG dd dZG dd dZdddZdd Zdd ZG d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)
FieldError)DEFAULT_DB_ALIASDatabaseError)
LOOKUP_SEP)treedjango.db.modelsPathInfozGfrom_opts to_opts target_fields join_field m2m direct filtered_relationc                 c   s(    | V  |   D ]	}t|E d H  qd S N)__subclasses__
subclassesclssubclass r   S/var/www/ideatree/venv/lib/python3.10/site-packages/django/db/models/query_utils.pyr      s
   r   c                       s   e Zd ZdZdZdZdZeZdZddd fd	d

Z	dd Z
dd Zdd Zdd Zdd Z	dddZdd ZefddZdd Z  ZS )Qze
    Encapsulate filters as objects that can then be combined logically (using
    `&` and `|`).
    ANDORXORTNF)
_connector_negatedc                   s&   t  jg |t| ||d d S )N)children	connectornegated)super__init__sorteditems)selfr   r   argskwargs	__class__r   r   r   1   s
   
z
Q.__init__c                 C   s   t |tst|dddu st|| s!t|dr| S t|S t |tr8|s8|  \}}}t| |i |S t|  }||_|	| | |	|| |S )NconditionalFTcopy)

isinstancer   getattr	TypeErrorhasattrr%   deconstructtyper   add)r   otherconn_r    r!   objr   r   r   _combine8   s   
z
Q._combinec                 C      |  || jS r
   )r1   r   r   r-   r   r   r   __or__H      zQ.__or__c                 C   r2   r
   )r1   r   r3   r   r   r   __and__K   r5   z	Q.__and__c                 C   r2   r
   )r1   r   r3   r   r   r   __xor__N   r5   z	Q.__xor__c                 C   s$   t |  }|| | j |  |S r
   )r+   r,   r   negate)r   r0   r   r   r   
__invert__Q   s   
zQ.__invert__c                 C   s&   |j | ||ddd\}}|| |S )NF)allow_joins
split_subqcheck_filterable)_add_qpromote_joins)r   queryr:   reuse	summarizefor_saveclausejoinsr   r   r   resolve_expressionW   s   

zQ.resolve_expressionc                 c   sJ    | V  | j D ]}t|tr|d }t|dr| E dH  q|V  qdS )zg
        Recursively yield this Q object and all subexpressions, in depth-first
        order.
           flattenN)r   r&   tupler)   rG   )r   childr   r   r   rG   f   s   


z	Q.flattenc              
   C   s   ddl m} ddlm} ddlm} |d}| D ]\}}t|ds'||}|j||dd q||d	d
 |	|  |j
|d}	z|	|duW S  tye }
 ztd| |
 W Y d}
~
dS d}
~
ww )z|
        Do a database query to check if the expressions of the Q instance
        matches against the expressions.
        r   )Value)Query)SINGLENrE   F)selectrF   _check)usingz.Got a database error calling check() on %r: %sT)django.db.modelsrJ   django.db.models.sqlrK   django.db.models.sql.constantsrL   r   r)   add_annotationadd_qget_compilerexecute_sqlr   loggerwarning)r   againstrO   rJ   rK   rL   r?   namevaluecompilerer   r   r   checku   s$   

zQ.checkc                 C   sf   d| j j| j jf }|dr|dd}t| j}i }| j| jkr'| j|d< | j	r.d|d< |||fS )Nz%s.%szdjango.db.models.query_utilsr   r   Tr   )
r#   
__module____name__
startswithreplacerH   r   r   defaultr   )r   pathr    r!   r   r   r   r*      s   



zQ.deconstruct)NTNFF)r`   r_   __qualname____doc__r   r   r   rc   r$   r   r1   r4   r6   r7   r9   rE   rG   r   r^   r*   __classcell__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 r
   )field)r   ri   r   r   r   r      s   
zDeferredAttribute.__init__Nc                 C   sZ   |du r| S |j }| jj}||vr)| |}|du r%|j|gd || S |||< || S )zx
        Retrieve and caches the value from the datastore on the first lookup.
        Return the cached value.
        N)fields)__dict__ri   attname_check_parent_chainrefresh_from_db)r   instancer   data
field_namevalr   r   r   __get__   s   
zDeferredAttribute.__get__c                 C   s6   |j }|| jj}| jjr| j|krt||jS d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)_metaget_ancestor_linkri   modelprimary_keyr'   rl   )r   ro   opts
link_fieldr   r   r   rm      s
   z%DeferredAttribute._check_parent_chainr
   )r`   r_   re   rf   r   rs   rm   r   r   r   r   rh      s
    
rh   c                   @   st   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   |   |d S r
   )get_lookupsget)r   lookup_namer   r   r   _get_lookup   s   zRegisterLookupMixin._get_lookupN)maxsizec                 C   s   dd t | D }| |S )Nc                 S   s   g | ]	}|j d i qS )class_lookups)rk   r|   ).0parentr   r   r   
<listcomp>   s    z3RegisterLookupMixin.get_lookups.<locals>.<listcomp>)inspectgetmromerge_dicts)r   r   r   r   r   r{      s   
zRegisterLookupMixin.get_lookupsc                 C   N   ddl m} | |}|d u rt| dr| j|S |d ur%t||s%d S |S )Nr   )Lookupoutput_field)django.db.models.lookupsr   r~   r)   r   
get_lookup
issubclass)r   r}   r   foundr   r   r   r         
zRegisterLookupMixin.get_lookupc                 C   r   )Nr   )	Transformr   )r   r   r~   r)   r   get_transformr   )r   r}   r   r   r   r   r   r      r   z!RegisterLookupMixin.get_transformc                 C   s    i }t | D ]}|| q|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)dictsmergeddr   r   r   r      s   zRegisterLookupMixin.merge_dictsc                 C   s   t | D ]}|j  qd S r
   )r   r{   cache_clearr   r   r   r   _clear_cached_lookups   s   z)RegisterLookupMixin._clear_cached_lookupsc                 C   s4   |d u r|j }d| jvri | _|| j|< |   |S )Nr   )r}   rk   r   r   r   lookupr}   r   r   r   register_lookup   s   

z#RegisterLookupMixin.register_lookupc                 C   s"   |du r|j }| j|= |   dS )zn
        Remove given lookup from cls lookups. For use in tests only as it's
        not thread-safe.
        N)r}   r   r   r   r   r   r   _unregister_lookup   s   z&RegisterLookupMixin._unregister_lookupr
   )r`   r_   re   classmethodr~   	functools	lru_cacher{   r   r   staticmethodr   r   r   r   r   r   r   r   rz      s     






	rz   Fc                 C   s   | j sdS | j jr|sdS |r"|r|  |vrdS |s"| j|vr"dS |s)| jr)dS |rE| j|vrE|rE| j|v rEd| jjj| jf }t	|dS )ap  
    Return True if this field should be used to descend deeper for
    select_related() purposes. Used by both the query construction code
    (compiler.get_related_selections()) and the model instance creation code
    (compiler.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)
remote_fieldparent_linkrelated_query_namerZ   nullrl   rv   rt   object_namer   )ri   
restricted	requestedload_fieldsreversemsgr   r   r   select_related_descend  s&   

r   c                 C   sV   t dt| d D ]}t| d| }||v r(|| r(|| | |d f  S q	d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.
    rF   r   N)Fr   )rangelenr   join)lookup_partsannotationsnlevel_n_lookupr   r   r   refs_expression0  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  v p |  v S r
   )rt   concrete_modelget_parent_list)rx   rv   r   r   r^   E  s
   
z-check_rel_lookup_compatibility.<locals>.checkrw   F)r'   rv   rt   )rv   target_optsri   r^   r   r   r   check_rel_lookup_compatibility=  s   r   c                   @   s@   e Zd ZdZe d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   s:   |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   rd   )r   r   r   r   r   r   r   ]  s   

zFilteredRelation.__init__c                 C   s4   t || jstS | j|jko| j|jko| j|jkS r
   )r&   r#   NotImplementedr   r   r   r3   r   r   r   __eq__g  s   

zFilteredRelation.__eq__c                 C   s,   t | j| jd}| j|_| jd d  |_|S )Nr   )r   r   r   r   rd   )r   cloner   r   r   r   p  s   zFilteredRelation.clonec                 O   s   t d)zz
        QuerySet.annotate() only accepts expression-like arguments
        (with a resolve_expression() method).
        z0FilteredRelation.resolve_expression() is unused.)NotImplementedError)r   r    r!   r   r   r   rE   v  s   z#FilteredRelation.resolve_expressionc                 C   s&   |j }|j| jt| jd}||S )N)r@   )r?   build_filtered_relation_qr   setrd   compile)r   r\   
connectionr?   wherer   r   r   as_sql}  s   
zFilteredRelation.as_sqlN)
r`   r_   re   rf   r   r   r   r   rE   r   r   r   r   r   r   Z  s    
	r   )F)rf   r%   r   r   loggingcollectionsr   django.core.exceptionsr   	django.dbr   r   django.db.models.constantsr   django.utilsr   	getLoggerrW   r	   r   Noder   rh   rz   r   r   r   r   r   r   r   r   <module>   s.    
w)
G%