U
    [+d7                  
   @   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	 ddl
mZ ddl
mZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ zddlZddlZddlZW n. ek
r Z  ze	de  W 5 dZ [ X Y nX dd Z!e! Z"e"dk re	dej# ddl$m%Z% ddl&m'Z' ddl(m)Z) ddl*m+Z+ ddl,m-Z- ddl.m/Z/ ej01eej0j2 ej34  dZ5ej06e5fdej0j7Z8ej09e8 G dd deZ:G dd deZdS ) zW
PostgreSQL database backend for Django.

Requires psycopg 2: https://www.psycopg.org/
    N)contextmanager)settings)ImproperlyConfigured)DatabaseError)connections)BaseDatabaseWrapperCursorDebugWrapper)async_unsafe)cached_property)
SafeString)get_version_tuplez!Error loading psycopg2 module: %sc                  C   s   t jddd } t| S )N    r   )psycopg2__version__splitr   )version r   F/tmp/pip-unpacked-wheel-n7e__lmp/django/db/backends/postgresql/base.pypsycopg2_version   s    r   )         z8psycopg2 version 2.8.4 or newer is required; you have %sr   )DatabaseClient)DatabaseCreation)DatabaseFeatures)DatabaseIntrospection)DatabaseOperations)DatabaseSchemaEditori  	INETARRAYc                       sT  e Zd ZdZdZddddddd	d
ddddddddddddddddddddZddddZddddZddddddddd d!ddddd"Zd#Z	d$d%d&d'd(d)d*Z
eZeZeZeZeZeZeZd+Zd,d- Zd.d/ Zed0d1 Zd2d3 Z fd4d5ZedId7d8Zd9d: Z ed;d< Z!d=d> Z"dJd?d@Z#dAdB Z$e% fdCdDZ&e'dEdF Z(dGdH Z)  Z*S )KDatabaseWrapper
postgresqlZ
PostgreSQLintegerZbigintZbyteabooleanzvarchar(%(max_length)s)dateztimestamp with time zonez+numeric(%(max_digits)s, %(decimal_places)s)intervalzdouble precisionZinetZjsonbZsmallinttexttimeuuid)	AutoFieldBigAutoFieldZBinaryFieldZBooleanFieldZ	CharFieldZ	DateFieldZDateTimeFieldZDecimalFieldZDurationFieldZ	FileFieldZFilePathFieldZ
FloatFieldZIntegerFieldZBigIntegerFieldZIPAddressFieldZGenericIPAddressFieldZ	JSONFieldZOneToOneFieldPositiveBigIntegerFieldPositiveIntegerFieldPositiveSmallIntegerFieldZ	SlugFieldSmallAutoFieldZSmallIntegerFieldZ	TextFieldZ	TimeFieldZ	UUIDFieldz"%(column)s" >= 0)r,   r-   r.   z GENERATED BY DEFAULT AS IDENTITY)r*   r+   r/   z= %sz= UPPER(%s)zLIKE %szLIKE UPPER(%s)z~ %sz~* %sz> %sz>= %sz< %sz<= %s)exactZiexactcontains	icontainsregexZiregexgtZgteltZlte
startswithendswithistartswith	iendswithzKREPLACE(REPLACE(REPLACE({}, E'\\', E'\\\\'), E'%%', E'\\%%'), E'_', E'\\_')zLIKE '%%' || {} || '%%'zLIKE '%%' || UPPER({}) || '%%'zLIKE {} || '%%'zLIKE UPPER({}) || '%%'zLIKE '%%' || {}zLIKE '%%' || UPPER({}))r1   r2   r6   r8   r7   r9   r   c                 C   s   t | jdS )zo
        Return a tuple of the database's version.
        E.g. for pg_version 120004, return (12, 4).
        i'  )divmod
pg_versionselfr   r   r   get_database_version   s    z$DatabaseWrapper.get_database_versionc                 C   s,  | j }|d dkr,|di ds,tdt|d p8d| j krjtd|d t|d | j f i }|d rd|d i|d }n<|d d kr|di dd  ddi|d }n
|d }|d	d  |d
 r|d
 |d< |d r|d |d< |d r|d |d< |d r(|d |d< |S )NNAME OPTIONSZservicez`settings.DATABASES is improperly configured. Please supply the NAME or OPTIONS['service'] value.zThe database name '%s' (%d characters) is longer than PostgreSQL's limit of %d characters. Supply a shorter NAME in settings.DATABASES.Zdatabasepostgresisolation_levelUSERuserZPASSWORDpasswordZHOSThostZPORTport)settings_dictgetr   lenopsZmax_name_lengthpop)r=   rI   conn_paramsr   r   r   get_connection_params   sJ    

 


z%DatabaseWrapper.get_connection_paramsc                 C   st   t jf |}| jd }z|d | _W n tk
r@   |j| _Y nX | j|jkr\|j| jd tjj|dd d |S )NrA   rC   )rC   c                 S   s   | S Nr   )xr   r   r   <lambda>       z4DatabaseWrapper.get_new_connection.<locals>.<lambda>)Zconn_or_cursloads)	DatabaseconnectrI   rC   KeyErrorZset_sessionr   extrasZregister_default_jsonb)r=   rN   
connectionoptionsr   r   r   get_new_connection   s    
 z"DatabaseWrapper.get_new_connectionc              	   C   s^   | j d krdS | j d}| j}|rZ||krZ| j  }|| j |g W 5 Q R X dS dS )NFZTimeZoneT)rY   Zget_parameter_statustimezone_namecursorexecuterL   Zset_time_zone_sql)r=   Zconn_timezone_namer\   r]   r   r   r   ensure_timezone   s    
zDatabaseWrapper.ensure_timezonec                    s8   t    | jd |  }|r4|  s4| j  d S )NUTF8)superinit_connection_staterY   Zset_client_encodingr_   Zget_autocommitcommit)r=   Ztimezone_changed	__class__r   r   rb      s    
z%DatabaseWrapper.init_connection_stateNc                 C   s<   |r| j j|d| j jd}n
| j  }tjr2| jnd |_|S )NF)Z
scrollableZwithhold)rY   r]   
autocommitr   ZUSE_TZtzinfo_factory)r=   namer]   r   r   r   create_cursor  s      
zDatabaseWrapper.create_cursorc                 C   s   | j S rP   )timezone)r=   offsetr   r   r   rg     s    zDatabaseWrapper.tzinfo_factoryc                 C   sh   |  j d7  _ zt }W n tk
r2   d }Y nX |rFtt|}nd}| jdt j	|| j f dS )Nr   syncz_django_curs_%d_%s_%d)rh   )
_named_cursor_idxasynciocurrent_taskRuntimeErrorstridZ_cursor	threadingcurrent_threadident)r=   ro   Z
task_identr   r   r   chunked_cursor  s     
zDatabaseWrapper.chunked_cursorc              	   C   s   | j  || j_W 5 Q R X d S rP   )Zwrap_database_errorsrY   rf   )r=   rf   r   r   r   _set_autocommit0  s    zDatabaseWrapper._set_autocommitc              	   C   s,   |   }|d |d W 5 Q R X dS )zl
        Check constraints by setting them to immediate. Return them to deferred
        afterward.
        zSET CONSTRAINTS ALL IMMEDIATEzSET CONSTRAINTS ALL DEFERREDN)r]   r^   )r=   Ztable_namesr]   r   r   r   check_constraints4  s    

z!DatabaseWrapper.check_constraintsc              	   C   sF   z$| j  }|d W 5 Q R X W n tjk
r<   Y dS X dS d S )NzSELECT 1FT)rY   r]   r^   rU   Errorr=   r]   r   r   r   	is_usable=  s    zDatabaseWrapper.is_usablec                 #   s   d }z t   }|V  W 5 Q R X W n tjtfk
r   |d k	rD tdt t	 D ]j}|j
dkrX|jd dkrX| j| jd|jd i| jd}z| }|V  W 5 Q R X W 5 |  X  qqX Y nX d S )Na8  Normally Django will use a connection to the 'postgres' database to avoid running initialization queries against the production database when it's not needed (for example, when running tests). Django was unable to create a connection to the 'postgres' database and will use the first PostgreSQL database instead.r"   r?   rB   )alias)ra   _nodb_cursorrU   r   WrappedDatabaseErrorwarningswarnRuntimeWarningr   allvendorrI   re   r|   closer]   )r=   r]   rY   connrd   r   r   r}   G  s:     

zDatabaseWrapper._nodb_cursorc              
   C   s(   |    | jjW  5 Q R  S Q R X d S rP   )Ztemporary_connectionrY   Zserver_versionr<   r   r   r   r;   m  s    
zDatabaseWrapper.pg_versionc                 C   s
   t || S rP   r   rz   r   r   r   make_debug_cursorr  s    z!DatabaseWrapper.make_debug_cursor)N)N)+__name__
__module____qualname__r   Zdisplay_name
data_typesZdata_type_check_constraintsZdata_types_suffix	operatorsZpattern_escZpattern_opsrU   r   ZSchemaEditorClassr   Zclient_classr   Zcreation_classr   Zfeatures_classr   Zintrospection_classr   Z	ops_classrm   r>   rO   r
   r[   r_   rb   ri   rg   rv   rw   rx   r{   r   r}   r   r;   r   __classcell__r   r   rd   r   r!   C   s   	-



	
%
r!   c                   @   s   e Zd Zdd Zdd ZdS )r	   c              
   G   s6   |  |" | jj||f| W  5 Q R  S Q R X d S rP   )	debug_sqlr]   copy_expert)r=   sqlfileargsr   r   r   r   w  s    zCursorDebugWrapper.copy_expertc              
   O   s>   | j d| d$ | jj||f||W  5 Q R  S Q R X d S )NzCOPY %s TO STDOUT)r   )r   r]   copy_to)r=   r   tabler   kwargsr   r   r   r   {  s    zCursorDebugWrapper.copy_toN)r   r   r   r   r   r   r   r   r   r	   v  s   r	   );__doc__rn   rs   r   
contextlibr   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   r~   r   Zdjango.db.backends.base.baser   Zdjango.db.backends.utilsr	   ZBaseCursorDebugWrapperZdjango.utils.asyncior
   Zdjango.utils.functionalr   Zdjango.utils.safestringr   Zdjango.utils.versionr   r   rU   Zpsycopg2.extensionsZpsycopg2.extrasImportErrorer   ZPSYCOPG2_VERSIONr   clientr   Zcreationr   featuresr   Zintrospectionr   
operationsr   Zschemar   
extensionsZregister_adapterQuotedStringrX   Zregister_uuidZINETARRAY_OIDZnew_array_typeUNICODEr    Zregister_typer!   r   r   r   r   <module>   s^   

  5