U
    [+dN                     @   s  d dl 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 d dlmZ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eZdLddZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd dZ G d d! d!ej!Z"G d"d# d#e ej#Z$e%e e%e e%e e%e e%e e%e" e%e$ G d$d% d%eZ&G d&d' d'e&Z'G d(d) d)Z(G d*d+ d+ej)Z*G d,d- d-ej+Z,G d.d/ d/e"Z-G d0d1 d1e e(ej.Z/G d2d3 d3e e(ej#Z0G d4d5 d5e(ej1Z2G d6d7 d7e e(ej3Z4G d8d9 d9e(ej5Z6G d:d; d;e e(ej7Z8G d<d= d=e(ej9Z:G d>d? d?e e(ej;Z<G d@dA dAZ=G dBdC dCe=ej>Z?G dDdE dEe=ej@ZAG dFdG dGe=ejBZCG dHdI dIe=ejDZEe&%e, e&%e- e&%e/ e&%e* e&%e0 e&%e2 e&%e4 e&%e6 e&%e8 e&%e: e&%e< e&%e? e&%eA e&%eC e&%eE G dJdK dKZFdS )M    N)forms)checks
exceptions)NotSupportedErrorconnectionsrouter)lookups)PostgresOperatorLookup	Transform)gettext_lazy   )Field)CheckFieldDefaultMixin	JSONFieldc                       s   e Zd ZdZedZdediZdZd fdd	Z fd	d
Z	dd Z
 fddZdd Zdd Zdd Z fddZ fddZdd Z fddZ  ZS )r   FzA JSON objectinvalidzValue must be valid JSON.)dictz{}Nc                    sJ   |rt |std|r(t |s(td|| _|| _t j||f| d S )Nz0The encoder parameter must be a callable object.z0The decoder parameter must be a callable object.)callable
ValueErrorencoderdecodersuper__init__)selfZverbose_namenamer   r   kwargs	__class__ @/tmp/pip-unpacked-wheel-n7e__lmp/django/db/models/fields/json.pyr      s    zJSONField.__init__c                    s0   t  jf |}|dpg }|| | |S )N	databases)r   checkgetextend_check_supported)r   r   errorsr   r   r   r   r    (   s    zJSONField.checkc                 C   sz   g }|D ]l}t || jsqt| }| jjjr@| jjj|jkr@qd| jjjks|jj	s|
tjd|j | jdd q|S )Nsupports_json_fieldz%s does not support JSONFields.zfields.E180)objid)r   Zallow_migrate_modelmodelr   Z_metaZrequired_db_vendorvendorZrequired_db_featuresfeaturesr%   appendr   ErrorZdisplay_name)r   r   r$   db
connectionr   r   r   r#   .   s,    zJSONField._check_supportedc                    sF   t   \}}}}| jd k	r&| j|d< | jd k	r:| j|d< ||||fS )Nr   r   )r   deconstructr   r   )r   r   pathargsr   r   r   r   r/   F   s    



zJSONField.deconstructc                 C   sV   |d kr|S t |tr$t |ts$|S ztj|| jdW S  tjk
rP   | Y S X d S Ncls)
isinstanceKeyTransformstrjsonloadsr   JSONDecodeError)r   valueZ
expressionr.   r   r   r   from_db_valueN   s    zJSONField.from_db_valuec                 C   s   dS )Nr   r   r   r   r   r   get_internal_typeZ   s    zJSONField.get_internal_typec                 C   s   |d kr|S t j|| jdS r2   )r8   dumpsr   )r   r;   r   r   r   get_prep_value]   s    zJSONField.get_prep_valuec                    s   t  |}|r|S t|S N)r   get_transformKeyTransformFactory)r   r   Z	transformr   r   r   rB   b   s    zJSONField.get_transformc                    sV   t  || ztj|| jd W n. tk
rP   tj| jd dd|idY nX d S )Nr3   r   r;   )codeparams)	r   validater8   r?   r   	TypeErrorr   ZValidationErrorZerror_messages)r   r;   Zmodel_instancer   r   r   rF   h   s    zJSONField.validatec                 C   s
   |  |S rA   )Zvalue_from_object)r   r&   r   r   r   value_to_strings   s    zJSONField.value_to_stringc                    s    t  jf tj| j| jd|S )N)Z
form_classr   r   )r   	formfieldr   r   r   r   )r   r   r   r   r   rI   v   s    zJSONField.formfield)NNNN)__name__
__module____qualname__Zempty_strings_allowed_descriptionZdefault_error_messagesZ_default_hintr   r    r#   r/   r<   r>   r@   rB   rF   rH   rI   __classcell__r   r   r   r   r      s*        Tc              	   C   sl   |r
dgng }| D ]N}zt |}W n. tk
rP   |d |t| Y qX |d|  qd|S )N$.z[%s] )intr   r+   r8   r?   join)key_transformsinclude_rootr0   key_transformnumr   r   r   compile_json_path   s    
rY   c                   @   s   e Zd ZdZdZdd ZdS )DataContainscontainsz@>c                 C   sP   |j jstd| ||\}}| ||\}}t|t| }d||f |fS )Nz:contains lookup is not supported on this database backend.JSON_CONTAINS(%s, %s)r*   Zsupports_json_field_containsr   process_lhsprocess_rhstupler   compilerr.   lhs
lhs_paramsrhs
rhs_paramsrE   r   r   r   as_sql   s    zDataContains.as_sqlNrJ   rK   rL   lookup_namepostgres_operatorrg   r   r   r   r   rZ      s   rZ   c                   @   s   e Zd ZdZdZdd ZdS )ContainedByZcontained_byz<@c                 C   sP   |j jstd| ||\}}| ||\}}t|t| }d||f |fS )Nz>contained_by lookup is not supported on this database backend.r\   r]   ra   r   r   r   rg      s    zContainedBy.as_sqlNrh   r   r   r   r   rk      s   rk   c                       sJ   e Zd ZdZdd ZdddZdd Zdd	 Z fd
dZdd Z	  Z
S )HasKeyLookupNc                 C   s   dt | S )Nz.%s)r8   r?   r   rW   r   r   r   compile_json_path_final_key   s    z(HasKeyLookup.compile_json_path_final_keyc                 C   s   t | jtr*| j||\}}}t|}n| ||\}}d}|| }| j}	g }
t |	ttfsd|	g}	|	D ]Z}t |tr|||^ }}n|g}|^ }}t|dd}|| 	|7 }|

||  qh| jrd| j|gt|
  }|t|t|
 fS )NrP   FrV   z(%s))r5   rc   r6   preprocess_lhsrY   r^   re   listr`   rn   r+   logical_operatorrT   len)r   rb   r.   templaterc   rd   Zlhs_key_transformsZlhs_json_pathsqlre   rf   keyrM   rhs_key_transformsZ	final_keyZrhs_json_pathr   r   r   rg      s0     



zHasKeyLookup.as_sqlc                 C   s   | j ||ddS )Nz"JSON_CONTAINS_PATH(%s, 'one', %%s)rt   rg   r   rb   r.   r   r   r   as_mysql   s
      zHasKeyLookup.as_mysqlc                 C   s$   | j ||dd\}}|t| g fS )NzJSON_EXISTS(%s, '%%s')rx   )rg   r`   )r   rb   r.   ru   rE   r   r   r   	as_oracle   s      
zHasKeyLookup.as_oraclec                    sX   t | jtrJ| j||^ }}|d d D ]}t|| j| _q,|d | _t ||S )N)r5   re   r6   rp   rc   r   as_postgresql)r   rb   r.   rM   rw   rv   r   r   r   r~      s    
zHasKeyLookup.as_postgresqlc                 C   s   | j ||ddS )NJSON_TYPE(%s, %%s) IS NOT NULLrx   ry   rz   r   r   r   	as_sqlite   s
      zHasKeyLookup.as_sqlite)N)rJ   rK   rL   rr   rn   rg   r{   r|   r~   r   rO   r   r   r   r   rl      s   
rl   c                   @   s   e Zd ZdZdZdZdS )HasKeyZhas_key?FN)rJ   rK   rL   ri   rj   Zprepare_rhsr   r   r   r   r      s   r   c                   @   s    e Zd ZdZdZdZdd ZdS )HasKeysZhas_keysz?&z AND c                 C   s   dd | j D S )Nc                 S   s   g | ]}t |qS r   )r7   ).0itemr   r   r   
<listcomp>   s     z+HasKeys.get_prep_lookup.<locals>.<listcomp>)re   r=   r   r   r   get_prep_lookup   s    zHasKeys.get_prep_lookupN)rJ   rK   rL   ri   rj   rr   r   r   r   r   r   r      s   r   c                   @   s   e Zd ZdZdZdZdS )
HasAnyKeysZhas_any_keysz?|z OR N)rJ   rK   rL   ri   rj   rr   r   r   r   r   r      s   r   c                   @   s   e Zd Zdd ZdS )HasKeyOrArrayIndexc                 C   s   t |gddS )NFro   )rY   rm   r   r   r   rn     s    z.HasKeyOrArrayIndex.compile_json_path_final_keyN)rJ   rK   rL   rn   r   r   r   r   r     s   r   c                       s,   e Zd ZdZ fddZ fddZ  ZS )CaseInsensitiveMixinz
    Mixin to allow case-insensitive comparison of JSON values on MySQL.
    MySQL handles strings used in JSON context using the utf8mb4_bin collation.
    Because utf8mb4_bin is a binary collation, comparison of JSON values is
    case-sensitive.
    c                    s0   t  ||\}}|jdkr(d| |fS ||fS Nmysqlz	LOWER(%s))r   r^   r)   )r   rb   r.   rc   rd   r   r   r   r^     s    
z CaseInsensitiveMixin.process_lhsc                    s0   t  ||\}}|jdkr(d| |fS ||fS r   )r   r_   r)   r   rb   r.   re   rf   r   r   r   r_     s    
z CaseInsensitiveMixin.process_rhs)rJ   rK   rL   __doc__r^   r_   rO   r   r   r   r   r     s   r   c                       s    e Zd ZdZ fddZ  ZS )	JSONExactTc                    sV   t  ||\}}|dkr*|d gkr*dg}|jdkrNdgt| }|t| }||fS )N%snullr   JSON_EXTRACT(%s, '$'))r   r_   r)   rs   r`   )r   rb   r.   re   rf   funcr   r   r   r_     s    
zJSONExact.process_rhs)rJ   rK   rL   Zcan_use_none_as_rhsr_   rO   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )JSONIContainsNrJ   rK   rL   r   r   r   r   r   )  s   r   c                       sL   e Zd ZdZdZ fddZdd Zdd Zd	d
 Zdd Z	dd Z
  ZS )r6   z->z#>c                    s   t  j|| t|| _d S rA   )r   r   r7   key_name)r   r   r1   r   r   r   r   r   :  s    zKeyTransform.__init__c                 C   s^   | j g}| j}t|tr.|d|j  |j}q||\}}|jdkrTdd |D }|||fS )Nr   oraclec                 S   s   g | ]}| d dqS )%z%%)replace)r   rv   r   r   r   r   G  s     z/KeyTransform.preprocess_lhs.<locals>.<listcomp>)r   rc   r5   r6   insertcompiler)   )r   rb   r.   rU   previousrc   rE   r   r   r   rp   >  s    

zKeyTransform.preprocess_lhsc                 C   s0   |  ||\}}}t|}d| t||f fS )NzJSON_EXTRACT(%s, %%s)rp   rY   r`   r   rb   r.   rc   rE   rU   	json_pathr   r   r   r{   J  s    zKeyTransform.as_mysqlc                 C   s6   |  ||\}}}t|}d||fd  t|d fS )Nz4COALESCE(JSON_QUERY(%s, '%s'), JSON_VALUE(%s, '%s'))   r   r   r   r   r   r|   O  s    

zKeyTransform.as_oraclec                 C   s   |  ||\}}}t|dkr>d|| jf }|t||f fS zt| j}W n tk
rf   | j}Y nX d|| jf t||f fS )Nr   z(%s %s %%s))rp   rs   postgres_nested_operatorr`   rS   r   r   rj   )r   rb   r.   rc   rE   rU   ru   lookupr   r   r   r~   W  s    zKeyTransform.as_postgresqlc                 C   sT   |  ||\}}}t|}ddd |jjD }d||||f t||f d fS )N,c                 S   s   g | ]}t |qS r   )repr)r   datatyper   r   r   r   f  s     z*KeyTransform.as_sqlite.<locals>.<listcomp>z](CASE WHEN JSON_TYPE(%s, %%s) IN (%s) THEN JSON_TYPE(%s, %%s) ELSE JSON_EXTRACT(%s, %%s) END)   )rp   rY   rT   opsjsonfield_datatype_valuesr`   )r   rb   r.   rc   rE   rU   r   Zdatatype_valuesr   r   r   r   b  s    
zKeyTransform.as_sqlite)rJ   rK   rL   rj   r   r   rp   r{   r|   r~   r   rO   r   r   r   r   r6   6  s   r6   c                   @   s   e Zd ZdZdZdS )KeyTextTransformz->>z#>>N)rJ   rK   rL   rj   r   r   r   r   r   r   n  s   r   c                       s    e Zd ZdZ fddZ  ZS )KeyTransformTextLookupMixinz
    Mixin for combining with a lookup expecting a text lhs from a JSONField
    key lookup. On PostgreSQL, make use of the ->> operator instead of casting
    key values to text and performing the lookup on the resulting
    representation.
    c                    s@   t |tstdt|jf|j|j}t j|f|| d S )NzLTransform should be an instance of KeyTransform in order to use this lookup.)	r5   r6   rG   r   r   Zsource_expressionsextrar   r   )r   rW   r1   r   Zkey_text_transformr   r   r   r   {  s    
z$KeyTransformTextLookupMixin.__init__)rJ   rK   rL   r   r   rO   r   r   r   r   r   s  s   r   c                   @   s   e Zd Zdd Zdd ZdS )KeyTransformIsNullc                 C   s\   t | jj| jj||\}}| js,||fS | j||\}}}d||f t|t| fS )Nz(NOT %s OR %s IS NULL))r   rc   r   r|   re   rp   r`   )r   rb   r.   ru   rE   rc   rd   rM   r   r   r   r|     s     zKeyTransformIsNull.as_oraclec                 C   s,   d}| j sd}t| jj| jjj|||dS )NzJSON_TYPE(%s, %%s) IS NULLr   rx   )re   r   rc   r   rg   )r   rb   r.   rt   r   r   r   r     s    zKeyTransformIsNull.as_sqliteN)rJ   rK   rL   r|   r   r   r   r   r   r     s   r   c                       s   e Zd Z fddZ  ZS )KeyTransformInc                    s   t  ||||\}}t|ds|jjs|jdkrbt|}d}t|t	t
frX|d }q|d }n(|jdks|jdkr|d |jjkrd	}|jdkr|jrd
| }||fS )Nrg   r   9%s(JSON_OBJECT('value' VALUE %%s FORMAT JSON), '$.value')
JSON_QUERY
JSON_VALUEr   sqliter   r   zJSON_UNQUOTE(%s))r   resolve_expression_parameterhasattrr*   has_native_json_fieldr)   r8   r9   r5   rq   r   r   r   Zmysql_is_mariadb)r   rb   r.   ru   paramrE   r;   r   r   r   r     s2    




z+KeyTransformIn.resolve_expression_parameter)rJ   rK   rL   r   rO   r   r   r   r   r     s   r   c                       s(   e Zd Z fddZ fddZ  ZS )KeyTransformExactc                    s   t | jtr ttj| ||S t ||\}}|jdkrg }d}|D ]:}t	|}t |t
tfrt||d  qH||d  qH|t| }nF|jdkrg }|D ]&}||jjkr|d q|d q|t| }||fS )Nr   r   r   r   r   r   r   )r5   re   r6   r   r   Exactr_   r)   r8   r9   rq   r   r+   r`   r   r   )r   rb   r.   re   rf   r   ru   r;   r   r   r   r_     s(    


zKeyTransformExact.process_rhsc                    s   t  ||\}}|dgkr~t| jj| jj}|||\}}| jd| jd}|||\}	}
d||	f t|t|
 fS t  ||S )Nr   ZisnullTz	%s AND %s)	r   r_   r   rc   r   r|   Z
get_lookuprg   r`   )r   rb   r.   re   rf   Zhas_key_exprZhas_key_sqlZhas_key_paramsZis_null_exprZis_null_sqlZis_null_paramsr   r   r   r|     s    

zKeyTransformExact.as_oracle)rJ   rK   rL   r_   r|   rO   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformIExactNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformIContainsNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformStartsWithNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformIStartsWithNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformEndsWithNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformIEndsWithNr   r   r   r   r   r      s   r   c                   @   s   e Zd ZdS )KeyTransformRegexNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformIRegexNr   r   r   r   r   r   
  s   r   c                       s   e Zd Z fddZ  ZS )KeyTransformNumericLookupMixinc                    s0   t  ||\}}|jjs(dd |D }||fS )Nc                 S   s   g | ]}t |qS r   )r8   r9   )r   r;   r   r   r   r     s     z>KeyTransformNumericLookupMixin.process_rhs.<locals>.<listcomp>)r   r_   r*   r   r   r   r   r   r_     s    z*KeyTransformNumericLookupMixin.process_rhs)rJ   rK   rL   r_   rO   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformLtNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformLteNr   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )KeyTransformGtNr   r   r   r   r   r      s   r   c                   @   s   e Zd ZdS )KeyTransformGteNr   r   r   r   r   r   $  s   r   c                   @   s   e Zd Zdd Zdd ZdS )rC   c                 C   s
   || _ d S rA   )r   )r   r   r   r   r   r   ;  s    zKeyTransformFactory.__init__c                 O   s   t | jf||S rA   )r6   r   )r   r1   r   r   r   r   __call__>  s    zKeyTransformFactory.__call__N)rJ   rK   rL   r   r   r   r   r   r   rC   :  s   rC   )T)Gr8   Zdjangor   Zdjango.corer   r   Z	django.dbr   r   r   Zdjango.db.modelsr   Zdjango.db.models.lookupsr	   r
   Zdjango.utils.translationr   rM   rR   r   Zmixinsr   __all__r   rY   rZ   rk   rl   r   r   r   r   r   r   r   Z	IContainsr   Zregister_lookupr6   r   r   ZIsNullr   ZInr   r   ZIExactr   r   Z
StartsWithr   ZIStartsWithr   ZEndsWithr   Z	IEndsWithr   Regexr   ZIRegexr   r   ZLessThanr   ZLessThanOrEqualr   ZGreaterThanr   ZGreaterThanOrEqualr   rC   r   r   r   r   <module>   s   q
@	






8(
  
  
  
  
  














