o
    9&i"^                  
   @   s&  d Z ddlZddlmZmZ ddlmZmZmZmZm	Z	m
Z
mZ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mZ dd
lmZ 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,m-Z-m.Z.m/Z/m0Z0 W n e1y Z2 zede2 e2dZ2[2ww zddl3m4Z4 W n e1y   dZ5Y nw dZ5ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ddl<m=Z= ddl>m?Z? ddl@mAZA ddlBmCZC ejDjEZEejDjFZFejDjGZGejDjHZHejDjIZIded e0fd!d"ZJG d#d$ d$ZKG d%d& d&eZLG d'd( d(e"ZMd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time)	AnyDict	GeneratorIteratorListOptionalSetTupleUnion)settings)ImproperlyConfigured)IntegrityError)BaseDatabaseWrapper)	dateparsetimezone)cached_property)MySQLConnection)CMySQLConnection)MySQLConverter)MySQLCursor)CMySQLCursor)
HexLiteral)PooledMySQLConnection)ParamsDictTypeParamsSequenceOrDictTypeParamsSequenceTypeRowType
StrOrBytesz&Error loading mysql.connector module: )datetime_to_mysqlFT   )DatabaseClient)DatabaseCreation)DatabaseFeatures)DatabaseIntrospection)DatabaseOperations)DatabaseSchemaEditor)DatabaseValidationvaluereturnc                 C   sf   t jr&t| rtd|  dt t }t| |} | 	tj
jdd} tr.t| }|S | dS )zDEquivalent to DateTimeField.get_db_prep_value. Used only by raw SQL.z!MySQL received a naive datetime (z$) while time zone support is active.N)tzinfoz%Y-%m-%d %H:%M:%S.%f)r   ZUSE_TZr   Zis_naivewarningswarnRuntimeWarningZget_default_timezoneZ
make_aware
astimezoneutcreplace	HAVE_CEXTr    strftime)r)   Zdefault_timezoneZmysql_datetime r4   FC:\wamp64\www\opt\env\Lib\site-packages\mysql/connector/django/base.py$adapt_datetime_with_timezone_supportb   s   


r6   c                   @   s   e Zd ZdZdZdeeef ddfddZe	de
de
fd	d
Ze	dee dee fddZ	ddedee deeeeef ddf  fddZdedeeedf ee f deeeeef ddf  fddZdedefddZdee f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  cursorr*   Nc                 C   s
   || _ d S N)r8   selfr8   r4   r4   r5   __init__      
zCursorWrapper.__init__argsc                 C   s<   | s| S t | }|  D ]\}}t|trt|||< q|S r9   )dictitems
isinstancer   r6   )r>   new_argskeyr)   r4   r4   r5   _adapt_execute_args_dict   s   
z&CursorWrapper._adapt_execute_args_dictc                 C   s@   | s| S t | }t| D ]\}}t|trt|||< qt|S r9   )list	enumeraterA   r   r6   tuple)r>   rB   iargr4   r4   r5   _adapt_execute_args   s   
z!CursorWrapper._adapt_execute_argsqueryc              
   C   st   d}t |tr| |}n| |}z| j||W S  tjjy9 } z|j	d | j
v r4tt|j	 d 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.
        Nr   )rA   r?   rD   rJ   r8   executemysql	connectorOperationalErrorr>   codes_for_integrityerrorr   rG   )r;   rK   r>   rB   excr4   r4   r5   rL      s   

zCursorWrapper.execute.c              
   C   sP   z| j ||W S  tjjy' } z|jd | jv r"tt|j d 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)	r8   executemanyrM   rN   rO   r>   rP   r   rG   )r;   rK   r>   rQ   r4   r4   r5   rR      s   zCursorWrapper.executemanyattrc                 C   s   t | j|S )z%Return an attribute of wrapped cursor)getattrr8   r;   rS   r4   r4   r5   __getattr__   s   zCursorWrapper.__getattr__c                 C   s
   t | jS )z&Return an iterator over wrapped cursor)iterr8   r;   r4   r4   r5   __iter__   s   
zCursorWrapper.__iter__r9   )__name__
__module____qualname____doc__rP   r   r   r   r<   staticmethodr   rD   r	   r   rJ   strr   r   rL   r   r   rR   r   rV   r   r   rY   r4   r4   r4   r5   r7   t   sB    



r7   c                       s  e Zd ZU 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/d0d1d2d3d4d.d.d-d-d5Zd6Zd7d8d9d:d;d<d=Z	d>Z
ee ed?< h d@ZejZeZeZeZeZeZeZeZdAe dBe dCd>f fdDdEZ!dFedCe"fdGdHZ#dCe$ee f fdIdJZ%dKe$ee f dCe&e'e(e)f fdLdMZ*dpdNdOZ+dqdPe dCe,fdQdRZ-dpdSdTZ.dUe"dCd>fdVdWZ/dCe"fdXdYZ0dpdZd[Z1dqd\ee2e  dCd>fd]d^Z3dCe"fd_d`Z4e5e6dCefdadbZ7e5dCe$eef fdcddZ8e5dCe$ee f fdedfZ9e5dCe fdgdhZ:e5dCe;e<dif fdjdkZ=e5dCe>e fdldmZ?e@dCe"fdndoZA  ZBS )rDatabaseWrapperz Represent a database connection.rM   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
mediumblobra   ZtinytexttextZ
mediumtextrf   re   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('%%', {}))rl   rm   rq   rs   rr   rt   Nisolation_level>   zrepeatable readzread committedZserializablezread uncommittedr>   kwargsr*   c                    sp   t  j|i | | jd}|r.|dt | _|dt}t|ts(td| | _	d S t | _	t | _d S )NOPTIONSuse_pureconverter_classzXConverter class should be a subclass of mysql.connector.django.base.DjangoMySQLConverter)
superr<   settings_dictgetr2   	_use_pureDjangoMySQLConverter
issubclassProgrammingError	converter)r;   r>   rv   optionsry   	__class__r4   r5   r<   <  s   
zDatabaseWrapper.__init__rS   c                 C   s   | drdS t)NZmysql_isF)rq   AttributeErrorrU   r4   r4   r5   rV   P  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< |di dr]|d d |d< tj|d< tjjj	j
g|d< z9|d  }|d}|r| }|| jvrddd t| jD }td| d| d|| _|| W |S  ty   Y |S w )Nutf8TF)charsetZuse_unicodebufferedZconsume_resultsUSERuserNAMEZdatabaseZPASSWORDpasswdZHOST/Zunix_sockethostZPORTportrw   Zinit_commandZraise_on_warningsZclient_flagsru   z, c                 s   s    | ]	}d | d V  qdS )'Nr4   ).0levelr4   r4   r5   	<genexpr>|  s    
z8DatabaseWrapper.get_connection_params.<locals>.<genexpr>z%Invalid transaction isolation level 'z' specified.
Use one of z
, or None.)r{   rq   intr|   r   DEBUGrM   rN   	constantsZ
ClientFlagZ
FOUND_ROWScopypoplowerisolation_levelsjoinsortedr   ru   updateKeyError)r;   rv   r{   r   ru   Zvalid_levelsr4   r4   r5   get_connection_paramsU  sX   




z%DatabaseWrapper.get_connection_paramsconn_paramsc                 C   s&   d|vrt |d< tjjdi |}|S )Nry   r4   )r~   rM   rN   connect)r;   r   Zcnxr4   r4   r5   get_new_connection  s   z"DatabaseWrapper.get_new_connectionc                 C   s   g }| j jr|d | jr|d| j   |r7|  }|d| W d    n1 s2w   Y  d| jv rZz| 	| jd  W d S  t
yY   | | jd  Y d S w d S )NzSET SQL_AUTO_IS_NULL = 0z(SET SESSION TRANSACTION ISOLATION LEVEL z; Z
AUTOCOMMIT)featuresZis_sql_auto_is_null_enabledappendru   upperr8   rL   r   r{   Zset_autocommitr   _set_autocommit)r;   Zassignmentsr8   r4   r4   r5   init_connection_state  s(   


z%DatabaseWrapper.init_connection_statenamec                 C   s   | j  }t|S r9   )
connectionr8   r7   )r;   r   r8   r4   r4   r5   create_cursor  s   
zDatabaseWrapper.create_cursorc                 C   s&   zt |  W d S  ty   Y d S w r9   )r   	_rollbackNotSupportedErrorrX   r4   r4   r5   r     s
   zDatabaseWrapper._rollback
autocommitc                 C   s4   | j  || j_W d    d S 1 sw   Y  d S r9   )Zwrap_database_errorsr   r   )r;   r   r4   r4   r5   r     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)r8   rL   r:   r4   r4   r5   disable_constraint_checking  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_rollbackr8   rL   )r;   r   r8   r4   r4   r5   enable_constraint_checking  s   

z*DatabaseWrapper.enable_constraint_checkingtable_namesc           
      C   s  |   s}|du r| j|}|D ]]}| j||}|sq| j||}|D ]G\}}}|d| d| d| d| d| d| d| d	| d
 | D ]}	td| d|	d  d| d| d|	d  d| d| dq&qW d   dS 1 szw   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.
        Nz+
                        SELECT REFERRING.`z&`,
                        REFERRING.`z `
                        FROM `z2` as REFERRING
                        LEFT JOIN `zR` as REFERRED
                        ON (
                            REFERRING.`z*` =
                            REFERRED.`zE`
                        )
                        WHERE REFERRING.`z4` IS NOT NULL
                        AND REFERRED.`z"` IS NULL
                        zThe row in table 'z' with primary key 'r   z' has an invalid foreign key: .z contains a value 'r!   z.' that does not have a corresponding value in )r8   introspectionr   Zget_primary_key_columnZget_key_columnsrL   Zfetchallr   )
r;   r   r8   Z
table_nameZprimary_key_column_nameZkey_columnsZcolumn_nameZreferenced_table_nameZreferenced_column_nameZbad_rowr4   r4   r5   check_constraints  sl   
	
"z!DatabaseWrapper.check_constraintsc                 C   s&   z| j   W dS  ty   Y dS w )NFT)r   ZpingErrorrX   r4   r4   r5   	is_usable  s   zDatabaseWrapper.is_usablec                   C   s   dS )zDisplay name.MySQLr4   r4   r4   r4   r5   display_name  s   zDatabaseWrapper.display_namec                 C   s   | j jrdddd}|S i S )z<Mapping of Field objects to their SQL for CHECK constraints.z`%(column)s` >= 0)rg   rh   ri   )r   Z!supports_column_check_constraints)r;   r   r4   r4   r5   data_type_check_constraints  s   z+DatabaseWrapper.data_type_check_constraintsc                 C   sp   |   }|d | }W d   n1 sw   Y  |d |d |d t|d t|d t|d d	S )
zReturn MySQL server data.a2  
                SELECT VERSION(),
                       @@sql_mode,
                       @@default_storage_engine,
                       @@sql_auto_is_null,
                       @@lower_case_table_names,
                       CONVERT_TZ('2001-01-01 01:00:00', 'UTC', 'UTC') IS NOT NULL
            Nr   r!               )versionsql_modeZdefault_storage_engineZsql_auto_is_nullZlower_case_table_namesZhas_zoneinfo_database)temporary_connectionrL   fetchonerb   )r;   r8   rowr4   r4   r5   mysql_server_data  s   





z!DatabaseWrapper.mysql_server_datac                 C   sB   |   }|d | d W  d   S 1 sw   Y  dS )Return MySQL version.zSELECT VERSION()r   N)r   rL   r   r:   r4   r4   r5   mysql_server_info5  s   


$z!DatabaseWrapper.mysql_server_info.c                 C   sH   |   }tjjdi |}| }W d   |S 1 sw   Y  |S )r   Nr4   )r   rM   rN   r   Zget_server_version)r;   configconnZserver_versionr4   r4   r5   mysql_version<  s   

zDatabaseWrapper.mysql_versionc                 C   sV   |   }|d | }W d   n1 sw   Y  t|r(|d dS dS )zReturn SQL mode.zSELECT @@sql_modeNr   ,r4   )r8   rL   r   setsplit)r;   r8   r   r4   r4   r5   r   D  s
   


zDatabaseWrapper.sql_modec                 C   s
   | j }|S )z1Return True if pure Python version is being used.)r}   )r;   Zansr4   r4   r5   rx   L  s   zDatabaseWrapper.use_pure)r*   Nr9   )CrZ   r[   r\   r]   vendor
data_typesZ_limited_data_types	operatorsZpattern_escZpattern_opsru   r	   r_   __annotations__r   rM   rN   ZDatabaser'   ZSchemaEditorClassr"   Zclient_classr#   Zcreation_classr$   Zfeatures_classr%   Zintrospection_classr&   Z	ops_classr(   Zvalidation_classr   r<   rb   rV   r   r   r   r   r   r   r   r   r7   r   r   r   r   r   r   r   r   r   r^   r   r   r   r   r   r   r   r
   r   propertyrx   __classcell__r4   r4   r   r5   r`      s   
 	
$	5


	


0r`   c                	   @   s   e Zd ZdZeddededee fddZ	eddededee
 fdd	Zdedeeef fd
dZdedeeef fddZdedefddZdS )r~   zCustom converter for Django.Nr)   dscr*   c                 C   s   t | dS )zXReturn MySQL TIME data type as datetime.time()

        Returns datetime.time()
        zutf-8)r   Z
parse_timedecoder)   r   r4   r4   r5   _time_to_pythonX  s   z$DjangoMySQLConverter._time_to_pythonc                 C   s   | rt | S dS )ao  Connector/Python always returns naive datetime.datetime

        Connector/Python always returns naive timestamps since MySQL has
        no time zone support.

        - A naive datetime is a datetime that doesn't know its own timezone.

        Django needs a non-naive datetime, but in this method we don't need
        to make a datetime value time zone aware since Django itself at some
        point will make it aware (at least in versions 3.2.16 and 4.1.2) when
        USE_TZ=True. This may change in a future release, we need to keep an
        eye on this behaviour.

        Returns datetime.datetime()
        N)r   _datetime_to_pythonr   r4   r4   r5   r   `  s   z(DjangoMySQLConverter._datetime_to_pythonc                 C   
   |  |S r9   Z_str_to_mysqlr;   r)   r4   r4   r5   _safestring_to_mysqlu  r=   z)DjangoMySQLConverter._safestring_to_mysqlc                 C   r   r9   r   r   r4   r4   r5   _safetext_to_mysqlx  r=   z'DjangoMySQLConverter._safetext_to_mysqlc                 C   r   r9   )Z_bytes_to_mysqlr   r4   r4   r5   _safebytes_to_mysql{  r=   z(DjangoMySQLConverter._safebytes_to_mysqlr9   )rZ   r[   r\   r]   r^   bytesr   r	   r   r   r   r   r_   r   r   r   r   r   r4   r4   r4   r5   r~   S  s    r~   )Nr]   r,   r   r   typingr   r   r   r   r   r	   r
   r   r   Zdjango.confr   Zdjango.core.exceptionsr   Z	django.dbr   Zdjango.db.backends.base.baser   Zdjango.utilsr   r   Zdjango.utils.functionalr   Zmysql.connectorrM   Zmysql.connector.connectionr   Zmysql.connector.connection_cextr   Zmysql.connector.conversionr   Zmysql.connector.cursorr   Zmysql.connector.cursor_cextr   Zmysql.connector.custom_typesr   Zmysql.connector.poolingr   Zmysql.connector.typesr   r   r   r   r   ImportErrorerrZ_mysql_connectorr    r2   clientr"   Zcreationr#   r   r$   r   r%   
operationsr&   Zschemar'   Z
validationr(   rN   r   ZDatabaseErrorr   rO   r   r6   r7   r`   r~   r4   r4   r4   r5   <module>   sb   , [   