U
    æãf}  ã                /   @   sÐ  d Z ddlZddlZddlZddlZddlmZmZmZ zddl	m
Z
 W n ek
r`   eZ
Y nX ddlmZmZ ddlmZmZmZmZmZmZ ddlmZmZmZmZ dd	l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+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2 ddl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZB ddlCmDZC e Ed¡ZFe EdejG¡ZHe EdejG¡ZIe Ed¡ZJddddddgZKeKddddddddd d!d"d#d$d%d&g ZLe MeN¡ Oe P¡ ¡ d'ZQd(ZRd)ZSd*ZTd+d,gZd-d.gZUd/ZVeWed0ƒrejXrd1ZVd2d3„ ZYd4d5„ ZZd6d7„ Z[dsd8d9„Z\d:d;„ Z]d<d=„ Z^d>d?„ Z_d@dA„ Z`dBdC„ ZadDdE„ ZbdFdGdEdCdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkdldmdndodpdqdrg/ZcdS )tz$MySQL X DevAPI Python implementationé    N)Ú	parse_qslÚunquoteÚurlparse)ÚJSONDecodeErroré   )ÚClientÚSession)ÚAuthÚLockContentionÚOPENSSL_CS_NAMESÚSSLModeÚTLS_VERSIONSÚTLS_CIPHER_SUITES)ÚSchemaÚ
CollectionÚTableÚView)ÚDbDoc)ÚErrorÚInterfaceErrorÚDatabaseErrorÚNotSupportedErrorÚ	DataErrorÚIntegrityErrorÚProgrammingErrorÚOperationalErrorÚInternalErrorÚ	PoolErrorÚTimeoutError)ÚColumnÚRowÚResultÚBufferingResultÚ	RowResultÚ	SqlResultÚ	DocResultÚ
ColumnType)Ú	StatementÚFilterableStatementÚSqlStatementÚFindStatementÚAddStatementÚRemoveStatementÚModifyStatementÚSelectStatementÚInsertStatementÚDeleteStatementÚUpdateStatementÚCreateCollectionIndexStatementÚExprÚReadStatementÚWriteStatement)Ú
ExprParserz,(?![^\(\)]*\))z!^\(address=(.+),priority=(\d+)\)$z^\(address=(.+)[,]*\)$z"^([a-zA-Z][a-zA-Z0-9+\-.]+)://(.*)ússl-certússl-caússl-keyússl-crlútls-versionsútls-ciphersuitesÚuserÚpasswordÚschemaÚhostÚportÚroutersÚsocketússl-modeÚauthzuse-pureúconnect-timeoutúconnection-attributesÚcompressionúcompression-algorithmsúdns-srvzVThe '{list}' list must not contain repeated values, the value '{value}' is duplicated.zdThe given tls-version: '{}' is not recognized as a valid TLS protocol version (should be one of {}).zHThe given tls_version: '{}' are no longer allowed (should be one of {}).zINo supported TLS protocol version found in the 'tls-versions' list '{}'. zTLSv1.2úTLSv1.3ÚTLSv1zTLSv1.1FÚHAS_TLSv1_3Tc           	      C   s‚  |   dd¡} d| ko.|  d¡dko.|  d¡dk oD|  d¡oD|  d¡}g }t |r^| dd… n| ¡}d	}|D ]Ô}i }t |¡}|r¨| d¡}t	| d
¡ƒ|d< |d7 }n t
 |¡}|rÈ| d¡}d|d< td |¡ƒ}|jsêtd |¡ƒ‚z|j|j|jd W n4 tk
r4 } ztd |¡dƒ‚W 5 d}~X Y nX | |¡ qld	|  k r^t|ƒk rln n
tddƒ‚|rzd|iS |d	 S )zÛParses a list of host, port pairs

    Args:
        path: String containing a list of routers or just router

    Returns:
        Returns a dict with parsed values of host, port and priority if
        specified.
    ú Ú ú,ú:r   ú[ú]éÿÿÿÿr   é   Úpriorityéd   z//{0}zInvalid address: {0})r@   rA   zInvalid URI: {0}i¢  Nz\You must either assign no priority to any of the routers or give a priority for every routeri   rB   )ÚreplaceÚcountÚ
startswithÚendswithÚ	_SPLIT_REÚsplitÚ_PRIORITY_REÚmatchÚgroupÚintÚ
_ROUTER_REr   ÚformatÚhostnamer   ÚupdaterA   Ú
ValueErrorr   ÚappendÚlen)	ÚpathÚarrayrB   Zaddress_listZpriority_countÚaddressÚrouterr_   Úerr© rn   ú3/tmp/pip-unpacked-wheel-mzf9r1ws/mysqlx/__init__.pyÚ_parse_address_listb   sF    
ÿÿþ




" þrp   c                 C   sè  ddi}t  | ¡}|r| ¡ nd| f\}} |dkr@td |¡ƒ‚|dkrPd|d< |  d	¡d
d
d… \}}| d¡d
d
d… \}}| d¡}||d
…  d¡dkr¼|dkr¼| dd¡\}|d< | 	d¡}|rÖ|rÖd|krätd | ¡ƒ‚| 
dd¡\}	}
t|	ƒt|
ƒ |d< |d< | d¡r(t|ƒ|d< n$| d¡r>tdƒ‚n| t|ƒ¡ d}t|dƒD ]ˆ\}}| dd¡ ¡ }||krŠtd |¡ƒ‚|tkr¨t| 	d¡ƒ||< n8| ¡ }|dkrÄd||< n|d krØd!||< n|||< qZ|S )"aq  Parses the connection string and returns a dictionary with the
    connection settings.

    Args:
        uri: mysqlx URI scheme to connect to a MySQL server/farm.

    Returns:
        Returns a dict with parsed values of credentials and address of the
        MySQL server/farm.

    Raises:
        :class:`mysqlx.InterfaceError`: If contains a invalid option.
    r?   rO   Úmysqlx)rq   ú
mysqlx+srvzScheme '{0}' is not validrr   TrJ   ú@NrU   ú?ú/ú)rT   r   r   z()rQ   zMalformed URI '{0}'r=   r>   )ru   z..Ú.rC   z\.zWindows Pipe is not supported)r=   r>   rJ   Ú_ú-zInvalid option: '{0}')Ú1Útrue)Ú0ÚfalseF)Ú_URI_SCHEME_REr_   Úgroupsr   rc   Ú	partitionÚrfindÚfindÚrsplitÚstripr]   r   rZ   re   rp   r   rX   ÚlowerÚ	_SSL_OPTS)ÚuriÚsettingsr_   ÚschemeÚuserinfoÚtmpr@   Z	query_strÚposr=   r>   Zinvalid_optionsÚkeyÚvalÚoptZval_strrn   rn   ro   Ú_parse_connection_uri•   sH    









r   c              	   C   sz  t |  ¡ ƒ t¡}|r*td d |¡¡ƒ‚d| krL| d D ]}t|dƒ q:nd| kr\t| ƒ d| kr²z"| d  ¡ | d< t	 
| d ¡ W n* ttfk
r°   td | d ¡ƒ‚Y nX d| krÊd	| krÊtd
ƒ‚d| krâd| krâtdƒ‚d	| kr|  d¡t	jt	jfkrtdƒ‚d	| kr:|  d¡t	jt	jt	jfkr:tdƒ‚d| kr”z"| d  ¡ | d< t 
| d ¡ W n, ttfk
r’   td | d ¡ƒ‚Y nX d| krÒ| d  ¡  ¡ }|dkrÊtd | d ¡ƒ‚|| d< d| krRt| d tƒr| d  ¡  d¡}|r| d¡| d< nd| d< nt| d ttfƒs:tdƒ‚|  d¡dkrRd| d< d| krdt| ƒ d| krÔzFt| d tƒrt| d ƒ| d< t| d tƒr®| d dk r²t‚W n tk
rÒ   tdƒ‚Y nX d| kr4t| d tƒsötd ƒ‚|  d!¡r
td"ƒ‚|  d#¡rtd$ƒ‚|  d¡rRtd%ƒ‚nd| krR|  d#¡sRd| d#< d&| krdt| ƒ d'| krvt| ƒ dS )(an  Validates the settings to be passed to a Session object
    the port values are converted to int if specified or set to 33060
    otherwise. The priority values for each router is converted to int
    if specified.

    Args:
        settings: dict containing connection settings.

    Raises:
        :class:`mysqlx.InterfaceError`: On any configuration issue.
    zInvalid option(s): '{0}'z', 'rB   i$  r@   rD   zInvalid SSL Mode '{0}'r:   r8   zCA Certificate not providedr9   r7   zClient Certificate not providedzCannot verify Server without CAz$Must verify Server if CA is providedrE   zInvalid Auth '{0}'rH   )Ú	preferredÚrequiredÚdisabledz†The connection property 'compression' acceptable values are: 'preferred', 'required', or 'disabled'. The value '{0}' is not acceptablerI   z[]rP   Nz@Invalid type of the connection property 'compression-algorithms'r“   rG   rF   r   zEThe connection timeout value must be a positive integer (including 0)rJ   z(The value of 'dns-srv' must be a booleanrC   z<Using Unix domain sockets with DNS SRV lookup is not allowedrA   z;Specifying a port number with DNS SRV lookup is not allowedzASpecifying multiple hostnames with DNS SRV look up is not allowedr;   r<   )ÚsetÚkeysÚ
differenceÚ
_SESS_OPTSr   rc   ÚjoinÚ_validate_hostsr…   r   ÚindexÚAttributeErrorrf   ÚgetZVERIFY_IDENTITYZ	VERIFY_CAZDISABLEDr	   r„   Ú
isinstanceÚstrr]   ÚlistÚtupleÚ_validate_connection_attributesra   Ú	TypeErrorÚboolÚ_validate_tls_versionsÚ_validate_tls_ciphersuites)rˆ   Zinvalid_optsrl   rH   Zcompression_algorithmsrn   rn   ro   Ú_validate_settingsÔ   s¨    ÿÿ
ÿÿ


þÿ
ÿÿ



ÿ



r¦   c                 C   sè   d| krŒ| d rŒz6t | d ƒ| d< | d dk s:| d dkrDtddƒ‚W nD tk
rd   tddƒ‚Y n( tk
rŠ   td | d ¡dƒ‚Y nX d| krÐ| d rÐzt | d ƒ| d< W qä tk
rÌ   td	ƒ‚Y qäX nd
| krä|rä|| d< dS )zØValidate hosts.

    Args:
        settings (dict): Settings dictionary.
        default_port (int): Default connection port.

    Raises:
        :class:`mysqlx.InterfaceError`: If priority or port are invalid.
    rV   r   rW   z1Invalid priority value, must be between 0 and 100i§  zInvalid priorityzInvalid priority: {}rA   zInvalid portr@   N)ra   r   Ú	NameErrorrf   rc   r   )rˆ   Údefault_portrn   rn   ro   r™   B  s*    
ÿ ÿ
r™   c           	      C   sÎ  i }d| krdS | d }t |tƒrü|dkr6i | d< dS | d¡rJ| d¡sb|dkrbtd |¡ƒ‚n–|dkrˆ|dkr|d	| d< ni | d< dS |d
d…  d¡}|D ]X}|dkr¬qž| d¡}|d }t|ƒd
krÒ|d
 nd}||krîtd |¡ƒ‚qž|||< qžn"t |tƒr:|D ]*}|| }t |tƒs,t	|ƒ}|||< qnät |t
ƒsP|dkrl|r`i | d< nd	| d< dS t |tƒrŽ|D ]}d||< q|nt |tƒr|D ]b}|dkr°qž| d¡}|d }t|ƒd
krØ|d
 nd}||krötd |¡ƒ‚n|||< qžnt |t
ƒstd |¡ƒ‚|rÂ|D ]˜}|| }t |tƒsNtd |¡ƒ‚t|ƒdkrjtd |¡ƒ‚| d¡r„td |¡ƒ‚t |tƒs td ||¡ƒ‚t|ƒdkr(td ||¡ƒ‚q(|| d< dS )z»Validate connection-attributes.

    Args:
        settings (dict): Settings dictionary.

    Raises:
        :class:`mysqlx.InterfaceError`: If attribute name or value exceeds size.
    rG   NrO   rR   rS   )ÚFalser}   ÚTruer{   z`The value of 'connection-attributes' must be a boolean or a list of key-value pairs, found: '{}')r©   r}   Fr   rT   rP   ú=r   z0Duplicate key '{}' used in connection-attributes)r   r   zOconnection-attributes must be Boolean or a list of key-value pairs, found: '{}'z(Attribute name '{}' must be a stringtypeé    z4Attribute name '{}' exceeds 32 characters limit sizerx   zEKey names in connection-attributes cannot start with '_', found: '{}'z0Attribute '{}' value: '{}' must be a string typei   z=Attribute '{}' value: '{}' exceeds 1024 characters limit size)r   rž   rZ   r[   r   rc   r]   rh   ÚdictÚreprr£   r”   rŸ   )	rˆ   Ú
attributesZ
conn_attrsZconn_attributesÚattrZattr_name_valÚ	attr_nameZattr_valÚ
attr_valuern   rn   ro   r¡   a  s®    	
ÿþ

þ



þþÿÿþ þ þ
r¡   c           	      C   sâ  g }d| krdS | d }t |tƒrœ| d¡r6| d¡sFtd |¡ƒ‚nT|dd…  d¡}|D ]<}| ¡ }|d	krtq\q\||krŽttjd
|dƒ‚| 	|¡ q\n€t |t
ƒrä|s²tdƒ‚|D ]*}||krÖttjd
|dƒ‚q¶| 	|¡ q¶n8t |tƒr|D ]}| 	|¡ qôntd d t¡|¡ƒ‚|s*tdƒ‚g }g }g }|D ]:}|tkrR| 	|¡ |tkrh| 	|¡ n
| 	|¡ q:|r°|dgkržtsžtt |t¡ƒ‚| ¡  || d< n.|rÈtt |t¡ƒ‚n|rÞtt |t¡ƒ‚dS )z¬Validate tls-versions.

    Args:
        settings (dict): Settings dictionary.

    Raises:
        :class:`mysqlx.InterfaceError`: If tls-versions name is not valid.
    r;   NrR   rS   z(tls-versions must be a list, found: '{}'r   rT   rP   rO   Útls_versions©rŸ   ÚvaluezKAt least one TLS protocol version must be specified in 'tls-versions' list.zMtls-versions should be a list with one or more of versions in {}. found: '{}'z, rK   )r   rž   rZ   r[   r   rc   r]   r„   ÚDUPLICATED_IN_LIST_ERRORrg   rŸ   r”   r˜   r   ÚDEPRECATED_TLS_VERSIONSÚTLS_V1_3_SUPPORTEDr   ÚTLS_VER_NO_SUPPORTEDÚsortÚTLS_VERSION_DEPRECATED_ERRORÚTLS_VERSION_ERROR)	rˆ   r³   Ztls_versions_settingsZtls_versÚtls_verZtls_versionZuse_tls_versionsZdeprecated_tls_versionsZnot_tls_versionsrn   rn   ro   r¤   Î  sŒ    	

ÿÿ ÿÿ
ÿÿ þ



ÿ
ÿÿ
ÿr¤   c                 C   sì  g }d| krdS | d }t |tƒrŠ| d¡r6| d¡sFtd |¡ƒ‚qÖ|dd…  d¡}|sdtd	ƒ‚|D ]}| ¡  ¡ }|rh| 	|¡ qhnLt |t
ƒr¤d
d„ |D ƒ}n2t |tƒrÈ|D ]}|r²| 	|¡ q²ntd |¡ƒ‚|  dd¡dkròtdd… n| d dd… }|jdd |d }g }i }g }	tdt |¡d … D ]"}
| t|
 ¡ |	 t|
 ¡ q8|D ]p}d|kr„||	kr„| 	|¡ nJ||krÀ|| }||kr´ttjd|dƒ‚n
| 	|¡ ntd |¡ƒ‚q`|sàtd	ƒ‚|| d< dS )z´Validate tls-ciphersuites.

    Args:
        settings (dict): Settings dictionary.

    Raises:
        :class:`mysqlx.InterfaceError`: If tls-ciphersuites name is not valid.
    r<   NrR   rS   z,tls-ciphersuites must be a list, found: '{}'r   rT   rP   z;No valid cipher suite found in the 'tls-ciphersuites' list.c                 S   s   g | ]}|r|‘qS rn   rn   )Ú.0Útls_csrn   rn   ro   Ú
<listcomp>>  s    ÿz._validate_tls_ciphersuites.<locals>.<listcomp>zLtls-ciphersuites should be a list with one or more ciphersuites. Found: '{}'r;   T)Úreverser   ry   Útls_ciphersuitesr´   z;The value '{}' in cipher suites is not a valid cipher suite)r   rž   rZ   r[   r   rc   r]   r„   Úupperrg   rŸ   r”   rœ   r   rº   rš   re   r   Úextendr   r›   r¶   )rˆ   rÂ   Ztls_ciphersuites_settingsZtls_cssr¿   r³   Znewer_tls_verZtranslated_namesZiani_cipher_suites_namesZossl_cipher_suites_namesr½   ÚnameZtranslated_namern   rn   ro   r¥      sz    	

ÿÿ

þ
ÿÿ

 ÿÿÿÿr¥   c                  O   s˜   i }| rZt | d tƒr$t| d ƒ}q€t | d tƒr€| d  ¡ D ]\}}||| dd¡< q>n&|r€| ¡ D ]\}}||| dd¡< qf|sŒtdƒ‚t|ƒ |S )aZ  Parses the connection string and returns a dictionary with the
    connection settings.

    Args:
        *args: Variable length argument list with the connection data used
               to connect to the database. It can be a dictionary or a
               connection string.
        **kwargs: Arbitrary keyword arguments with connection data used to
                  connect to the database.

    Returns:
        mysqlx.Session: Session object.

    Raises:
        TypeError: If connection timeout is not a positive integer.
        :class:`mysqlx.InterfaceError`: If settings not provided.
    r   rx   ry   zSettings not provided)r   rž   r   r­   ÚitemsrX   r   r¦   )ÚargsÚkwargsrˆ   r   rŽ   rn   rn   ro   Ú_get_connection_settingss  s    rÉ   c                  O   s   t | |Ž}t|ƒS )a°  Creates a Session instance using the provided connection data.

    Args:
        *args: Variable length argument list with the connection data used
               to connect to a MySQL server. It can be a dictionary or a
               connection string.
        **kwargs: Arbitrary keyword arguments with connection data used to
                  connect to the database.

    Returns:
        mysqlx.Session: Session object.
    )rÉ   r   )rÇ   rÈ   rˆ   rn   rn   ro   Úget_session—  s    
rÊ   c                 C   sT  t | ttfƒstdƒ‚t| ƒ}t |ttfƒs4tdƒ‚t |tƒrlzt |¡}W q’ tk
rh   tdƒ‚Y q’X n&i }| ¡ D ]\}}||| 	dd¡< qxt |tƒs¤tdƒ‚i }d|krJ| 
d¡}t |tƒsÎtdƒ‚| 
dd	¡|d< | 
d
d¡|d
< | 
dd¡|d< | 
dd¡|d< t|ƒdkr*td |¡ƒ‚t|ƒdkrJtd | ¡ ¡ƒ‚t||ƒS )a8  Creates a Client instance with the provided connection data and settings.

    Args:
        connection_string: A string or a dict type object to indicate the             connection data used to connect to a MySQL server.

            The string must have the following uri format::

                cnx_str = 'mysqlx://{user}:{pwd}@{host}:{port}'
                cnx_str = ('mysqlx://{user}:{pwd}@['
                           '    (address={host}:{port}, priority=n),'
                           '    (address={host}:{port}, priority=n), ...]'
                           '       ?[option=value]')

            And the dictionary::

                cnx_dict = {
                    'host': 'The host where the MySQL product is running',
                    'port': '(int) the port number configured for X protocol',
                    'user': 'The user name account',
                    'password': 'The password for the given user account',
                    'ssl-mode': 'The flags for ssl mode in mysqlx.SSLMode.FLAG',
                    'ssl-ca': 'The path to the ca.cert'
                    "connect-timeout": '(int) milliseconds to wait on timeout'
                }

        options_string: A string in the form of a document or a dictionary             type with configuration for the client.

            Current options include::

                options = {
                    'pooling': {
                        'enabled': (bool), # [True | False], True by default
                        'max_size': (int), # Maximum connections per pool
                        "max_idle_time": (int), # milliseconds that a
                            # connection will remain active while not in use.
                            # By default 0, means infinite.
                        "queue_timeout": (int), # milliseconds a request will
                            # wait for a connection to become available.
                            # By default 0, means infinite.
                    }
                }

    Returns:
        mysqlx.Client: Client object.

    .. versionadded:: 8.0.13
    z(connection_data must be a string or dictz+connection_options must be a string or dictzA'pooling' options must be given in the form of a document or dictry   rx   Zpoolingz<'pooling' options must be given in the form document or dictZenabledTÚmax_sizeé   Zmax_idle_timer   Zqueue_timeoutz Unrecognized pooling options: {}z#Unrecognized connection options: {})r   rž   r­   r   rÉ   ÚjsonÚloadsr   rÆ   rX   Úpoprh   rc   r•   r   )Zconnection_stringZoptions_stringZsettings_dictZoptions_dictr   rµ   Zpooling_options_dictZpooling_optionsrn   rn   ro   Ú
get_client¨  sF    2





ÿ
ÿÿÿrÐ   r   r   Úexprr	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r4   r5   r2   r3   )N)dÚ__doc__ÚrerÍ   ÚloggingÚsslÚurllib.parser   r   r   Zjson.decoderr   ÚImportErrorrf   Ú
connectionr   r   Ú	constantsr	   r
   r   r   r   r   Zcrudr   r   r   r   Zdbdocr   Úerrorsr   r   r   r   r   r   r   r   r   r   r   Úresultr   r    r!   r"   r#   r$   r%   r&   Z	statementr'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   rÑ   r6   Úcompiler\   ÚVERBOSEr^   rb   r~   r†   r—   Ú	getLoggerÚ__name__Ú
addHandlerÚNullHandlerr¶   r¼   r»   r¹   r·   r¸   ÚhasattrrM   rp   r   r¦   r™   r¡   r¤   r¥   rÉ   rÊ   rÐ   Ú__all__rn   rn   rn   ro   Ú<module>   sÒ   
 4(D


ÿ       ýÿ3?n
mRS$d                                  è