3
S^M              "   @   s>  d Z ddlmZ ddlmZ ddlZddlZddlZddlmZ ddl	m
Z
 y(ddlZddlmZmZ ddlmZ W n0 ek
r Z zed	jeW Y ddZ[X nX yejjdd
 ZW n, ek
r   ddlmZ edd
 ZY nX yddlmZmZ W n ek
r   dZY nX dZed(k r6edej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)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3 ddl4m5Z5 ddl6m7Z7 ddl8m9Z9 ddl:m;Z; ejj<Z<ejj=Z=ejj>Z>dd Z?G d d! d!eZ@G d"d# d#eZAG d$d% d%eBZCG d&d' d'e%ZDdS ))a  Django database Backend using MySQL Connector/Python

This Django database backend is heavily based on the MySQL backend coming
with 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 v1.1 and later:
    http://dev.mysql.com/downloads/connector/python/
    )unicode_literals)datetimeN)ImproperlyConfigured)cached_property)MySQLConverterMySQLConverterBase)PY2z)Error loading mysql.connector module: {0}   )VERSION)datetime_to_mysqltime_to_mysqlFT      z@MySQL Connector/Python v1.11.0 or newer is required; you have %s)utils)BaseDatabaseWrapper)connection_created)sixtimezone	dateparse)settings)DatabaseClient)DatabaseCreation)DatabaseIntrospection)DatabaseValidation)DatabaseFeatures)DatabaseOperations)DatabaseSchemaEditorc             C   sb   t jrHtj| r4tjd|  t tj }tj| |} | j	tj
jd d} trTt| S | jd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)   M/tmp/pip-build-8app2_gc/mysql-connector-python/mysql/connector/django/base.py$adapt_datetime_with_timezone_supportK   s    
r+   c               @   s4   e Zd ZdZdddZdddZdd Zd	d
 ZdS )DjangoMySQLConverterz/Custom converter for Django for MySQLConnectionNc             C   s   t j|jdS )zXReturn MySQL TIME data type as datetime.time()

        Returns datetime.time()
        zutf-8)r   
parse_timedecode)selfr(   dscr)   r)   r*   _TIME_to_python]   s    z$DjangoMySQLConverter._TIME_to_pythonc             C   sB   |sdS t j| |}|dkr dS tjr>tj|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()
        N)r   )r   _DATETIME_to_pythonr   r   r   r   r%   r$   )r/   r(   r0   dtr)   r)   r*   r2   d   s    	z(DjangoMySQLConverter._DATETIME_to_pythonc             C   s   t r| j|S | j|S d S )N)r   Z_unicode_to_mysqlZ_str_to_mysql)r/   r(   r)   r)   r*   _safetext_to_mysqlv   s    
z'DjangoMySQLConverter._safetext_to_mysqlc             C   s
   | j |S )N)Z_bytes_to_mysql)r/   r(   r)   r)   r*   _safebytes_to_mysql|   s    z(DjangoMySQLConverter._safebytes_to_mysql)N)N)__name__
__module____qualname____doc__r1   r2   r4   r5   r)   r)   r)   r*   r,   [   s
   

r,   c               @   s$   e Zd ZdZdddZdddZdS )	DjangoCMySQLConverterz0Custom converter for Django for CMySQLConnectionNc             C   s   t jt|S )zXReturn MySQL TIME data type as datetime.time()

        Returns datetime.time()
        )r   r-   str)r/   r(   r0   r)   r)   r*   r1      s    z%DjangoCMySQLConverter._TIME_to_pythonc             C   s*   |sdS t jr&tj|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()
        N)r   )r   r   r   r   r%   r$   )r/   r(   r0   r)   r)   r*   r2      s
    	z)DjangoCMySQLConverter._DATETIME_to_python)N)N)r6   r7   r8   r9   r1   r2   r)   r)   r)   r*   r:      s   
r:   c               @   sf   e Zd ZdZdZd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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.
      c             C   s
   || _ d S )N)cursor)r/   r>   r)   r)   r*   __init__   s    zCursorWrapper.__init__c             C   sZ  y
|||S  t jjk
rR } z&tjtjtj|jtj d  W Y dd}~X n t jj	k
r } z&tjtj	tj	|jtj d  W Y dd}~X n t jj
k
r } zX|jd | jkrtjtj	tj	|jtj d  n tjtjtj|jtj d  W Y dd}~X nH t jjk
rT } z&tjtjtj|jtj d  W Y dd}~X nX dS )z*Wrapper around execute() and executemany()   Nr   )mysql	connectorZProgrammingErrorr   reraiser   msgsysexc_infoIntegrityErrorZOperationalErrorargscodes_for_integrityerrorDatabaseError)r/   methodqueryrH   errr)   r)   r*   _execute_wrapper   s"    
*((zCursorWrapper._execute_wrapperc             C   s@   |s|S t |}x*|j D ]\}}t|trt|||< qW |S )N)dictitems
isinstancer   r+   )r/   rH   new_argskeyr(   r)   r)   r*   _adapt_execute_args_dict   s    
z&CursorWrapper._adapt_execute_args_dictc             C   sD   |s|S t |}x*t|D ]\}}t|trt|||< qW t|S )N)list	enumeraterQ   r   r+   tuple)r/   rH   rR   iargr)   r)   r*   _adapt_execute_args   s    
z!CursorWrapper._adapt_execute_argsNc             C   s2   t |tr| j|}n
| j|}| j| jj||S )zExecutes the given operation

        This wrapper method around the execute()-method of the cursor is
        mainly needed to re-raise using different exceptions.
        )rQ   rO   rT   rZ   rN   r>   execute)r/   rL   rH   rR   r)   r)   r*   r[      s    

zCursorWrapper.executec             C   s   | j | jj||S )zExecutes the given operation

        This wrapper method around the executemany()-method of the cursor is
        mainly needed to re-raise using different exceptions.
        )rN   r>   executemany)r/   rL   rH   r)   r)   r*   r\      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__c             C   s   | S )Nr)   )r/   r)   r)   r*   	__enter__   s    zCursorWrapper.__enter__c             C   s   | j   d S )N)close)r/   exc_type	exc_valueexc_tracebackr)   r)   r*   __exit__   s    zCursorWrapper.__exit__)r=   )N)r6   r7   r8   r9   rI   r?   rN   rT   rZ   r[   r\   r_   ra   rb   rg   r)   r)   r)   r*   r<      s   


r<   c                   sV  e 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Ze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jZeZeZeZeZeZeZ fd)d*Zd+d, Zd-d. Zd/d0 Zd1d2 ZdNd4d5Z d6d7 Z! fd8d9Z"d:d; Z#d<d= Z$d>d? Z%dOd@dAZ&dBdC Z'dDdE Z(dFdG Z)dHdI Z*edJdK Z+e,dLdM Z-  Z.S )PDatabaseWrapperrA   zinteger AUTO_INCREMENTZlongblobboolzvarchar(%(max_length)s)dater   z+numeric(%(max_digits)s, %(decimal_places)s)Zbigintzdouble precisionintegerzchar(15)zchar(39)zinteger UNSIGNEDzsmallint UNSIGNEDZsmallintZlongtexttimezchar(32))Z	AutoFieldZBinaryFieldZBooleanFieldZ	CharFieldZCommaSeparatedIntegerFieldZ	DateFieldDateTimeFieldZDecimalFieldZDurationFieldZ	FileFieldZFilePathFieldZ
FloatFieldZIntegerFieldZBigIntegerFieldZIPAddressFieldZGenericIPAddressFieldZNullBooleanFieldZOneToOneFieldZPositiveIntegerFieldZPositiveSmallIntegerFieldZ	SlugFieldZSmallIntegerFieldZ	TextField	TimeFieldZ	UUIDFieldc             C   s"   | j jrt| jdddS | jS d S )Nzdatetime(6)ztime(6))rm   rn   )featuresZsupports_microsecond_precisionrO   _data_types)r/   r)   r)   r*   
data_types  s    zDatabaseWrapper.data_typesz= %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('%%', {}))rs   rt   rx   rz   ry   r{   c                s^   t t| j|| y| jd d | _W n tk
r@   d| _Y nX | jsRt | _nt	 | _d S )NOPTIONSuse_pureT)
superrh   r?   settings_dict	_use_pureKeyErrorr}   r:   	converterr,   )r/   rH   kwargs)	__class__r)   r*   r?   L  s    
zDatabaseWrapper.__init__c             C   s   | j r| j j S dS )NF)
connectionis_connected)r/   r)   r)   r*   _valid_connectionY  s    
z!DatabaseWrapper._valid_connectionc             C   s   ddddd}| j }|d r(|d |d< |d r<|d |d< |d	 rP|d	 |d
< |d jdrl|d |d< n|d r|d |d< |d rt|d |d< tj|d< tjjjj	g|d< y|j
|d  W n tk
r   Y nX |S )Nutf8TF)charsetZuse_unicodeZbufferedZconsume_resultsUSERuserNAMEZdatabaseZPASSWORDpasswdZHOST/Zunix_sockethostZPORTportZraise_on_warningsZclient_flagsr|   )r   rx   intr   DEBUGrA   rB   	constantsZ
ClientFlagZ
FOUND_ROWSupdater   )r/   r   r   r)   r)   r*   get_connection_params^  s0    
z%DatabaseWrapper.get_connection_paramsc             C   s*   | j st|d< nt|d< tjjf |}|S )NZconverter_class)r}   r:   r,   rA   rB   connect)r/   Zconn_paramsZcnxr)   r)   r*   get_new_connection  s
    
z"DatabaseWrapper.get_new_connectionc             C   s^   | j dk r| jjd d| jkrZy| j| jd  W n$ tk
rX   | j| jd  Y nX d S )N   r	   zSET SQL_AUTO_IS_NULL = 0Z
AUTOCOMMIT)r   r   r	   )mysql_versionr   Z	cmd_queryr   Zset_autocommitAttributeError_set_autocommit)r/   r)   r)   r*   init_connection_state  s    

z%DatabaseWrapper.init_connection_stateNc             C   s   | j j }t|S )N)r   r>   r<   )r/   namer>   r)   r)   r*   create_cursor  s    
zDatabaseWrapper.create_cursorc             C   s,   | j | j | _tj| j| d | j  dS )zSetup the connection with MySQL)Zsenderr   N)r   r   r   r   sendr   r   )r/   r)   r)   r*   _connect  s    zDatabaseWrapper._connectc                s:   yt t| j S  tk
r4   | js,| j  | j S X dS )zGReturn a CursorWrapper object

        Returns a CursorWrapper
        N)r~   rh   _cursorr   r   r   r   )r/   )r   r)   r*   r     s    zDatabaseWrapper._cursorc             C   s:   y| j   W n" tk
r.   | js*| j  Y nX | jj S )zXReturns the MySQL server version of current connection

        Returns a tuple
        )Zensure_connectionr   r   r   get_server_version)r/   r)   r)   r*   r     s    z"DatabaseWrapper.get_server_versionc             C   s   | j  jd dS )zDisables foreign key checks

        Disables foreign key checks, primarily for use in adding rows with
        forward references. Always returns True,
        to indicate constraint checks need to be re-enabled.

        Returns True
        z$SET @@session.foreign_key_checks = 0T)r>   r[   )r/   r)   r)   r*   disable_constraint_checking  s    	z+DatabaseWrapper.disable_constraint_checkingc             C   s.   d| j  | _ }z| j jd W d|| _ X dS )zjRe-enable foreign key checks

        Re-enable foreign key checks after they have been disabled.
        Fz$SET @@session.foreign_key_checks = 1N)needs_rollbackr>   r[   )r/   r   r)   r)   r*   enable_constraint_checking  s    z*DatabaseWrapper.enable_constraint_checkingc             C   s   d}| j  }|dkr | jj|}x|D ]}| jj||}|s>q&| jj||}xj|D ]b\}}}	|j|j||||||	||	 x8|j D ],}
dj||
d |||
d ||	}tj	|qW qRW q&W dS )a  Check rows in tables for invalid foreign key references

        Checks 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.

        Raises an IntegrityError on the first invalid foreign key reference
        encountered (if any) and provides detailed information about the
        invalid reference in the error message.

        Backends can override this method if they can more directly apply
        constraint checking (e.g. via "SET CONSTRAINTS ALL IMMEDIATE")
        z
            SELECT REFERRING.`{0}`, REFERRING.`{1}` FROM `{2}` as REFERRING
            LEFT JOIN `{3}` as REFERRED
            ON (REFERRING.`{4}` = REFERRED.`{5}`)
            WHERE REFERRING.`{6}` IS NOT NULL AND REFERRED.`{7}` IS NULLNzThe row in table '{0}' with primary key '{1}' has an invalid foreign key: {2}.{3} contains a value '{4}' that does not have a corresponding value in {5}.{6}.r   r   )
r>   Zintrospectiontable_namesZget_primary_key_columnZget_key_columnsr[   formatZfetchallr   rG   )r/   r   Z	ref_queryr>   Z
table_nameZprimary_key_column_nameZkey_columnsZcolumn_nameZreferenced_table_nameZreferenced_column_nameZbad_rowrD   r)   r)   r*   check_constraints  s4    

z!DatabaseWrapper.check_constraintsc             C   s(   yt j|  W n tk
r"   Y nX d S )N)r   	_rollbackNotSupportedError)r/   r)   r)   r*   r     s    zDatabaseWrapper._rollbackc          	   C   s   | j  || j_W d Q R X d S )N)Zwrap_database_errorsr   
autocommit)r/   r   r)   r)   r*   r     s    zDatabaseWrapper._set_autocommitc             O   s   t | f||S )z5Returns a new instance of this backend's SchemaEditor)r   )r/   rH   r   r)   r)   r*   schema_editor  s    zDatabaseWrapper.schema_editorc             C   s
   | j j S )N)r   r   )r/   r)   r)   r*   	is_usable  s    zDatabaseWrapper.is_usablec             C   s*   | j  }tjjf |}|j }|j  |S )N)r   rA   rB   r   r   rc   )r/   configZ	temp_connZserver_versionr)   r)   r*   r     s
    zDatabaseWrapper.mysql_versionc             C   s   t  p
| jS )N)r&   r   )r/   r)   r)   r*   r}      s    zDatabaseWrapper.use_pure)N)N)/r6   r7   r8   vendorrp   r   rq   	operatorsZpattern_escZpattern_opsr   ZSchemaEditorClassrA   rB   ZDatabaser   Zclient_classr   Zcreation_classr   Zfeatures_classr   Zintrospection_classr   Z	ops_classr   Zvalidation_classr?   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   propertyr}   __classcell__r)   r)   )r   r*   rh      s   	&	

2	rh   )r   r   )Er9   
__future__r   r   rE   r    ZdjangoZdjango.core.exceptionsr   Zdjango.utils.functionalr   Zmysql.connectorrA   Zmysql.connector.conversionr   r   Zmysql.connector.catch23r   ImportErrorrM   r   rB   __version_info__versionr   Zmysql.connector.versionr
   Z_mysql_connectorr   r   r&   __version__Z	django.dbr   Zdjango.db.backendsZbackend_utilsZdjango.db.backends.base.baser   Zdjango.db.backends.signalsr   Zdjango.utilsr   r   r   Zdjango.confr   Zmysql.connector.django.clientr   Zmysql.connector.django.creationr   Z$mysql.connector.django.introspectionr   Z!mysql.connector.django.validationr   Zmysql.connector.django.featuresr   Z!mysql.connector.django.operationsr   Zmysql.connector.django.schemar   rJ   rG   r   r+   r,   r:   objectr<   rh   r)   r)   r)   r*   <module>   sb   

%Z