U
    ø×ccÅ(  ã                   @   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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   úE/tmp/pip-unpacked-wheel-8u86ls_i/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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¡nd| _d S )NÚ__version__©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  d|¡}|r,tdd„ | 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   )ÚreÚmatchÚtupleÚgroup)r   ÚversionÚmr   r   r   r   ‘   s    z)MySQLDialect_mysqldb._parse_dbapi_versionc              	   C   s8   zt dƒj}|j| _W dS  ttfk
r2   Y dS X d S )NzMySQLdb.cursorsTF)Ú
__import__ÚcursorsZSSCursorZ	_sscursorÚImportErrorÚAttributeError)r   r0   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| ƒ ¡ ‰ ‡ fdd„}|S )Nc                    sB   ˆ d k	rˆ | ƒ |   ¡ }|d k	r>|  ¡ }| d| ¡ | ¡  d S )NzSET NAMES %s)Úcharacter_set_namer   ÚexecuteÚclose)ÚconnÚcharset_namer   ©Zsuper_r   r   Ú
on_connect¨   s    z3MySQLDialect_mysqldb.on_connect.<locals>.on_connect)r   r   r;   )r   r;   r!   r:   r   r;   ¥   s    zMySQLDialect_mysqldb.on_connectc              
   C   sX   z|  d¡ W n@ | jjk
rN } z|  ||d ¡r<W Y ¢
dS ‚ W 5 d }~X Y 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   |  ||¡}|d k	r||_d S r#   )Zexecutemanyr   )r   r   Z	statementÚ
parametersÚcontextr   r   r   r   Údo_executemanyÀ   s    z#MySQLDialect_mysqldb.do_executemanyc                    sr   |  d| j d¡| j d¡f ¡ ¡ }| jdko2|}|r\t t t d¡t	dd¡d¡g}ng }t
t| ƒ ||¡S )	Nz:show collation where %s = 'utf8mb4' and %s = 'utf8mb4_bin'ÚCharsetZ	Collation)é   z'test collated returns'Zutf8mb4)ÚcharsetZutf8mb4_bin)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_testsr!   r   r   rG   Å   s,    

þÿÿþûÿ

 ÿz+MySQLDialect_mysqldb._check_unicode_returnsc           
      C   sT  |d krt dddd}|jf |Ž}| |j¡ t |dt¡ t |dt¡ t |dt¡ t |dt¡ t |d	t¡ t |d
t¡ t |dt¡ t |dt¡ i }dtfdtfdtfdtfdtfdtfg}|D ]@\}}||krÎ|| ||dd … < t ||dd … |¡ ||= qÎ|r||d< | 	d	d¡}|  
¡ }	|	d k	rL||	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_unicoderD   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ÚoptsrS   ÚkeysÚkeyZkw_typerQ   Zclient_flag_found_rowsr   r   r   Úcreate_connect_argsâ   sJ      ÿú
z(MySQLDialect_mysqldb.create_connect_argsc              	   C   sN   | j d k	rFzt| j jd ƒjj}W n ttfk
r<   Y d S X |jS nd S d S )Nz.constants.CLIENT)r   r/   r   Ú	constantsZCLIENTr2   r1   Z
FOUND_ROWS)r   ZCLIENT_FLAGSr   r   r   rZ     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   s8   z|j j}W n  tk
r,   t d¡ Y 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)rH   r5   r2   r
   Úwarn)r   rH   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|  d¡ n|  d¡ tt| ƒ ||¡ d S )Nrg   TF)Z
autocommitr   r   Ú_set_isolation_level)r   rH   Úlevelr!   r   r   rh   A  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   Úpreparerr   r   r
   ZlanghelpersZmemoized_propertyr3   Úclassmethodr   r;   r>   rA   rG   r_   rZ   rc   rf   ÚsetZ_isolation_lookuprh   Ú__classcell__r   r   r!   r   r   {   sB   



3ûÿ
r   )Ú__doc__r)   Úbaser   r   r   r   r   Ú r	   r
   r   r   r   Údialectr   r   r   r   Ú<module>   s   [	 Q