3
a)                 @   s   d 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
 G dd deZG dd deZG dd deZG dd deZeZdS )a
  

.. dialect:: mysql+mysqldb
    :name: mysqlclient (maintained fork of MySQL-Python)
    :dbapi: mysqldb
    :connectstring: mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
    :url: https://pypi.org/project/mysqlclient/

Driver Status
-------------

The mysqlclient DBAPI is a maintained fork of the
`MySQL-Python <https://sourceforge.net/projects/mysql-python>`_ DBAPI
that is no longer maintained.  `mysqlclient`_ supports Python 2 and Python 3
and is very stable.

.. _mysqlclient: https://github.com/PyMySQL/mysqlclient-python

.. _mysqldb_unicode:

Unicode
-------

Please see :ref:`mysql_unicode` for current recommendations on unicode
handling.

.. _mysqldb_ssl:

SSL Connections
----------------

The mysqlclient and PyMySQL DBAPIs accept an additional dictionary under the
key "ssl", which may be specified using the
:paramref:`_sa.create_engine.connect_args` dictionary::

    engine = create_engine(
        "mysql+mysqldb://scott:tiger@192.168.0.134/test",
        connect_args={
            "ssl": {
                "ssl_ca": "/home/gord/client-ssl/ca.pem",
                "ssl_cert": "/home/gord/client-ssl/client-cert.pem",
                "ssl_key": "/home/gord/client-ssl/client-key.pem"
            }
        }
    )

For convenience, the following keys may also be specified inline within the URL
where they will be interpreted into the "ssl" dictionary automatically:
"ssl_ca", "ssl_cert", "ssl_key", "ssl_capath", "ssl_cipher",
"ssl_check_hostname". An example is as follows::

    connection_uri = (
        "mysql+mysqldb://scott:tiger@192.168.0.134/test"
        "?ssl_ca=/home/gord/client-ssl/ca.pem"
        "&ssl_cert=/home/gord/client-ssl/client-cert.pem"
        "&ssl_key=/home/gord/client-ssl/client-key.pem"
    )

If the server uses an automatically-generated certificate that is self-signed
or does not match the host name (as seen from the client), it may also be
necessary to indicate ``ssl_check_hostname=false``::

    connection_uri = (
        "mysql+pymysql://scott:tiger@192.168.0.134/test"
        "?ssl_ca=/home/gord/client-ssl/ca.pem"
        "&ssl_cert=/home/gord/client-ssl/client-cert.pem"
        "&ssl_key=/home/gord/client-ssl/client-key.pem"
        "&ssl_check_hostname=false"
    )


.. seealso::

    :ref:`pymysql_ssl` in the PyMySQL dialect


Using MySQLdb with Google Cloud SQL
-----------------------------------

Google Cloud SQL now recommends use of the MySQLdb dialect.  Connect
using a URL like the following::

    mysql+mysqldb://root@/<dbname>?unix_socket=/cloudsql/<projectid>:<instancename>

Server Side Cursors
-------------------

The mysqldb dialect supports server-side cursors. See :ref:`mysql_ss_cursors`.

    N   )MySQLCompiler)MySQLDialect)MySQLExecutionContext)MySQLIdentifierPreparer)TEXT   )sql)utilc               @   s   e Zd Zedd ZdS )MySQLExecutionContext_mysqldbc             C   s   t | dr| jS | jjS d S )N	_rowcount)hasattrr   cursorrowcount)self r   G/tmp/pip-build-6_cqtusv/SQLAlchemy/sqlalchemy/dialects/mysql/mysqldb.pyr   o   s    
z&MySQLExecutionContext_mysqldb.rowcountN)__name__
__module____qualname__propertyr   r   r   r   r   r   n   s   r   c               @   s   e Zd ZdS )MySQLCompiler_mysqldbN)r   r   r   r   r   r   r   r   w   s   r   c               @   s   e Zd ZdS )MySQLIdentifierPreparer_mysqldbN)r   r   r   r   r   r   r   r   {   s   r   c                   s   e Zd ZdZdZdZdZdZdZdZ	e
ZeZeZ fddZdd Zejjdd	 Zed
d Z fddZdd Zd$ddZ fddZd%ddZdd Zdd Zdd Ze dddd d!gZ! fd"d#Z"  Z#S )&MySQLDialect_mysqldbZmysqldbTformatc                s@   t t| jf | | jd k	r6t| jdr6| j| jjnd| _d S )N__version__r   )r   r   r   )superr   __init__dbapir   _parse_dbapi_versionr   Z_mysql_dbapi_version)r   kwargs)	__class__r   r   r      s    $zMySQLDialect_mysqldb.__init__c             C   s4   t jd|}|r,tdd |jdddD S dS d S )	Nz(\d+)\.(\d+)(?:\.(\d+))?c             s   s   | ]}|d k	rt |V  qd S )N)int).0xr   r   r   	<genexpr>   s    z<MySQLDialect_mysqldb._parse_dbapi_version.<locals>.<genexpr>r      r   r   )r   r   r   )rematchtuplegroup)r   versionmr   r   r   r      s    z)MySQLDialect_mysqldb._parse_dbapi_versionc             C   s4   yt dj}|j| _dS  ttfk
r.   dS X d S )NzMySQLdb.cursorsTF)
__import__cursorsZSSCursorZ	_sscursorImportErrorAttributeError)r   r.   r   r   r   supports_server_side_cursors   s    
z1MySQLDialect_mysqldb.supports_server_side_cursorsc             C   s   t dS )NZMySQLdb)r-   )clsr   r   r   r      s    zMySQLDialect_mysqldb.dbapic                s   t t| j   fdd}|S )Nc                sB    d k	r |  | j  }|d k	r>| j }|jd|  |j  d S )NzSET NAMES %s)character_set_namer   executeclose)conncharset_namer   )super_r   r   
on_connect   s    z3MySQLDialect_mysqldb.on_connect.<locals>.on_connect)r   r   r9   )r   r9   )r!   )r8   r   r9      s    zMySQLDialect_mysqldb.on_connectc             C   sR   y|j d W n: | jjk
rH } z| j||d r6dS  W Y d d }~X nX dS d S )NFT)Zpingr   ErrorZis_disconnect)r   Zdbapi_connectionerrr   r   r   do_ping   s    zMySQLDialect_mysqldb.do_pingNc             C   s   |j ||}|d k	r||_d S )N)Zexecutemanyr   )r   r   Z	statement
parameterscontextr   r   r   r   do_executemany   s    z#MySQLDialect_mysqldb.do_executemanyc                sr   |j d| jjd| jjdf j }| jd	ko2|}|r\tjtjtjdt	dddg}ng }t
t| j||S )
Nz:show collation where %s = 'utf8mb4' and %s = 'utf8mb4_bin'CharsetZ	Collation   z'test collated returns'Zutf8mb4)charsetZutf8mb4_bin)rA   )Zexec_driver_sqlZidentifier_preparerquoteZscalarZserver_version_infor	   ZcollatecastZliteral_columnr   r   r   _check_unicode_returns)r   
connectionZ	collationZhas_utf8mb4_binZadditional_tests)r!   r   r   rE      s    



z+MySQLDialect_mysqldb._check_unicode_returnsc       
      C   sX  |d krt dddd}|jf |}|j|j tj|dt tj|dt tj|dt tj|dt tj|d	t tj|d
t tj|dt tj|dt i }dtfdtfdtfdtfdtfdtfg}xH|D ]@\}}||kr|| ||dd  < tj||dd  | ||= qW |r"||d< |j	d	d}| j
 }	|	d k	rP||	O }||d	< g |gS )Ndbuserpasswd)Zdatabaseusernamepasswordcompressconnect_timeoutread_timeoutZwrite_timeoutclient_flagZlocal_infileZuse_unicoderB   Zssl_caZssl_keyZssl_certZ
ssl_capathZ
ssl_cipherZssl_check_hostname   sslr   )dictZtranslate_connect_argsupdatequeryr
   Zcoerce_kw_typeboolr"   strget_found_rows_client_flag)
r   urlZ_translate_argsoptsrQ   keyskeyZkw_typerO   Zclient_flag_found_rowsr   r   r   create_connect_args   sB    


z(MySQLDialect_mysqldb.create_connect_argsc             C   sL   | j d k	rDyt| j jd jj}W n ttfk
r:   d S X |jS nd S d S )Nz.constants.CLIENT)r   r-   r   	constantsZCLIENTr0   r/   Z
FOUND_ROWS)r   ZCLIENT_FLAGSr   r   r   rX     s    
z,MySQLDialect_mysqldb._found_rows_client_flagc             C   s
   |j d S )Nr   )args)r   	exceptionr   r   r   _extract_error_code&  s    z(MySQLDialect_mysqldb._extract_error_codec             C   s6   y|j j}W n tk
r*   tjd dS X | S dS )z:Sniff out the character set in use for connection results.zNo 'character_set_name' can be detected with this MySQL-Python version; please upgrade to a recent version of MySQL-Python.  Assuming latin1.latin1N)rF   r3   r0   r
   warn)r   rF   Z	cset_namer   r   r   _detect_charset)  s    z$MySQLDialect_mysqldb._detect_charsetZSERIALIZABLEzREAD UNCOMMITTEDzREAD COMMITTEDzREPEATABLE READ
AUTOCOMMITc                s4   |dkr|j d n|j d tt| j|| d S )Nre   TF)Z
autocommitr   r   _set_isolation_level)r   rF   level)r!   r   r   rf   E  s
    

z)MySQLDialect_mysqldb._set_isolation_level)N)N)$r   r   r   ZdriverZsupports_statement_cacheZsupports_unicode_statementsZsupports_sane_rowcountZsupports_sane_multi_rowcountZsupports_native_decimalZdefault_paramstyler   Zexecution_ctx_clsr   Zstatement_compilerr   Zpreparerr   r   r
   ZlanghelpersZmemoized_propertyr1   classmethodr   r9   r<   r?   rE   r]   rX   ra   rd   setZ_isolation_lookuprf   __classcell__r   r   )r!   r   r      s:   	

3r   )__doc__r'   baser   r   r   r   r    r	   r
   r   r   r   r   dialectr   r   r   r   <module>a   s   	 Q