U
    d(                     @   s   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	m
Z
mZ d dlmZmZmZ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 dlmZ dgZG dd deZG dd deZdS )    N)OpClass)ValidationError)DEFAULT_DB_ALIASNotSupportedError)Expressions	StatementTable)BaseConstraint
DeferrableFQ)ExistsExpressionList)IndexExpression)PostgresOperatorLookup)Query)RemovedInDjango50WarningExclusionConstraintc                   @   s   e Zd ZdZdS )ExclusionConstraintExpressionz!%(expressions)s WITH %(operator)sN)__name__
__module____qualname__template r   r   G/tmp/pip-unpacked-wheel-7vj2equ7/django/contrib/postgres/constraints.pyr      s   r   c                       s   e Zd ZdZddddddd fdd
Zdd Zd	d
 Zdd Zdd Zdd Z	dd Z
 fddZ fddZdd ZdefddZ  ZS )r   zdCONSTRAINT %(name)s EXCLUDE USING %(index_type)s (%(expressions)s)%(include)s%(where)s%(deferrable)sNr   )
index_type	condition
deferrableinclude	opclassesviolation_error_messagec          	         s0  |r|  dkrtd|s$tdtdd |D s>tdt|td tfsXtd|rh|rhtdt|td tfstd	t|td ttfstd
t|ttfstd|rt	|t	|krtd|| _
|pd| _|| _|| _|rt|nd| _|| _| jrtjdtdd t j||d d S )N>   spgistgistz;Exclusion constraints only support GiST or SP-GiST indexes.zFAt least one expression is required to define an exclusion constraint.c                 s   s(   | ] }t |ttfot|d kV  qdS )   N)
isinstancelisttuplelen).0exprr   r   r   	<genexpr>0   s    z/ExclusionConstraint.__init__.<locals>.<genexpr>z+The expressions must be a list of 2-tuples.z3ExclusionConstraint.condition must be a Q instance.z7ExclusionConstraint with conditions cannot be deferred.z=ExclusionConstraint.deferrable must be a Deferrable instance.z4ExclusionConstraint.include must be a list or tuple.z6ExclusionConstraint.opclasses must be a list or tuple.zhExclusionConstraint.expressions and ExclusionConstraint.opclasses must have the same number of elements.ZGISTr   zThe opclasses argument is deprecated in favor of using django.contrib.postgres.indexes.OpClass in ExclusionConstraint.expressions.r#   )category
stacklevel)namer    )lower
ValueErrorallr$   typer   r
   r%   r&   r'   expressionsr   r   r   r   r   warningswarnr   super__init__)	selfr-   r2   r   r   r   r   r   r    	__class__r   r   r6      sR    
zExclusionConstraint.__init__c              	   C   s   g }t | jD ]j\}\}}t|tr,t|}zt|| j| }W n tk
rT   Y nX t||d}|	|j
 || qt| |S )N)operator)	enumerater2   r$   strr   r   r   
IndexErrorr   Zset_wrapper_classes
connectionappendr   Zresolve_expression)r7   schema_editorqueryr2   idx
expressionr:   r   r   r   _get_expressionsV   s    
z$ExclusionConstraint._get_expressionsc                    sF   | j d krd S || j }|| j\}}|t fdd|D  S )Nc                 3   s   | ]}  |V  qd S N)quote_value)r(   pr@   r   r   r*   i   s     z9ExclusionConstraint._get_condition_sql.<locals>.<genexpr>)r   Zbuild_whereZas_sqlr>   r&   )r7   compilerr@   rA   whereZsqlparamsr   rH   r   _get_condition_sqld   s
    
z&ExclusionConstraint._get_condition_sqlc           	         s   t  dd}|j|jd}| ||} jj}| |||} fdd| jD }t| j	t
||j|| j| jt||||j|rd| nd| ||| jdS )	NF)Z
alias_cols)r>   c                    s   g | ]} j |jqS r   )_meta	get_fieldcolumn)r(   
field_namemodelr   r   
<listcomp>q   s    z6ExclusionConstraint.constraint_sql.<locals>.<listcomp>z WHERE (%s) )tabler-   r   r2   rJ   r   r   )r   Zget_compilerr>   rD   rM   db_tablerL   r   r   r   r   
quote_namer-   r   r   rF   Z_index_include_sqlZ_deferrable_constraint_sqlr   )	r7   rR   r@   rA   rI   r2   rU   r   r   r   rQ   r   constraint_sqlk   s.    


   

z"ExclusionConstraint.constraint_sqlc                 C   s,   |  | tdt|jj|j| ||dS )Nz(ALTER TABLE %(table)s ADD %(constraint)s)rU   
constraint)check_supportedr   r   rM   rV   rW   rX   r7   rR   r@   r   r   r   
create_sql   s    

zExclusionConstraint.create_sqlc                 C   s   | |j||| jS rE   )Z_delete_constraint_sqlZsql_delete_checkrW   r-   r[   r   r   r   
remove_sql   s
    
zExclusionConstraint.remove_sqlc                 C   sP   | j r&| j dkr&|jjjs&td| j rL| j dkrL|jjjsLtdd S )Nr"   zICovering exclusion constraints using a GiST index require PostgreSQL 12+.r!   zMCovering exclusion constraints using an SP-GiST index require PostgreSQL 14+.)r   r   r.   r>   featuresZsupports_covering_gist_indexesr   Z supports_covering_spgist_indexes)r7   r@   r   r   r   rZ      s$    z#ExclusionConstraint.check_supportedc                    s   t   \}}}| j|d< | jd k	r.| j|d< | j dkrF| j|d< | jrV| j|d< | jrf| j|d< | jrv| j|d< |||fS )Nr2   r   r"   r   r   r   r   )	r5   deconstructr2   r   r   r.   r   r   r   )r7   pathargskwargsr8   r   r   r_      s    






zExclusionConstraint.deconstructc                    sx   t || jrl| j|jkoj| j|jkoj| j|jkoj| j|jkoj| j|jkoj| j|jkoj| j|jkoj| j	|j	kS t
 |S rE   )r$   r9   r-   r   r2   r   r   r   r   r    r5   __eq__)r7   otherr8   r   r   rc      s"    







zExclusionConstraint.__eq__c                 C   s~   d| j jt| jt| jt| j| jd kr.dnd| j | jd krDdnd| j | jsVdndt| j | j	sldndt| j	 f S )Nz2<%s: index_type=%s expressions=%s name=%s%s%s%s%s>rT   z condition=%sz deferrable=%rz include=%sz opclasses=%s)
r9   r   reprr   r2   r-   r   r   r   r   )r7   r   r   r   __repr__   s    zExclusionConstraint.__repr__c                 C   s  |j |}|j|j|d}g }t| jD ]\}\}	}
t|	trHt|	}	t|	trv|rf|	j	|krf d S |
|	j	|	}n8|	|}|r| D ] }t|tr|j	|kr  d S qt|	tr|	 d }	t|tr| d }t|	|d}|
|_|| q*|j| }||j}|jjs.|d k	r.|j|d}| jsN| r|t|  n.| jt|| j@ j||dr|t|  d S )N)metaexcluder   )lhsrhs)pk)using)Z_default_managerrl   Z_get_field_value_maprM   r;   r2   r$   r<   r   r-   getZreplace_referencesflattenr   Zget_source_expressionsr   Zpostgres_operatorr?   filterZ_get_pk_val_stateZaddingrh   r   existsr   Zget_violation_error_messager   check)r7   rR   instancerh   rl   ZquerysetZreplacement_mapZlookupsrB   rC   r:   Zrhs_expressionr)   lookupZmodel_class_pkr   r   r   validate   sJ     







 zExclusionConstraint.validate)r   r   r   r   r6   rD   rL   rX   r\   r]   rZ   r_   rc   rf   r   ru   __classcell__r   r   r8   r   r      s&   
;)r3   Zdjango.contrib.postgres.indexesr   Zdjango.core.exceptionsr   Z	django.dbr   r   Z!django.db.backends.ddl_referencesr   r   r   Zdjango.db.modelsr	   r
   r   r   Zdjango.db.models.expressionsr   r   Zdjango.db.models.indexesr   Zdjango.db.models.lookupsr   Zdjango.db.models.sqlr   Zdjango.utils.deprecationr   __all__r   r   r   r   r   r   <module>   s   