U
     5øiý4  ã                
   @   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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j0 1eej0j2¡ ej3 4¡  dZ5ej0 6e5fdej0j7¡Z8ej0 9e8¡ 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-gcyiijx6/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                       s<  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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ed/d0„ ƒZd1d2„ Zd3d4„ ZedHd6d7„ƒZd8d9„ Zed:d;„ ƒZd<d=„ Z dId>d?„Z!d@dA„ Z"e#‡ fdBdC„ƒZ$e%dDdE„ ƒZ&dFdG„ Z'‡  Z(S )JÚDatabaseWrapperÚ
postgresqlZ
PostgreSQLÚserialZ	bigserialZbyteaÚbooleanzvarchar(%(max_length)s)Údateztimestamp with time zonez+numeric(%(max_digits)s, %(decimal_places)s)Úintervalzdouble precisionÚintegerZbigintZinetZjsonbZsmallintZsmallserialÚtextÚtimeÚuuid)Z	AutoFieldZBigAutoFieldZBinaryFieldZBooleanFieldZ	CharFieldZ	DateFieldZDateTimeFieldZDecimalFieldZDurationFieldZ	FileFieldZFilePathFieldZ
FloatFieldZIntegerFieldZBigIntegerFieldZIPAddressFieldZGenericIPAddressFieldZ	JSONFieldZOneToOneFieldÚPositiveBigIntegerFieldÚPositiveIntegerFieldÚPositiveSmallIntegerFieldZ	SlugFieldZSmallAutoFieldZSmallIntegerFieldZ	TextFieldZ	TimeFieldZ	UUIDFieldz"%(column)s" >= 0)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({}))r/   r0   r4   r6   r5   r7   r   c                 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 rŒd|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.z‡The 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)ÚselfrB   Úconn_paramsr   r   r   Úget_connection_params˜   sL    
ÿþÿ
ýþÿ	 ÿþ


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 )Nr:   r<   )r<   c                 S   s   | S ©Nr   )Úxr   r   r   Ú<lambda>Ú   ó    z4DatabaseWrapper.get_new_connection.<locals>.<lambda>)Zconn_or_cursÚloads)	ÚDatabaseÚconnectrB   r<   ÚKeyErrorZset_sessionr   ÚextrasZregister_default_jsonb)rG   rH   Ú
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)rS   Zget_parameter_statusÚtimezone_nameÚcursorÚexecuterE   Zset_time_zone_sql)rG   Zconn_timezone_namerV   rW   r   r   r   Úensure_timezoneÝ   s    
zDatabaseWrapper.ensure_timezonec                 C   s.   | j  d¡ |  ¡ }|r*|  ¡ s*| j  ¡  d S )NÚUTF8)rS   Zset_client_encodingrY   Zget_autocommitÚcommit)rG   Ztimezone_changedr   r   r   Úinit_connection_stateè   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)rS   rW   Ú
autocommitr   ZUSE_TZÚtzinfo_factory)rG   ÚnamerW   r   r   r   Úcreate_cursorñ   s
    
zDatabaseWrapper.create_cursorc                 C   s   | j S rJ   )Útimezone)rG   Úoffsetr   r   r   r^   ü   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)r_   )
Ú_named_cursor_idxÚasyncioÚcurrent_taskÚRuntimeErrorÚstrÚidZ_cursorÚ	threadingÚcurrent_threadÚident)rG   rf   Z
task_identr   r   r   Úchunked_cursorÿ   s    
üÿzDatabaseWrapper.chunked_cursorc              	   C   s   | j � || j_W 5 Q R X d S rJ   )Zwrap_database_errorsrS   r]   )rG   r]   r   r   r   Ú_set_autocommit  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)rW   rX   )rG   Ztable_namesrW   r   r   r   Úcheck_constraints  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)rS   rW   rX   rO   ÚError©rG   rW   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  qÆqX‚ 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"   r8   r;   )Úalias)ÚsuperÚ_nodb_cursorrO   r   ÚWrappedDatabaseErrorÚwarningsÚwarnÚRuntimeWarningr   ÚallÚvendorrB   Ú	__class__rs   ÚcloserW   )rG   rW   rS   Úconn©r|   r   r   ru   1  s.    úþ

zDatabaseWrapper._nodb_cursorc              
   C   s(   |   ¡ � | jjW  5 Q R £ S Q R X d S rJ   )Ztemporary_connectionrS   Zserver_version)rG   r   r   r   Ú
pg_versionQ  s    
zDatabaseWrapper.pg_versionc                 C   s
   t || ƒS rJ   r   rq   r   r   r   Úmake_debug_cursorV  s    z!DatabaseWrapper.make_debug_cursor)N)N))Ú__name__Ú
__module__Ú__qualname__r{   Zdisplay_nameÚ
data_typesZdata_type_check_constraintsÚ	operatorsZpattern_escZpattern_opsrO   r   ZSchemaEditorClassr   Zclient_classr   Zcreation_classr   Zfeatures_classr   Zintrospection_classr   Z	ops_classrd   rI   r
   rU   rY   r\   r`   r^   rm   rn   ro   rr   r   ru   r   r€   r�   Ú__classcell__r   r   r   r   r!   A   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 rJ   )Ú	debug_sqlrW   Úcopy_expert)rG   ÚsqlÚfileÚargsr   r   r   r‰   [  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ˆ   rW   Úcopy_to)rG   r‹   ÚtablerŒ   Úkwargsr   r   r   r�   _  s    zCursorDebugWrapper.copy_toN)r‚   rƒ   r„   r‰   r�   r   r   r   r   r	   Z  s   r	   );Ú__doc__re   rj   rw   Ú
contextlibr   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   rv   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   rO   Zpsycopg2.extensionsZpsycopg2.extrasÚImportErrorÚer   ZPSYCOPG2_VERSIONr   Úclientr   Zcreationr   Úfeaturesr   Zintrospectionr   Ú
operationsr   Zschemar   Ú
extensionsZregister_adapterÚQuotedStringrR   Zregister_uuidZINETARRAY_OIDZnew_array_typeÚUNICODEr    Zregister_typer!   r   r   r   r   Ú<module>   sT   

ý  