o
    [h[                     @   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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zddlZW n eyf   ddlZY nw W n eys   e	dw dd Z e  dk re	dej! de    krdk rn ne	dej! ddl"m#Z#m$Z$ e$rddlm%Z%m&Z& ddl'm(Z( ddl"m)Z)m*Z* e%j+d j,Z-n)ddl.Zddl/Zej01eej0j2 ej34  dZ5ej06e5fdej0j7Z8ej09e8 ddl:m;Z; ddl<m=Z= dd l>m?Z? dd!l@mAZA dd"lBmCZC dd#lDmEZE d$d% ZFG d&d' d'eZGe$rOG d(d) d)ZHG d*d+ d+eHejIZJG d,d- d-eHejKZIG d.d/ d/eHejLjMejNZOG d0d1 d1eZdS ej0jPZIG d2d1 d1eZdS )3zY
PostgreSQL database backend for Django.

Requires psycopg2 >= 2.8.4 or psycopg >= 3.1.8
    N)contextmanager)settings)ImproperlyConfigured)DatabaseError)connections)NO_DB_ALIASBaseDatabaseWrapperCursorDebugWrapper)async_unsafe)cached_property)
SafeString)get_version_tuplez(Error loading psycopg2 or psycopg modulec                  C   s   t jddd } t| S )N    r   )Database__version__splitr   )version r   /home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/venv/lib/python3.10/site-packages/django/db/backends/postgresql/base.pypsycopg_version    s   r   )         z6psycopg2 version 2.8.4 or newer is required; you have )   )r   r   r   z5psycopg version 3.1.8 or newer is required; you have r   )IsolationLevelis_psycopg3)adapterssql)Format)get_adapters_templateregister_tzloaderZtimestamptzi  	INETARRAY)DatabaseClient)DatabaseCreation)DatabaseFeatures)DatabaseIntrospection)DatabaseOperations)DatabaseSchemaEditorc                 C   s   | d d u rdS d|  S )N
max_lengthZvarcharvarchar(%(max_length)s)r   )datar   r   r   _get_varchar_columnS   s   r-   c                       s  e Zd ZdZdZi ddddddd	d
de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 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/d0d1d2d+d+d,d,d3Z	d4Z
d5d6d7d8d9d:d;ZeZeZeZeZeZeZeZd<Zi Zed=d> Zd?d@ ZdAdB ZdCdD Ze dEdF Z!dGdH Z"dIdJ Z#dKdL Z$dMdN Z%dOdP Z& fdQdRZ'e dhdTdUZ(dVdW Z)e dXdY Z*dZd[ Z+dhd\d]Z,d^d_ Z- fd`daZ.e/ fdbdcZ0e1ddde Z2dfdg Z3  Z4S )iDatabaseWrapper
postgresqlZ
PostgreSQL	AutoFieldintegerBigAutoFieldZbigintZBinaryFieldZbyteaZBooleanFieldbooleanZ	CharFieldZ	DateFielddateZDateTimeFieldztimestamp with time zoneZDecimalFieldz+numeric(%(max_digits)s, %(decimal_places)s)ZDurationFieldintervalZ	FileFieldr+   ZFilePathFieldZ
FloatFieldzdouble precisionZIntegerFieldZBigIntegerFieldZIPAddressFieldZinetZGenericIPAddressFieldZ	JSONFieldZjsonbZsmallinttexttimeuuid)
ZOneToOneFieldPositiveBigIntegerFieldPositiveIntegerFieldPositiveSmallIntegerFieldZ	SlugFieldSmallAutoFieldZSmallIntegerFieldZ	TextFieldZ	TimeFieldZ	UUIDFieldz"%(column)s" >= 0)r9   r:   r;   z GENERATED BY DEFAULT AS IDENTITY)r0   r2   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>   r?   rC   rE   rD   rF   r   c              
   C   s   | j d d}| jtks|sd S | j| jvrk| j dddkr$td|du r*i }zddlm} W n tyC } ztd|d }~ww | 	 }d|d	< | j d
 }|d|d| j
|r\|jnd d|}| j| j| | j| j S )NOPTIONSpoolZCONN_MAX_AGEr   z/Pooling doesn't support persistent connections.T)ConnectionPoolzAError loading psycopg_pool module.
Did you install psycopg[pool]?
autocommitZCONN_HEALTH_CHECKSF)kwargsopen	configurecheckr   )settings_dictgetaliasr   _connection_poolsr   Zpsycopg_poolrI   ImportErrorget_connection_params_configure_connectionZcheck_connection
setdefault)selfpool_optionsrI   errZconnect_kwargsZenable_checksrH   r   r   r   rH      sB   
zDatabaseWrapper.poolc                 C   s"   | j r| j   | j| j= d S d S N)rH   closerR   rQ   rW   r   r   r   
close_pool   s   
zDatabaseWrapper.close_poolc                 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_versionr\   r   r   r   get_database_version   s   z$DatabaseWrapper.get_database_versionc                 C   s  | j }|d dkr|d dstdt|d pd| j kr3td|d t|d | j f |d rBd|d i|d }n|d d u rY|d dd  ddi|d }ni |d }d	|d
< |dd  |dd  |dd }|r}ts}td|dd }|dtr|du rt	nt
 |d r|d |d< |d r|d |d< |d r|d |d< |d r|d |d< trttj| j|d< |dd |d< |S )NNAME rG   Z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dbnamepostgresUTF8Zclient_encodingassume_roleisolation_levelrH   z&Database pooling requires psycopg >= 3server_side_bindingZcursor_factoryTUSERuserZPASSWORDpasswordZHOSThostZPORTportcontextZprepare_threshold)rO   rP   r   lenopsZmax_name_lengthpopr   rV   ServerBindingCursorCursorr!   r   USE_TZtimezone)rW   rO   conn_paramsrX   rg   r   r   r   rT      sl   

z%DatabaseWrapper.get_connection_paramsc                 C   s   | j d }d}z|d }W n ty   tj| _Y nw z	t|| _d}W n ty3   td| dw | jrB| j  | j	 }n	| j
jd
i |}|rQ| j|_ts]tjj|dd d	 |S )NrG   Frf   Tz$Invalid transaction isolation level z9 specified. Use one of the psycopg.IsolationLevel values.c                 S   s   | S rZ   r   )xr   r   r   <lambda>T  s    z4DatabaseWrapper.get_new_connection.<locals>.<lambda>)Zconn_or_cursloadsr   )rO   KeyErrorr   ZREAD_COMMITTEDrf   
ValueErrorr   rH   rL   Zgetconnr   connectr   psycopg2extrasZregister_default_jsonb)rW   ru   optionsZset_isolation_levelZisolation_level_value
connectionr   r   r   get_new_connection0  s4   



z"DatabaseWrapper.get_new_connectionc                 C   s"   |    | jd u rdS | | jS )NF)r]   r   _configure_timezoner\   r   r   r   ensure_timezoneX  s   
zDatabaseWrapper.ensure_timezonec                 C   sd   |j d}| j}|r0||kr0| }|| j |g W d    dS 1 s)w   Y  dS dS )NZTimeZoneTF)infoZparameter_statustimezone_namecursorexecutero   Zset_time_zone_sql)rW   r   Zconn_timezone_namer   r   r   r   r   r   _  s   

z#DatabaseWrapper._configure_timezonec                 C   s`   | j d d }r.| }| jd|g}|| W d    dS 1 s'w   Y  dS dS )NrG   re   zSET ROLE %sTF)rO   rP   r   ro   Zcompose_sqlr   )rW   r   Znew_roler   r   r   r   r   _configure_roleh  s   

zDatabaseWrapper._configure_rolec                 C   s   |  |}| |}|p|S rZ   )r   r   )rW   r   Z	commit_tzZcommit_roler   r   r   rU   p  s   

z%DatabaseWrapper._configure_connectionc                 C   sp   | j d ur6| j$ | jr| j j| j  d | _ n| j  W  d    S W d    d S 1 s/w   Y  d S d S rZ   )r   wrap_database_errorsrH   _poolZputconnr[   r\   r   r   r   _close}  s   
"zDatabaseWrapper._closec                    sP   t    | jd ur | js"| | j}|r$|  s&| j  d S d S d S d S d S rZ   )superinit_connection_stater   rH   rU   Zget_autocommitcommit)rW   r   	__class__r   r   r     s   
z%DatabaseWrapper.init_connection_stateNc                 C   s   |r&t r| jd ddurt| j|d| jjd}n| jj|d| jjd}n| j }t rD| jjt	t
j}| j|jkrBt| j| |S tjrJ| jnd |_|S )NrG   rg   TF)name
scrollablewithhold)r   r   )r   rO   rP   ServerSideCursorr   rJ   r   r   
get_loaderTIMESTAMPTZ_OIDr    ZTEXTrt   r"   r   rs   tzinfo_factory)rW   r   r   Ztzloaderr   r   r   create_cursor  s(   	

zDatabaseWrapper.create_cursorc                 C   s   | j S rZ   )rt   )rW   offsetr   r   r   r     s   zDatabaseWrapper.tzinfo_factoryc                 C   sf   |  j d7  _ zt }W n ty   d }Y nw |r"t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)rW   r   Z
task_identr   r   r   chunked_cursor  s"   zDatabaseWrapper.chunked_cursorc                 C   s4   | j  || j_W d    d S 1 sw   Y  d S rZ   )r   r   rJ   )rW   rJ   r   r   r   _set_autocommit  s   
"zDatabaseWrapper._set_autocommitc                 C   sB   |   }|d |d W d   dS 1 sw   Y  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   )rW   Ztable_namesr   r   r   r   check_constraints  s   

"z!DatabaseWrapper.check_constraintsc                 C   sd   | j d u rdS z| j  }|d W d    W dS 1 sw   Y  W dS  tjy1   Y dS w )NFzSELECT 1T)r   r   r   r   ErrorrW   r   r   r   r   	is_usable  s   
zDatabaseWrapper.is_usablec                    s   | j rd S t  S rZ   )rH   r   close_if_health_check_failedr\   r   r   r   r     s   
z,DatabaseWrapper.close_if_health_check_failedc                 #   s   d }zt   }|V  W d    W d S 1 sw   Y  W d S  tjtfy   |d ur/ tdt t	 D ]G}|j
dkr|jd dkr| ji | jd|jd i| jd}z| }|V  W d    n1 slw   Y  W |  n|  w  Y d S q9 w )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/   ra   rc   )rQ   )r   _nodb_cursorr   r   WrappedDatabaseErrorwarningswarnRuntimeWarningr   allvendorrO   r   rQ   r   r[   )rW   r   r   connr   r   r   r     sD   &


zDatabaseWrapper._nodb_cursorc                 C   s6   |    | jjjW  d    S 1 sw   Y  d S rZ   )Ztemporary_connectionr   r   Zserver_versionr\   r   r   r   r_     s   
$zDatabaseWrapper.pg_versionc                 C   s
   t || S rZ   r	   r   r   r   r   make_debug_cursor"  s   
z!DatabaseWrapper.make_debug_cursorrZ   )5__name__
__module____qualname__r   display_namer-   
data_typesZdata_type_check_constraintsZdata_types_suffix	operatorsZpattern_escZpattern_opsr   r)   ZSchemaEditorClassr$   Zclient_classr%   Zcreation_classr&   Zfeatures_classr'   Zintrospection_classr(   Z	ops_classr   rR   propertyrH   r]   r`   rT   r   r   r   r   r   rU   r   r   r   r   r   r   r   r   r   r   r   r   r_   r   __classcell__r   r   r   r   r.   Y   s    	
	
(C
'		"

	%
r.   c                   @   s   e Zd ZdZdddZdS )CursorMixinzE
        A subclass of psycopg cursor implementing callproc.
        Nc                 C   s   t |tjst|}td|tdg}|r0|D ]}|t| |td q|d= |td t|}| | |S )NzSELECT * FROM (,))
isinstancer   Z
IdentifierSQLappendLiteralZComposedr   )rW   r   argsZqpartsitemstmtr   r   r   callproc-  s   


zCursorMixin.callprocrZ   )r   r   r   __doc__r   r   r   r   r   r   (  s    r   c                   @      e Zd ZdS )rq   Nr   r   r   r   r   r   r   rq   =      rq   c                   @   r   )rr   Nr   r   r   r   r   rr   @  r   rr   c                   @   s   e Zd ZdZdS )r   aD  
        psycopg >= 3 forces the usage of server-side bindings when using named
        cursors but the ORM doesn't yet support the systematic generation of
        prepareable SQL (#20516).

        ClientCursorMixin forces the usage of client-side bindings while
        ServerCursor implements the logic required to declare and scroll
        through named cursors.

        Mixing ClientCursorMixin in wouldn't be necessary if Cursor allowed to
        specify how parameters should be bound instead, which ServerCursor
        would inherit, but that's not the case.
        N)r   r   r   r   r   r   r   r   r   C  s    r   c                   @   s   e Zd Zdd ZdS )r
   c                 C   s:   |  | | j|W  d    S 1 sw   Y  d S rZ   )	debug_sqlr   copy)rW   Z	statementr   r   r   r   U  s   
$zCursorDebugWrapper.copyN)r   r   r   r   r   r   r   r   r
   T  s    r
   c                   @   s   e Zd Zdd Zdd ZdS )r
   c                 G   sD   |  | | jj||g|R  W  d    S 1 sw   Y  d S rZ   )r   r   copy_expert)rW   r   filer   r   r   r   r   ]  s   $zCursorDebugWrapper.copy_expertc                 O   sP   | j d| d | jj||g|R i |W  d    S 1 s!w   Y  d S )NzCOPY %s TO STDOUT)r   )r   r   copy_to)rW   r   tabler   rK   r   r   r   r   a  s   $zCursorDebugWrapper.copy_toN)r   r   r   r   r   r   r   r   r   r
   \  s    )Qr   r   r   r   
contextlibr   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   r   r   Zdjango.db.backends.base.baser   r   Zdjango.db.backends.utilsr
   ZBaseCursorDebugWrapperZdjango.utils.asyncior   Zdjango.utils.functionalr   Zdjango.utils.safestringr   Zdjango.utils.versionr   Zpsycopgr   rS   r|   r   r   Zpsycopg_anyr   r   r   r   Z
psycopg.pqr    r!   r"   typesoidr   Zpsycopg2.extensionsZpsycopg2.extras
extensionsZregister_adapterZQuotedStringr}   Zregister_uuidZINETARRAY_OIDZnew_array_typeUNICODEr#   Zregister_typeclientr$   Zcreationr%   featuresr&   Zintrospectionr'   
operationsr(   Zschemar)   r-   r.   r   rr   rq   ZClientCursorZclient_cursorZClientCursorMixinZServerCursorr   r   r   r   r   r   <module>   s    



   P
