U
    ¤�©j_  ã                
   @   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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 ddlmZ zDd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(m)Z) W n4 e*k
�r  Z+ zede+› �ƒe+‚W 5 dZ+[+X Y nX zddl,m-Z- W n e*k
�rL   dZ.Y nX dZ.ddl/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 ddl7m8Z8 ddl9m:Z: ddl;m<Z< e j=j>Z>e j=j?Z?e j=j@Z@e j=jAZAe j=jBZBe�räddlCmDZDmEZE ee)dœdd„ZFG d d!„ d!ƒZGG d"d#„ d#eƒZHG d$d%„ d%e"ƒZId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)ÚTYPE_CHECKINGÚAnyÚDictÚ	GeneratorÚIteratorÚListÚOptionalÚSequenceÚSetÚTupleÚUnion)Úsettings)ÚImproperlyConfigured)ÚIntegrityError)ÚBaseDatabaseWrapper)Ú	dateparseÚtimezone)Úcached_property)ÚMySQLConvertibleType)ÚMySQLConverter)Ú
HexLiteral)ÚPooledMySQLConnection)ÚParamsSequenceOrDictTypeÚRowTypeÚ
StrOrBytesz&Error loading mysql.connector module: )Údatetime_to_mysqlFTé   )ÚDatabaseClient)ÚDatabaseCreation)ÚDatabaseFeatures)ÚDatabaseIntrospection)ÚDatabaseOperations)ÚDatabaseSchemaEditor)ÚDatabaseValidation)ÚMySQLConnectionAbstractÚMySQLCursorAbstract©ÚvalueÚreturnc                 C   sf   t jrLt | ¡r8t 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   ú?/tmp/pip-unpacked-wheel-d6bt0v6z/mysql/connector/django/base.pyÚ$adapt_datetime_with_timezone_supporti   s    

ýÿr6   c                   @   sô   e Zd ZdZdZdddœdd„Zeeee	f eee	f dœd	d
„ƒZ
eeee	  eee	  dœdd„ƒZdeeeee	 eee	f f  eed  dœdd„Zeeeee	 eee	f f  eed  dœdd„Zeedœdd„Zee dœdd„ZdS )ÚCursorWrapperzãWrapper 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¹  r'   N)Úcursorr*   c                 C   s
   || _ d S ©N)r8   ©Úselfr8   r4   r4   r5   Ú__init__�   s    zCursorWrapper.__init__)Úargsr*   c                 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Ú	enumerater@   r   r6   Útuple)r=   rA   ÚiÚargr4   r4   r5   Ú_adapt_execute_args�   s    
z!CursorWrapper._adapt_execute_args)r'   NN)Úqueryr=   r*   c              
   C   s‚   d}t |tƒr|  |¡}n
|  |¡}z| j ||¡W S  tjjk
r| } z&|j	d | j
krjtt|j	ƒŽ d‚‚ W 5 d}~X Y nX dS )z­Executes the given operation

        This wrapper method around the execute()-method of the cursor is
        mainly needed to re-raise using different exceptions.
        Nr   )r@   r>   rC   rI   r8   ÚexecuteÚmysqlÚ	connectorÚOperationalErrorr=   Úcodes_for_integrityerrorr   rF   )r;   rJ   r=   rA   Úexcr4   r4   r5   rK   ª   s    

zCursorWrapper.executec              
   C   s^   z| j  ||¡W S  tjjk
rX } z&|jd | jkrFtt|jƒŽ d‚‚ W 5 d}~X Y nX dS )z±Executes 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   ÚexecutemanyrL   rM   rN   r=   rO   r   rF   )r;   rJ   r=   rP   r4   r4   r5   rQ   Â   s    zCursorWrapper.executemany©Úattrr*   c                 C   s   t | j|ƒS )z%Return an attribute of wrapped cursor)Úgetattrr8   ©r;   rS   r4   r4   r5   Ú__getattr__Õ   s    zCursorWrapper.__getattr__©r*   c                 C   s
   t | jƒS )z&Return an iterator over wrapped cursor)Úiterr8   ©r;   r4   r4   r5   Ú__iter__Ù   s    zCursorWrapper.__iter__)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rO   r<   Ústaticmethodr   Ústrr   rC   r
   r   rI   r   r   rK   rQ   r   rV   r   r   rZ   r4   r4   r4   r5   r7   ~   s6   

þ

þ ûÿ
úÿ
úr7   c                       sN  e Zd ZU 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dœZ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	d-Z
ee ed.< d/d0d1d2hZejZeZeZeZeZeZeZeZe e d-d3œ‡ fd4d5„Z!ee"d6œd7d8„Z#e$ee f d9œd:d;„Z%e$ee f e&e'd<f d=œd>d?„Z(d-d9œd@dA„Z)dbe e*dBœdCdD„Z+d-d9œdEdF„Z,e"d-dGœdHdI„Z-e"d9œdJdK„Z.d-d9œdLdM„Z/dcee0e  d-dNœdOdP„Z1e"d9œdQdR„Z2e3e4ed9œdSdT„ƒƒZ5e3e$eef d9œdUdV„ƒZ6e3e$ee f d9œdWdX„ƒZ7e3e d9œdYdZ„ƒZ8e3e9e:d[f d9œd\d]„ƒZ;e3e<e d9œd^d_„ƒZ=e>e"d9œd`da„ƒZ?‡  Z@S )dÚDatabaseWrapperz Represent a database connection.rL   zinteger AUTO_INCREMENTzbigint AUTO_INCREMENTÚlongblobÚboolzvarchar(%(max_length)s)Údatezdatetime(6)z+numeric(%(max_digits)s, %(decimal_places)s)Zbigintzdouble precisionÚintegerzchar(15)zchar(39)Újsonzbigint UNSIGNEDzinteger UNSIGNEDzsmallint UNSIGNEDzsmallint AUTO_INCREMENTZsmallintÚlongtextztime(6)zchar(32))Z	AutoFieldZBigAutoFieldZBinaryFieldZBooleanFieldZ	CharFieldZ	DateFieldZDateTimeFieldZDecimalFieldZDurationFieldZ	FileFieldZFilePathFieldZ
FloatFieldZIntegerFieldZBigIntegerFieldZIPAddressFieldZGenericIPAddressFieldZ	JSONFieldZNullBooleanFieldZOneToOneFieldÚPositiveBigIntegerFieldÚPositiveIntegerFieldÚPositiveSmallIntegerFieldZ	SlugFieldZSmallAutoFieldZSmallIntegerFieldZ	TextFieldZ	TimeFieldZ	UUIDField)	ZtinyblobZblobZ
mediumblobrb   ZtinytextÚtextZ
mediumtextrg   rf   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('%%', {}))rm   rn   rr   rt   rs   ru   NÚisolation_levelzread uncommittedzread committedzrepeatable readZserializable)r=   Úkwargsr*   c                    sj   t ƒ j||Ž | j d¡}|rV| dt ¡| _| dt¡}t|tƒsLtdƒ‚|ƒ | _	n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=   rw   Úoptionsrz   ©Ú	__class__r4   r5   r<   K  s    þ
ÿ
zDatabaseWrapper.__init__rR   c                 C   s   |  d¡rdS t‚d S )NZmysql_isF)rr   ÚAttributeErrorrU   r4   r4   r5   rV   _  s    
zDatabaseWrapper.__getattr__rW   c                 C   sh  dddddœ}| j }|d r(|d |d< |d r<|d |d< |d	 rP|d	 |d
< |d  d¡rl|d |d< n|d r€|d |d< |d r˜t|d ƒ|d< | di ¡ d¡rº|d d |d< tj|d< tjjj	j
g|d< zv|d  ¡ }| dd ¡}|�r:| ¡ }|| jk�r:d dd„ t| jƒD ƒ¡}td|› d|› d�ƒ‚|| _| |¡ W n tk
�rb   Y nX |S )NÚutf8TF)ÚcharsetZuse_unicodeZbufferedZconsume_resultsÚUSERÚuserÚNAMEZdatabaseZPASSWORDÚpasswdZHOSTú/Zunix_socketÚhostZPORTÚportrx   Zinit_commandZraise_on_warningsZclient_flagsrv   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|   rr   Úintr}   r   ÚDEBUGrL   rM   Ú	constantsZ
ClientFlagZ
FOUND_ROWSÚcopyÚpopÚlowerÚisolation_levelsÚjoinÚsortedr   rv   ÚupdateÚKeyError)r;   rw   r|   rƒ   rv   Zvalid_levelsr4   r4   r5   Úget_connection_paramsd  sP    ü

þ
ÿÿz%DatabaseWrapper.get_connection_paramsr&   )Úconn_paramsr*   c                 C   s"   d|krt |d< tjjf |Ž}|S )Nrz   )r   rL   rM   Úconnect)r;   r    Zcnxr4   r4   r5   Úget_new_connection™  s    z"DatabaseWrapper.get_new_connectionc              	   C   s¢   g }| j jr| d¡ | jr2| d| j ¡ › �¡ |rZ|  ¡ �}| d |¡¡ W 5 Q R X d| jkržz|  	| jd ¡ W n$ t
k
rœ   |  | jd ¡ Y nX d S )NzSET SQL_AUTO_IS_NULL = 0z(SET SESSION TRANSACTION ISOLATION LEVEL z; Z
AUTOCOMMIT)ÚfeaturesZis_sql_auto_is_null_enabledÚappendrv   Úupperr8   rK   r›   r|   Zset_autocommitr†   Ú_set_autocommit)r;   Zassignmentsr8   r4   r4   r5   Úinit_connection_state¢  s    
ÿ

z%DatabaseWrapper.init_connection_state)Únamer*   c                 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 n tk
r"   Y nX d S r9   )r   Ú	_rollbackÚNotSupportedErrorrY   r4   r4   r5   r«   ¿  s    zDatabaseWrapper._rollback)Ú
autocommitr*   c              	   C   s   | j � || j_W 5 Q R X d S r9   )Zwrap_database_errorsr©   r­   )r;   r­   r4   r4   r5   r¦   Å  s    zDatabaseWrapper._set_autocommitc              	   C   s"   |   ¡ �}| d¡ W 5 Q R X 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=0T)r8   rK   r:   r4   r4   r5   Údisable_constraint_checkingÉ  s    
z+DatabaseWrapper.disable_constraint_checkingc              	   C   s>   d| j  | _ }z"|  ¡ �}| d¡ W 5 Q R X W 5 || _ X dS )zM
        Re-enable foreign key checks after they have been disabled.
        FzSET foreign_key_checks=1N)Úneeds_rollbackr8   rK   )r;   r¯   r8   r4   r4   r5   Úenable_constraint_checkingÓ  s
    
z*DatabaseWrapper.enable_constraint_checking)Útable_namesr*   c           
      C   sî   |   ¡ �Ü}|dkr| j |¡}|D ]¼}| j ||¡}|s:q"| j ||¡}|D ]�\}}}| d|› d|› d|› d|› d|› d|› d|› d	|› d
�¡ | ¡ D ]@}	td|› d|	d › d|› d|› d|	d › d|› d|› d�ƒ‚qšqLq"W 5 Q R X 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_columnsrK   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à  sT    
 ÿ ÿüÿþýüþùþùÿ6ÿz!DatabaseWrapper.check_constraintsc                 C   s*   z| j  ¡  W n tk
r$   Y dS X dS )NFT)r©   ZpingÚErrorrY   r4   r4   r5   Ú	is_usable  s
    zDatabaseWrapper.is_usablec                   C   s   dS )zDisplay name.Z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)rh   ri   rj   )r£   Z!supports_column_check_constraints)r;   r´   r4   r4   r5   Údata_type_check_constraints  s    ýz+DatabaseWrapper.data_type_check_constraintsc              	   C   s\   |   ¡ �}| d¡ | ¡ }W 5 Q R X |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
            r   r   é   é   é   é   )ÚversionÚsql_modeZdefault_storage_engineZsql_auto_is_nullZlower_case_table_namesZhas_zoneinfo_database)Útemporary_connectionrK   Úfetchonerc   )r;   r8   Úrowr4   r4   r5   Úmysql_server_data+  s    
ÿ



úz!DatabaseWrapper.mysql_server_datac              
   C   s6   |   ¡ �$}| d¡ | ¡ d W  5 Q R £ S Q R X dS )úReturn MySQL version.zSELECT VERSION()r   N)r¿   rK   rÀ   r:   r4   r4   r5   Úmysql_server_infoF  s    

z!DatabaseWrapper.mysql_server_info.c              	   C   s.   |   ¡ }tjjf |Ž�}| ¡ }W 5 Q R X |S )rÃ   )rŸ   rL   rM   r¡   Zget_server_version)r;   ÚconfigÚconnZserver_versionr4   r4   r5   Úmysql_versionM  s    zDatabaseWrapper.mysql_versionc              	   C   s@   |   ¡ �}| d¡ | ¡ }W 5 Q R X t|r:|d  d¡ndƒS )zReturn SQL mode.zSELECT @@sql_moder   ú,r4   )r8   rK   rÀ   ÚsetÚsplit)r;   r8   r¾   r4   r4   r5   r¾   U  s    

zDatabaseWrapper.sql_modec                 C   s
   | j }|S )z1Return True if pure Python version is being used.)r~   )r;   Zansr4   r4   r5   ry   ]  s    zDatabaseWrapper.use_pure)N)N)Ar[   r\   r]   r^   ÚvendorÚ
data_typesZ_limited_data_typesÚ	operatorsZpattern_escZpattern_opsrv   r
   r`   Ú__annotations__rš   rL   rM   ZDatabaser$   ZSchemaEditorClassr   Zclient_classr    Zcreation_classr!   Zfeatures_classr"   Zintrospection_classr#   Z	ops_classr%   Zvalidation_classr   r<   rc   rV   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¾   Úpropertyry   Ú__classcell__r4   r4   r„   r5   ra   Þ   sÄ   
ä$òú	ü6

þ	
2ra   c                   @   sˆ   e Zd ZdZedeeee dœdd„ƒZ	edeeee
 dœdd„ƒZeeeef dœd	d
„Zeeeef dœdd„Zeedœdd„ZdS )r   zCustom converter for Django.N)r)   Ú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_pythoni  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Õ   q  s    z(DjangoMySQLConverter._datetime_to_pythonr(   c                 C   s
   |   |¡S r9   ©Z_str_to_mysql©r;   r)   r4   r4   r5   Ú_safestring_to_mysql†  s    z)DjangoMySQLConverter._safestring_to_mysqlc                 C   s
   |   |¡S r9   rÖ   r×   r4   r4   r5   Ú_safetext_to_mysql‰  s    z'DjangoMySQLConverter._safetext_to_mysqlc                 C   s
   |   |¡S r9   )Z_bytes_to_mysqlr×   r4   r4   r5   Ú_safebytes_to_mysqlŒ  s    z(DjangoMySQLConverter._safebytes_to_mysql)N)N)r[   r\   r]   r^   r_   Úbytesr   r
   r   rÔ   r   rÕ   r`   r   r   rØ   rÙ   rÚ   r4   r4   r4   r5   r   d  s   r   )Jr^   r,   r   r   Útypingr   r   r   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.connector.typesr   Zmysql.connectorrL   Zmysql.connector.conversionr   Zmysql.connector.custom_typesr   Zmysql.connector.poolingr   r   r   r   ÚImportErrorÚerrZ_mysql_connectorr   r2   Úclientr   Zcreationr    r£   r!   r³   r"   Ú
operationsr#   Zschemar$   Z
validationr%   rM   rµ   ZDatabaseErrorr¬   rN   r�   Zmysql.connector.abstractsr&   r'   r6   r7   ra   r   r4   r4   r4   r5   Ú<module>   sX   4"
`   	