o
    bM                  
   @   s  d 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mZ zddlZddlmZmZ W n eyc Z zededZ[ww z
ddlmZmZ W n eyy   dZ Y nw d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. ej/j0Z0ej/j1Z1ej/j2Z2ej/j3Z3ej/j4Z4dd Z5G dd dZ6G dd deZG dd  d eZ7G d!d" d"eZ8dS )#a  Django database Backend using MySQL Connector/Python.

This Django database backend is heavily based on the MySQL backend from Django.

Changes include:
* Support for microseconds (MySQL 5.6.3 and later)
* Using INFORMATION_SCHEMA where possible
* Using new defaults for, for example SQL_AUTO_IS_NULL

Requires and comes with MySQL Connector/Python v8.0.22 and later:
    http://dev.mysql.com/downloads/connector/python/
    N)datetime)settings)ImproperlyConfigured)IntegrityError)BaseDatabaseWrapper)DatabaseWrapper)utils)cached_property)	dateparsetimezone)MySQLConverterMySQLConverterBasez)Error loading mysql.connector module: {0})datetime_to_mysqltime_to_mysqlFT   )DatabaseClient)DatabaseCreation)DatabaseIntrospection)DatabaseValidation)DatabaseFeatures)DatabaseOperations)DatabaseSchemaEditorc                 C   s^   t jr$t| rtd|  t t }t| |} | 	tj
jd d} tr*t| S | dS )NzGMySQL received a naive datetime (%s) while time zone support is active.tzinfoz%Y-%m-%d %H:%M:%S.%f)r   USE_TZr   is_naivewarningswarnRuntimeWarningZget_default_timezoneZ
make_aware
astimezoneutcreplace	HAVE_CEXTr   strftime)valueZdefault_timezone r%   Z/var/www/secure340b-portal/env/lib/python3.10/site-packages/mysql/connector/django/base.py$adapt_datetime_with_timezone_supportV   s   

r'   c                   @   sN   e Zd ZdZdZdd Zdd Zdd Zdd
dZdd Z	dd Z
dd Zd	S )CursorWrapperzWrapper around MySQL Connector/Python's cursor class.

    The cursor class is defined by the options passed to MySQL
    Connector/Python. If buffered option is True in those options,
    MySQLCursorBuffered will be used.
    )i  i  i  i  c                 C   s
   || _ d S N)cursorselfr*   r%   r%   r&   __init__t      
zCursorWrapper.__init__c                 C   s<   |s|S t |}| D ]\}}t|trt|||< q|S r)   )dictitems
isinstancer   r'   )r,   argsnew_argskeyr$   r%   r%   r&   _adapt_execute_args_dictw   s   
z&CursorWrapper._adapt_execute_args_dictc                 C   s@   |s|S t |}t|D ]\}}t|trt|||< qt|S r)   )list	enumerater1   r   r'   tuple)r,   r2   r3   iargr%   r%   r&   _adapt_execute_args   s   
z!CursorWrapper._adapt_execute_argsNc              
   C   sn   t |tr| |}n| |}z| j||W S  tjjy6 } z|j	d | j
v r1tt|j	  d}~ww )zExecutes the given operation

        This wrapper method around the execute()-method of the cursor is
        mainly needed to re-raise using different exceptions.
        r   N)r1   r/   r5   r;   r*   executemysql	connectorOperationalErrorr2   codes_for_integrityerrorr   r8   )r,   queryr2   r3   er%   r%   r&   r<      s   

zCursorWrapper.executec              
   C   sN   z| j ||W S  tjjy& } z|jd | jv r!tt|j  d}~ww )zExecutes the given operation

        This wrapper method around the executemany()-method of the cursor is
        mainly needed to re-raise using different exceptions.
        r   N)	r*   executemanyr=   r>   r?   r2   r@   r   r8   )r,   rA   r2   rB   r%   r%   r&   rC      s   zCursorWrapper.executemanyc                 C   s   t | j|S )z"Return attribute of wrapped cursor)getattrr*   r,   attrr%   r%   r&   __getattr__   s   zCursorWrapper.__getattr__c                 C   s
   t | jS )z$Returns iterator over wrapped cursor)iterr*   r,   r%   r%   r&   __iter__   s   
zCursorWrapper.__iter__r)   )__name__
__module____qualname____doc__r@   r-   r5   r;   r<   rC   rG   rJ   r%   r%   r%   r&   r(   f   s    


r(   c                       s  e Zd ZdZi 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	dd!d"d#dd$d%d&d'd(d)Zd*Zd+d,d-d,d.d/d0d1d2d3d-d-d,d,d4Zd5Zd6d7d8d9d:d;d<Zh d=Z	e
jZeZeZeZeZeZeZeZ fd>d?Zd@dA ZdBdC ZdDdE ZdFdG ZdcdIdJZ dKdL Z!dMdN Z"dOdP Z#dQdR Z$dcdSdTZ%dUdV Z&e'dWdX Z(e'dYdZ Z)e'd[d\ Z*e'd]d^ Z+e'd_d` Z,e-dadb Z.  Z/S )dr   r=   Z	AutoFieldzinteger AUTO_INCREMENTZBigAutoFieldzbigint AUTO_INCREMENTZBinaryFieldlongblobZBooleanFieldboolZ	CharFieldzvarchar(%(max_length)s)Z	DateFielddateZDateTimeFieldzdatetime(6)ZDecimalFieldz+numeric(%(max_digits)s, %(decimal_places)s)ZDurationFieldZbigintZ	FileFieldZFilePathFieldZ
FloatFieldzdouble precisionZIntegerFieldintegerZBigIntegerFieldZIPAddressFieldzchar(15)ZGenericIPAddressFieldzchar(39)Z	JSONFieldjsonzbigint UNSIGNEDzinteger UNSIGNEDzsmallint UNSIGNEDzsmallint AUTO_INCREMENTZsmallintlongtextztime(6)zchar(32))ZNullBooleanFieldZOneToOneFieldPositiveBigIntegerFieldPositiveIntegerFieldPositiveSmallIntegerFieldZ	SlugFieldZSmallAutoFieldZSmallIntegerFieldZ	TextFieldZ	TimeFieldZ	UUIDField)	ZtinyblobZblobZ
mediumblobrO   ZtinytexttextZ
mediumtextrT   rS   z= %szLIKE %szLIKE BINARY %szREGEXP BINARY %sz	REGEXP %sz> %sz>= %sz< %sz<= %s)exactZiexactcontains	icontainsregexZiregexgtZgteltZlte
startswithendswithistartswith	iendswithzCREPLACE(REPLACE(REPLACE({}, '\\', '\\\\'), '%%', '\%%'), '_', '\_')z"LIKE BINARY CONCAT('%%', {}, '%%')zLIKE CONCAT('%%', {}, '%%')zLIKE BINARY CONCAT({}, '%%')zLIKE CONCAT({}, '%%')zLIKE BINARY CONCAT('%%', {})zLIKE CONCAT('%%', {}))rZ   r[   r_   ra   r`   rb   >   serializableread committedrepeatable readread uncommittedc                    sd   t t| j|i | z
| jd d | _W n ty"   t | _Y nw | jr,t | _
d S t	 | _
d S )NOPTIONSuse_pure)superr   r-   settings_dict	_use_pureKeyErrorr"   rh   DjangoMySQLConverterDjangoCMySQLConverter	converter)r,   r2   kwargs	__class__r%   r&   r-     s   zDatabaseWrapper.__init__c                 C   s   | drdS t)NZmysql_isF)r_   AttributeErrorrE   r%   r%   r&   rG      s   
zDatabaseWrapper.__getattr__c                 C   s   ddddd}| j }|d r|d |d< |d r|d |d< |d	 r(|d	 |d
< |d dr6|d |d< n
|d r@|d |d< |d rLt|d |d< tj|d< tjjjj	g|d< z
|
|d  W |S  tyn   Y |S w )Nutf8TF)charsetZuse_unicodebufferedZconsume_resultsUSERuserNAMEZdatabaseZPASSWORDpasswdZHOST/Zunix_sockethostZPORTportZraise_on_warningsZclient_flagsrg   )rj   r_   intr   DEBUGr=   r>   	constantsZ
ClientFlagZ
FOUND_ROWSupdaterl   )r,   rp   rj   r%   r%   r&   get_connection_params%  s8   

z%DatabaseWrapper.get_connection_paramsc                 C   s.   | j st|d< nt|d< tjjdi |}|S )NZconverter_classr%   )rh   rn   rm   r=   r>   connect)r,   Zconn_paramsZcnxr%   r%   r&   get_new_connectionK  s
   
z"DatabaseWrapper.get_new_connectionc                 C   s   g }| j jr|d |r)|  }|d| W d    n1 s$w   Y  d| jv rLz| | jd  W d S  tyK   | 	| jd  Y d S w d S )NzSET SQL_AUTO_IS_NULL = 0z; Z
AUTOCOMMIT)
featuresZis_sql_auto_is_null_enabledappendr*   r<   joinrj   Zset_autocommitrs   _set_autocommit)r,   Zassignmentsr*   r%   r%   r&   init_connection_stateT  s   


z%DatabaseWrapper.init_connection_stateNc                 C   s   | j  }t|S r)   )
connectionr*   r(   )r,   namer*   r%   r%   r&   create_cursorg  s   
zDatabaseWrapper.create_cursorc                 C   s&   zt |  W d S  ty   Y d S w r)   )r   	_rollbackNotSupportedErrorrI   r%   r%   r&   r   k  s
   zDatabaseWrapper._rollbackc                 C   s4   | j  || j_W d    d S 1 sw   Y  d S r)   )Zwrap_database_errorsr   
autocommit)r,   r   r%   r%   r&   r   q  s   
"zDatabaseWrapper._set_autocommitc                 C   s8   |   }|d W d   dS 1 sw   Y  dS )z
        Disable foreign key checks, primarily for use in adding rows with
        forward references. Always return True to indicate constraint checks
        need to be re-enabled.
        zSET foreign_key_checks=0NT)r*   r<   r+   r%   r%   r&   disable_constraint_checkingu  s   

z+DatabaseWrapper.disable_constraint_checkingc                 C   sb   d| j | _ }z%|  }|d W d   n1 sw   Y  W || _ dS W || _ dS || _ w )zM
        Re-enable foreign key checks after they have been disabled.
        FzSET foreign_key_checks=1N)needs_rollbackr*   r<   )r,   r   r*   r%   r%   r&   enable_constraint_checking  s   

z*DatabaseWrapper.enable_constraint_checkingc           
      C   s   |   W}|du r| j|}|D ]A}| j||}|sq| j||}|D ]+\}}}|d||||||||f  | D ]}	td||	d |||	d ||f q&qW d   dS 1 s^w   Y  dS )a]  
        Check each table name in `table_names` for rows with invalid foreign
        key references. This method is intended to be used in conjunction with
        `disable_constraint_checking()` and `enable_constraint_checking()`, to
        determine if rows with invalid references were entered while constraint
        checks were off.
        Na0  
                        SELECT REFERRING.`%s`, REFERRING.`%s` FROM `%s` as REFERRING
                        LEFT JOIN `%s` as REFERRED
                        ON (REFERRING.`%s` = REFERRED.`%s`)
                        WHERE REFERRING.`%s` IS NOT NULL AND REFERRED.`%s` IS NULL
                        zThe row in table '%s' with primary key '%s' has an invalid foreign key: %s.%s contains a value '%s' that does not have a corresponding value in %s.%s.r   r   )r*   introspectiontable_namesZget_primary_key_columnZget_key_columnsr<   Zfetchallr   )
r,   r   r*   Z
table_nameZprimary_key_column_nameZkey_columnsZcolumn_nameZreferenced_table_nameZreferenced_column_nameZbad_rowr%   r%   r&   check_constraints  s:   

"z!DatabaseWrapper.check_constraintsc                 C   s&   z| j   W dS  ty   Y dS w )NFT)r   ZpingErrorrI   r%   r%   r&   	is_usable  s   zDatabaseWrapper.is_usablec                 C   s   dS )NMySQLr%   rI   r%   r%   r&   display_name  s   zDatabaseWrapper.display_namec                 C   s   | j jrdddd}|S i S )Nz`%(column)s` >= 0)rU   rV   rW   )r   Z!supports_column_check_constraints)r,   r   r%   r%   r&   data_type_check_constraints  s   z+DatabaseWrapper.data_type_check_constraintsc                 C   sB   |   }|d | d W  d    S 1 sw   Y  d S )NzSELECT VERSION()r   )Ztemporary_connectionr<   fetchoner+   r%   r%   r&   mysql_server_info  s   


$z!DatabaseWrapper.mysql_server_infoc                 C   sH   |   }tjjdi |}| }W d    |S 1 sw   Y  |S )Nr%   )r   r=   r>   r   Zget_server_version)r,   configconnZserver_versionr%   r%   r&   mysql_version  s   

zDatabaseWrapper.mysql_versionc                 C   sV   |   }|d | }W d    n1 sw   Y  t|r(|d dS dS )NzSELECT @@sql_moder   ,r%   )r*   r<   r   setsplit)r,   r*   sql_moder%   r%   r&   r     s
   


zDatabaseWrapper.sql_modec                 C   s   | j S r)   )rk   rI   r%   r%   r&   rh     s   zDatabaseWrapper.use_purer)   )0rK   rL   rM   vendor
data_typesZ_limited_data_types	operatorsZpattern_escZpattern_opsZisolation_levelsr=   r>   ZDatabaser   ZSchemaEditorClassr   Zclient_classr   Zcreation_classr   Zfeatures_classr   Zintrospection_classr   Z	ops_classr   Zvalidation_classr-   rG   r   r   r   r   r   r   r   r   r   r   r	   r   r   r   r   r   propertyrh   __classcell__r%   r%   rq   r&   r      s    	
$	&	


(





r   c                   @   s<   e Zd ZdZdddZdddZdd Zd	d
 Zdd ZdS )rm   z/Custom converter for Django for MySQLConnectionNc                 C   s   t |dS )XReturn MySQL TIME data type as datetime.time()

        Returns datetime.time()
        zutf-8)r
   
parse_timedecoder,   r$   dscr%   r%   r&   _TIME_to_python  s   z$DjangoMySQLConverter._TIME_to_pythonc                 C   sB   |sdS t | |}|du rdS tjrt|r|jtjd}|S a  Connector/Python always returns naive datetime.datetime

        Connector/Python always returns naive timestamps since MySQL has
        no time zone support. Since Django needs non-naive, we need to add
        the UTC time zone.

        Returns datetime.datetime()
        Nr   )r   Z_DATETIME_to_pythonr   r   r   r   r!   r    )r,   r$   r   dtr%   r%   r&   __DATETIME_to_python  s   	z)DjangoMySQLConverter.__DATETIME_to_pythonc                 C   
   |  |S r)   Z_str_to_mysqlr,   r$   r%   r%   r&   _safestring_to_mysql   r.   z)DjangoMySQLConverter._safestring_to_mysqlc                 C   r   r)   r   r   r%   r%   r&   _safetext_to_mysql  r.   z'DjangoMySQLConverter._safetext_to_mysqlc                 C   r   r)   )Z_bytes_to_mysqlr   r%   r%   r&   _safebytes_to_mysql  r.   z(DjangoMySQLConverter._safebytes_to_mysqlr)   )	rK   rL   rM   rN   r   Z)_DjangoMySQLConverter__DATETIME_to_pythonr   r   r   r%   r%   r%   r&   rm     s    

rm   c                   @   s$   e Zd ZdZdddZdddZdS )rn   z0Custom converter for Django for CMySQLConnectionNc                 C   s   t t|S )r   )r
   r   strr   r%   r%   r&   r     s   z%DjangoCMySQLConverter._TIME_to_pythonc                 C   s*   |sdS t jrt|r|jtjd}|S r   )r   r   r   r   r!   r    r   r%   r%   r&   r     s
   	z*DjangoCMySQLConverter.__DATETIME_to_pythonr)   )rK   rL   rM   rN   r   Z*_DjangoCMySQLConverter__DATETIME_to_pythonr%   r%   r%   r&   rn   
  s    
rn   )9rN   r   sysr   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.db.backends.base.baser   Zdjango.db.backends.mysql.baser   ZMySQLDatabaseWrapperr   Zdjango.utils.functionalr	   Zdjango.utilsr
   r   Zmysql.connectorr=   Zmysql.connector.conversionr   r   ImportErrorerrformatZ_mysql_connectorr   r   r"   clientr   Zcreationr   r   r   Z
validationr   r   r   
operationsr   Zschemar   r>   r   ZDatabaseErrorr   r?   ZProgrammingErrorr'   r(   rm   rn   r%   r%   r%   r&   <module>   s\   L  5%