U
    h&                     @  s^  d Z ddlm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 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 er&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 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": {
                "ca": "/home/gord/client-ssl/ca.pem",
                "cert": "/home/gord/client-ssl/client-cert.pem",
                "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"
    )

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

.. sourcecode:: text

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

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

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

    )annotationsN)Any)Callable)cast)Dict)Optional)Tuple)TYPE_CHECKING   )MySQLCompiler)MySQLDialect)MySQLExecutionContext)MySQLIdentifierPreparer   )util)Literal)
Connection)_DBAPIMultiExecuteParams)ConnectArgsType)DBAPIConnection)DBAPICursor)DBAPIModule)ExecutionContext)IsolationLevel)URLc                   @  s   e Zd ZdS )MySQLExecutionContext_mysqldbN__name__
__module____qualname__ r    r    E/tmp/pip-unpacked-wheel-y9ln43lq/sqlalchemy/dialects/mysql/mysqldb.pyr   v   s   r   c                   @  s   e Zd ZdS )MySQLCompiler_mysqldbNr   r    r    r    r!   r"   z   s   r"   c                      s>  e Zd ZU dZdZdZdZdZdZdZ	e
ZeZeZded< dd fdd	Zd
ddddZejjddddZeddddZdd fddZdddddZdAdd
dd d!d"d#d$ZdBd%d&d'd(d)d*Zd+dd,d-Zd.d/d0d1d2Zd3d
d4d5d6Zdd7d8d9d:Z ddd8d;d<Z!dd=d!d> fd?d@Z"  Z#S )CMySQLDialect_mysqldbZmysqldbTformatzTuple[int, ...]Zserver_version_infor   )kwargsc                   s<   t  jf | | jd k	r2t| jdr2| | jjnd| _d S )N__version__r   r   r   )super__init__dbapihasattr_parse_dbapi_versionr&   Z_mysql_dbapi_version)selfr%   	__class__r    r!   r)      s    
zMySQLDialect_mysqldb.__init__str)versionreturnc                 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-   r1   mr    r    r!   r,      s    z)MySQLDialect_mysqldb._parse_dbapi_versionbool)r2   c              	   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-   r@   r    r    r!   supports_server_side_cursors   s    
z1MySQLDialect_mysqldb.supports_server_side_cursorsr   c                 C  s   t dS )NZMySQLdb)r?   )clsr    r    r!   import_dbapi   s    z!MySQLDialect_mysqldb.import_dbapiz!Callable[[DBAPIConnection], None]c                   s"   t    ddd fdd}|S )Nr   None)connr2   c                   sB    d k	r |  |   }|d k	r>|  }|d|  |  d S )NzSET NAMES %s)character_set_namecursorexecuteclose)rG   charset_namerI   Zsuper_r    r!   
on_connect   s    z3MySQLDialect_mysqldb.on_connect.<locals>.on_connect)r(   rN   )r-   rN   r.   rM   r!   rN      s    
zMySQLDialect_mysqldb.on_connectr   zLiteral[True])dbapi_connectionr2   c                 C  s   |   dS )NT)Zping)r-   rO   r    r    r!   do_ping   s    zMySQLDialect_mysqldb.do_pingNr   r   zOptional[ExecutionContext]rF   )rI   	statement
parameterscontextr2   c                 C  s$   | ||}|d k	r |tt|_d S r3   )Zexecutemanyr   r   Z	_rowcount)r-   rI   rQ   rR   rS   Zrowcountr    r    r!   do_executemany   s    z#MySQLDialect_mysqldb.do_executemanyr   zOptional[Dict[str, Any]]r   )url_translate_argsr2   c           
      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 |fS )Ndbuserpasswd)Zdatabaseusernamepasswordcompressconnect_timeoutread_timeoutZwrite_timeoutclient_flagZlocal_infileZuse_unicodecharsetZssl_caZssl_keyZssl_certZ
ssl_capathZ
ssl_cipherZssl_check_hostname   sslr   )dictZtranslate_connect_argsupdatequeryr   Zcoerce_kw_typer>   r4   r0   get_found_rows_client_flag)
r-   rU   rV   optsrb   keyskeyZkw_typer_   Zclient_flag_found_rowsr    r    r!   create_connect_args   sJ      
z(MySQLDialect_mysqldb.create_connect_argszOptional[int]c              	   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CLIENTrB   rA   Z
FOUND_ROWS)r-   ZCLIENT_FLAGSr    r    r!   rg      s    

z,MySQLDialect_mysqldb._found_rows_client_flagzDBAPIModule.Errorr4   )	exceptionr2   c                 C  s
   |j d S )Nr   )args)r-   rm   r    r    r!   _extract_error_code
  s    z(MySQLDialect_mysqldb._extract_error_coder   )
connectionr2   c                 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)rp   rH   rB   r   warn)r-   rp   Z	cset_namer    r    r!   _detect_charset  s    z$MySQLDialect_mysqldb._detect_charsetzTuple[IsolationLevel, ...])
dbapi_connr2   c                 C  s   dS )N)ZSERIALIZABLEzREAD UNCOMMITTEDzREAD COMMITTEDzREPEATABLE READ
AUTOCOMMITr    r-   rt   r    r    r!   get_isolation_level_values"  s    z/MySQLDialect_mysqldb.get_isolation_level_valuesc                 C  s   |  S r3   )Zget_autocommitrv   r    r    r!   detect_autocommit_setting-  s    z.MySQLDialect_mysqldb.detect_autocommit_settingr   )rO   levelr2   c                   s0   |dkr| d n| d t || d S )Nru   TF)Z
autocommitr(   set_isolation_level)r-   rO   ry   r.   r    r!   rz   0  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   preparer__annotations__r)   r,   r   ZlanghelpersZmemoized_propertyrC   classmethodrE   rN   rP   rT   rk   rg   ro   rs   rw   rx   rz   __classcell__r    r    r.   r!   r#   ~   s:   
	  5r#   )%__doc__
__future__r   r9   typingr   r   r   r   r   r   r	   baser   r   r   r    r   Zutil.typingr   Zengine.baser   Zengine.interfacesr   r   r   r   r   r   r   Z
engine.urlr   r   r"   r#   dialectr    r    r    r!   <module>   s<   O =