U
    ¤�©j¦  ã                   @  sD  d Z ddlmZ ddlZddlZddlmZ ddlmZm	Z	 ddl
mZmZmZmZmZ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 dd
l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& ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0 e�rddl1m2Z2 dZ3dZ4dZ5dZ6dZ7dZ8dZ9dZ:G dd„ dƒZ;dS )z,Implements the MySQL Client/Server protocol.é    )ÚannotationsN)Údeque)ÚDecimalÚDecimalException)	ÚTYPE_CHECKINGÚAnyÚDequeÚDictÚListÚOptionalÚSequenceÚTupleÚUnioné   )Úutils)ÚPARAMETER_COUNT_AVAILABLEÚ
ClientFlagÚ	FieldFlagÚ	FieldTypeÚ	ServerCmd)ÚMySQLConverter)ÚDatabaseErrorÚInterfaceErrorÚProgrammingErrorÚget_exception)Úlogger)ÚMySQLAuthPluginÚget_auth_plugin)Ú"MySQLCachingSHA2PasswordAuthPlugin)ÚBinaryProtocolTypeÚDescriptionTypeÚEofPacketTypeÚHandShakeTypeÚOkPacketTypeÚStatsPacketTypeÚ
StrOrBytes)ÚMySQLSocketé
   éþ   é   éÿ   é-   i   @c                   @  sâ  e Zd ZdZedddœdd„ƒZedddœdd„ƒZedddœd	d
„ƒZedddœdd„ƒZeddddœdd„ƒZ	ed~ddddddddddœ	dd„ƒZ
edededdddddf
ddddddddddddddd œd!d"„ƒZeedefddddd#œd$d%„ƒZeddd&dd'œd(d)„ƒZed€dddd+œd,d-„ƒZeddd.œd/d0„ƒZedd1d.œd2d3„ƒZedd4d.œd5d6„ƒZed�ddd8d9œd:d;„ƒZdd<d.œd=d>„Zed‚ddd@dAœdBdC„ƒZdƒdDdEddFdGœdHdI„Zedd8dJdKœdLdM„ƒZedd8dNdKœdOdP„ƒZed„dddRdSœdTdU„ƒZedddVdWœdXdY„ƒZeddZd.œd[d\„ƒZd…d]ddd^d_œd`da„Zd†dDd]dddbdcœddde„Zeddfd.œdgdh„ƒZeddidjœdkdl„ƒZ edmdJdjœdndo„ƒZ!edpdJdjœdqdr„ƒZ"edddddsœdtdu„ƒZ#d‡ddwdxddyddzddd{œ	d|d}„Z$dS )ˆÚMySQLProtocolzRImplements MySQL client/server protocol

    Create and parses MySQL packets.
    Úbytes)ÚpktÚreturnc                 C  s    | d t kstdƒ‚| dd… S )a  Parse a MySQL auth more data packet.

        Args:
            pkt: Packet representing an `auth more data` response.

        Returns:
            auth_data: Authentication method data (see [1]).

        Raises:
            InterfaceError: If packet's status tag doesn't
                            match `protocol.EXCHANGE_FURTHER_STATUS`.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_auth_more_data.html
        é   z"Failed parsing AuthMoreData packeté   N)ÚEXCHANGE_FURTHER_STATUSr   )r.   © r3   ú</tmp/pip-unpacked-wheel-d6bt0v6z/mysql/connector/protocol.pyÚparse_auth_more_data\   s    z"MySQLProtocol.parse_auth_more_datazTuple[str, bytes]c                 C  sV   | d t krtdƒ‚tj| dd… dd�\} }| rJ| d dkrJ| dd… } | ¡ | fS )	a|  Parse a MySQL auth switch request packet.

        Args:
            pkt: Packet representing an `auth switch request` response.

        Returns:
            plugin_name: Name of the client authentication plugin to switch to.
            plugin_provided_data: Plugin provided data (see [1]).

        Raises:
            InterfaceError: If packet's status tag doesn't
                            match `protocol.AUTH_SWITCH_STATUS`.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/                latest/page_protocol_connection_phase_packets_protocol_
                auth_switch_request.html
        r0   z'Failed parsing AuthSwitchRequest packetr1   Nó    ©Úendéÿÿÿÿr   )ÚAUTH_SWITCH_STATUSr   r   Úread_stringÚdecode)r.   Úplugin_namer3   r3   r4   Úparse_auth_switch_requestr   s    z'MySQLProtocol.parse_auth_switch_requestc                 C  sF   t  | dd… d¡\} }|tkr(tdƒ‚t j| dd�\} }| ¡ | fS )a¦  Parse a MySQL auth next factor packet.

        Args:
            pkt: Packet representing an `auth next factor` response.

        Returns:
            plugin_name: Name of the client authentication plugin.
            plugin_provided_data: Initial authentication data for that
                                  client plugin (see [1]).

        Raises:
            InterfaceError: If packet's packet type doesn't
                            match `protocol.MFA_STATUS`.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_auth_                next_factor_request.html
        r0   Nr   z.Failed parsing AuthNextFactor packet (invalid)r6   r7   )r   Úread_intÚ
MFA_STATUSr   r;   r<   )r.   Ústatusr=   r3   r3   r4   Úparse_auth_next_factor�   s
    z$MySQLProtocol.parse_auth_next_factorzDict[str, str])Ú
conn_attrsr/   c              	     s¾   ˆ D ]}ˆ | dkrdˆ |< qt ‡ fdd„ˆ D ƒƒtˆ  ¡ ƒ tˆ  ¡ ƒ }t d|¡g}ˆ D ]T}| t dt|ƒ¡¡ | | ¡ ¡ | t dtˆ | ƒ¡¡ | ˆ |  ¡ ¡ q^d |¡S )az  Encode the connection attributes.

        Args:
            conn_attrs: Connection attributes.

        Returns:
            serialized_conn_attrs: Serialized connection attributes as per [1].

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_handshake_response.html
        NÚ c                 3  s"   | ]}t |ƒt ˆ | ƒ V  qd S )N)Úlen)Ú.0Úx©rC   r3   r4   Ú	<genexpr>º   s     z0MySQLProtocol.make_conn_attrs.<locals>.<genexpr>ú<Bó    )	ÚsumrE   ÚkeysÚvaluesÚstructÚpackÚappendÚencodeÚjoin)rC   Ú	attr_nameZconn_attrs_lenZconn_attrs_packetr3   rH   r4   Úmake_conn_attrs¨   s     

ÿ
þÿzMySQLProtocol.make_conn_attrsÚintzOptional[str])Úclient_flagsÚdatabaser/   c                 C  s   | t j@ r|r| ¡ d S dS )aÙ  Prepare database string for handshake response.

        Args:
            client_flags: Integer representing client capabilities flags.
            database: Initial database name for the connection.

        Returns:
            serialized_database: Serialized database name as per [1].

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_handshake_response.html
        r6   )r   ZCONNECT_WITH_DBrR   )rW   rX   r3   r3   r4   Úconnect_with_dbÇ   s    ÿÿýzMySQLProtocol.connect_with_dbNFÚstrÚboolzOptional[Dict[str, Any]]zTuple[bytes, MySQLAuthPlugin])	Ú	auth_dataÚusernameÚpasswordrW   Úauth_pluginÚauth_plugin_classÚssl_enabledÚplugin_configr/   c              
   C  sÄ   |sdt |||d�fS |dkr"i }z&t||ƒ|||d�}|j| f|Ž}	W n6 ttfk
r~ }
 ztd|
› �ƒ|
‚W 5 d}
~
X Y nX |	dkr˜td|j› �ƒ‚|tj@ r´t 	t
|	ƒ¡|	 n|	d }	|	|fS )a  Prepare the first authentication response.

        Args:
            auth_data: Authorization data from initial handshake.
            username: Account's username.
            password: Account's password.
            client_flags: Integer representing client capabilities flags.
            auth_plugin: Authorization plugin name.
            auth_plugin_class: Authorization plugin class (has higher precedence
                               than the authorization plugin name).
            ssl_enabled: Whether SSL is enabled or not.
            plugin_config: Custom configuration to be passed to the auth plugin
                           when invoked. The parameters defined here will override
                           the ones defined in the auth plugin itself.

        Returns:
            auth_response: Authorization plugin response.
            auth_strategy: Authorization plugin instance created based
                           on the provided `auth_plugin` and `auth_plugin_class`
                           parameters.

        Raises:
            InterfaceError: If authentication fails or when got a NULL auth response.
        r6   )ra   NzFailed authentication: z8Got NULL auth response while authenticating with plugin )r   r   Úauth_responseÚ	TypeErrorr   Únamer   ÚSECURE_CONNECTIONr   Ú	int1storerE   )r\   r]   r^   rW   r_   r`   ra   rb   Úauth_strategyrc   Úerrr3   r3   r4   Úauth_plugin_first_responseÜ   s4    #  ÿ  ÿ"
ÿÿýz(MySQLProtocol.auth_plugin_first_responser   r"   zOptional[Dict[str, str]])Ú	handshaker]   r^   rX   ÚcharsetrW   Úmax_allowed_packetr_   r`   rC   Úis_change_user_requestra   rb   r/   c              
   C  s   |  ¡ }g }|
rt d¡ t d¡ | dkr6tdƒd‚|  d¡dkrNtdƒd‚z|pZ| d }W n8 ttfk
r– } ztd|› d	�ƒd‚W 5 d}~X Y nX t d
|¡ |
rÌ| t 	dt
|ƒ› d�tj|¡¡ n,d}| t 	d|› t
|ƒ› d�||||¡¡ tj| d |||||||d�\}}| |¡ | t ||¡¡ |
�rN| t 	d|¡¡ |tj@ �rl| |  ¡ d ¡ |tj@ �r’|	dk	�r’| t |	¡¡ d |¡|fS )a²  Make a MySQL Authentication packet.

        Args:
            handshake: Initial handshake.
            username: Account's username.
            password: Account's password.
            database: Initial database name for the connection
            charset: Client charset (see [2]), only the lower 8-bits.
            client_flags: Integer representing client capabilities flags.
            max_allowed_packet: Maximum packet size.
            auth_plugin: Authorization plugin name.
            auth_plugin_class: Authorization plugin class (has higher precedence
                               than the authorization plugin name).
            conn_attrs: Connection attributes.
            is_change_user_request: Whether is a `change user request` operation or not.
            ssl_enabled: Whether SSL is enabled or not.
            plugin_config: Custom configuration to be passed to the auth plugin
                           when invoked. The parameters defined here will override
                           the one defined in the auth plugin itself.

        Returns:
            handshake_response: Handshake response as per [1].
            auth_strategy: Authorization plugin instance created based
                           on the provided `auth_plugin` and `auth_plugin_class`.

        Raises:
            ProgrammingError: Handshake misses authentication info.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_handshake_response.html

            [2]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_basic_character_set.html#a_protocol_character_set
        zGot a `change user` requestzStarting authorization phaseNzGot a NULL handshaker\   z$Handshake misses authentication infor_   z-Handshake misses authentication plugin info (ú)z#The provided initial strategy is %srJ   ZsxZxxxxxxxxxxxxxxxxxxxxxxz<IIH)r\   r]   r^   rW   r_   r`   ra   rb   ú<Hr6   rK   )rR   r   Údebugr   Úgetrd   ÚKeyErrorrQ   rO   rP   rE   r   ZCHANGE_USERr,   rj   rY   r   ÚPLUGIN_AUTHZCONNECT_ARGSrU   rS   )rk   r]   r^   rX   rl   rW   rm   r_   r`   rC   rn   ra   rb   Z
b_usernameZresponse_payloadri   Zfillerrc   rh   r3   r3   r4   Ú	make_auth  sn    3




ÿþýÿûÿø


zMySQLProtocol.make_auth)rl   rW   rm   r/   c                 C  s$   d  t |¡t |¡t | ¡dg¡S )a“  Make a SSL authentication packet (see [1]).

        Args:
            charset: Client charset (see [2]), only the lower 8-bits.
            client_flags: Integer representing client capabilities flags.
            max_allowed_packet: Maximum packet size.

        Returns:
            ssl_request_pkt: SSL connection request packet.

        References:
            [1]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_connection_phase_packets_protocol_ssl_request.html

            [2]: https://dev.mysql.com/doc/dev/mysql-server/latest/                page_protocol_basic_character_set.html#a_protocol_character_set
        rK   s                         ©rS   r   Ú	int4storeÚ	int2store)rl   rW   rm   r3   r3   r4   Úmake_auth_ssl™  s    üÿzMySQLProtocol.make_auth_sslzOptional[bytes])ÚcommandÚargumentr/   c                 C  s   t  | ¡}|dkr|S || S )z(Make a MySQL packet containing a commandN)r   rg   )rz   r{   Údatar3   r3   r4   Úmake_commandº  s    
zMySQLProtocol.make_commandr   )Ústatement_idÚrowsr/   c                 C  s   t  | ¡t  |¡ S )z0Make a MySQL packet with Fetch Statement command)r   rw   )r~   r   r3   r3   r4   Úmake_stmt_fetchÀ  s    zMySQLProtocol.make_stmt_fetch)Úpacketr/   c           	   	   C  s’  i }t  d| dd… ¡d |d< |d tkrDtd|d › dt› �ƒ‚tj| dd… dd	�\} |d
< t  d| dd… ¡\|d< }}|d< |d< }}|d
  ¡ |d
< | dd… } t || ¡}d}|tj	@ �r|rÜt
d|d ƒnd}| d|… }| |d… } |d dk�r|dd… }|tj@ �rrd| k�rH|d
  d¡�rHd|  } |d< ntj| dd	�\} |d< |d  d¡|d< nd|d< || |d< ||d< |S )zParse a MySQL Handshake-packet.ú<xxxxBr   r1   Úprotocolz$Protocol mismatch; server version = z, client version = Nr6   r7   Zserver_version_originalz<I8sx2sBH2sBxxxxxxxxxxé   Zserver_threadidrl   Zserver_statusrK   é   é   r9   z5.5.8r_   úutf-8Zmysql_native_passwordr\   Úcapabilities)rO   ÚunpackÚPROTOCOL_VERSIONr   r   r;   r<   Zintreadr   rf   Úminrt   Ú
startswith)	r�   ÚresZ
auth_data1Zcapabilities1Zcapabilities2Zauth_data_lengthrˆ   Z
auth_data2Úsizer3   r3   r4   Úparse_handshakeÅ  sP    ÿ
 ÿøÿzMySQLProtocol.parse_handshaker#   c              
   C  sê   | d dkst dƒ‚i }z t d| dd… ¡d |d< t | dd… ¡\} |d< t | ¡\} |d	< t d
| dd… ¡\|d< |d< | dd… } | r¶t | ¡\} |d< |d  d¡|d< W n, tk
rä } zt dƒ|‚W 5 d}~X Y nX |S )zParse a MySQL OK-packetr0   r   z#Failed parsing OK packet (invalid).r‚   r1   Zfield_countNZaffected_rowsZ	insert_idz<HHÚstatus_flagÚwarning_countZinfo_msgr‡   zFailed parsing OK packet.)r   rO   r‰   r   Úread_lc_intÚread_lc_stringr<   Ú
ValueError)r�   Z	ok_packetri   r3   r3   r4   Úparse_okù  s$    ýzMySQLProtocol.parse_okzOptional[int]c              
   C  sT   zt  | dd… ¡d }|W S  tjtfk
rN } ztdƒ|‚W 5 d}~X Y nX dS )z=Parse a MySQL packet with the number of columns in result setr0   Nr   zFailed parsing column count)r   r’   rO   Úerrorr”   r   )r�   Úcountri   r3   r3   r4   Úparse_column_count  s
    z MySQLProtocol.parse_column_countr‡   r    )r�   Úencodingr/   c              	   C  s¼   t  | dd… ¡\} }t  | ¡\} }t  | ¡\} }t  | ¡\} }t  | ¡\} }t  | ¡\} }zt d| ¡\}}}}}W n  tjk
r–   tdƒd‚Y nX | |¡|dddd| tj@ ||f	S )zParse a MySQL column-packet.r0   Nz	<xHIBHBxxz!Failed parsing column information)	r   r“   rO   r‰   r–   r   r<   r   ZNOT_NULL)r�   r™   Ú_re   rl   Zcolumn_typeÚflagsr3   r3   r4   Úparse_column  s6    
úû
÷zMySQLProtocol.parse_columnr!   c              
   C  sš   |d dkr|   |¡S d}i }zt d|¡}W n. tjk
r\ } zt|ƒ|‚W 5 d}~X Y nX |d dkrvt|ƒdks~t|ƒ‚|d	 |d
< |d |d< |S )zParse a MySQL EOF-packetr0   r   zFailed parsing EOF packet.z<xxxBBHHNr   r(   é	   r)   r‘   é   r�   )r•   rO   r‰   r–   r   rE   )Úselfr�   Úerr_msgr�   Úunpackedri   r3   r3   r4   Ú	parse_eof:  s    
zMySQLProtocol.parse_eofTr$   )r�   Úwith_headerr/   c           	      C  s   d}i }dg}d}|r*| dd…   d¡}n
|   d¡}|D ]â}zdd„ |  dd	¡D ƒ\}}W n, tk
r† } zt|ƒ|‚W 5 d}~X Y nX | d
¡}zt|ƒ||< W q8 ttfk
�r   zt| d
¡ƒ||< W nD tk
�r } z$t|› d|› dt|ƒ› d�ƒ|‚W 5 d}~X Y nX Y q8X q8|S )zParse the statistics packetz)Failed getting COM_STATISTICS informationrK   r0   Ns     c                 S  s   g | ]}|  ¡ ‘qS r3   )Ústrip)rF   Úvr3   r3   r4   Ú
<listcomp>\  s     z2MySQLProtocol.parse_statistics.<locals>.<listcomp>ó   :r)   r‡   z (ú:ro   )	Úsplitr”   r   r<   rV   rs   r   r   Úrepr)	r�   r£   Úerrmsgr�   ÚpairsZlblÚpairÚvalri   r3   r3   r4   Úparse_statisticsN  s*    

:zMySQLProtocol.parse_statisticsr&   zTuple[int, ...]zATuple[List[Tuple[Optional[bytes], ...]], Optional[EofPacketType]])ÚsockÚversionr—   r/   c                 C  s"  |}g }d}d}d}|s ||kr$�q|  ¡ }	|	 d¡r–|	dd… g}
|  ¡ }	|	 d¡rr|
 |	dd… ¡ |  ¡ }	qL|
 |	dd… ¡ t d |
¡¡}nB|	d dkr¾|	d dk r¾|  |	¡}d}nd}t t|	dd… ƒ¡}|dkrô|dk	rô| |¡ n|dk�r|dk�rt|	ƒ‚|d7 }q||fS )	z¶Read MySQL text result

        Reads all or given number of rows from the socket.

        Returns a tuple with 2 elements: a list with all rows and
        the EOF packet.
        Nr   s   ÿÿÿr0   rK   r(   é   r   )	ÚrecvrŒ   rQ   r   Zread_lc_string_listrS   r¢   r-   r   )rŸ   r°   r±   r—   rš   r   ÚeofZrowdataÚir�   Zdatasr3   r3   r4   Úread_text_resultk  s6    




zMySQLProtocol.read_text_resultzTuple[bytes, int])r�   Úfieldr/   c                 C  s¨   |d t jkrd}d}nV|d t jkr0d}d}n>|d t jt jfkrNd}d}n |d t jkrfd}d}ntd	ƒ‚|d
 tj@ r„| 	¡ }| |d… t
 || d|… ¡d fS )z%Parse an integer from a binary packetr   ú<bú<hr)   ú<ir0   ú<qr†   zUnknown integer typer²   Nr   )r   ÚTINYÚSHORTÚINT24ÚLONGÚLONGLONGr”   r   ZUNSIGNEDÚupperrO   r‰   )r�   r·   Úformat_Úlengthr3   r3   r4   Ú_parse_binary_integer—  s     z#MySQLProtocol._parse_binary_integerzTuple[bytes, float]c                 C  sD   |d t jkrd}d}nd}d}| |d… t || d|… ¡d fS )z)Parse a float/double from a binary packetr   r†   ú<dr0   z<fNr   )r   ÚDOUBLErO   r‰   )r�   r·   rÃ   rÂ   r3   r3   r4   Ú_parse_binary_float±  s    z!MySQLProtocol._parse_binary_floatÚutf8zTuple[bytes, Decimal])r�   rl   r/   c                 C  s    t  | ¡\} }| t| |¡ƒfS )z(Parse a New Decimal from a binary packet)r   r“   r   r<   )r�   rl   Úvaluer3   r3   r4   Ú_parse_binary_new_decimal¿  s    z'MySQLProtocol._parse_binary_new_decimalz?Tuple[bytes, Optional[Union[datetime.date, datetime.datetime]]])r�   Ú
field_typer/   c              	   C  sô   | d }d}|dkrpt  d| dd… ¡d }| d }| d }|tjtjfkr^tj|||d�}qàtj|||d�}np|dkràd}|d	kr t  d
| d|d … ¡d }tjt  d| dd… ¡d | d | d | d | d | d |d�}| |d d… |fS )z&Parse a timestamp from a binary packetr   Nr0   rp   r   rž   )ÚyearÚmonthÚdayr²   é   ú<Ir†   r1   é   )rÌ   rÍ   rÎ   ÚhourÚminuteÚsecondÚmicrosecond)rO   r‰   r   ÚDATETIMEÚ	TIMESTAMPÚdatetimeÚdate)r�   rË   rÃ   rÉ   rÌ   rÍ   rÎ   Úmcsr3   r3   r4   Ú_parse_binary_timestampÇ  s.    ù
z%MySQLProtocol._parse_binary_timestampz Tuple[bytes, datetime.timedelta]c                 C  s´   | d }|s | dd… t  ¡ fS | d|d … }d}|dkrTt d|dd… ¡d }t d|dd… ¡d }|d dkr€|d9 }t j||d ||d	 |d d
�}| |d d… |fS )z'Parse a time value from a binary packetr   r   Nr†   rÐ   r1   r9   r²   rÑ   )ÚdaysÚsecondsÚmicrosecondsÚminutesÚhours)rØ   Ú	timedeltarO   r‰   )r�   rÃ   r|   rÚ   rÜ   Útmpr3   r3   r4   Ú_parse_binary_timeç  s$    ûz MySQLProtocol._parse_binary_timezList[DescriptionType]zTuple[BinaryProtocolType, ...])Úfieldsr�   rl   r/   c           
   	   C  s8  t |ƒd d d }dd„ |d|… D ƒ}||d… }g }d}t|ƒD �]æ\}}	|t|d d ƒ d|d d > @ r€| d¡ qF|	d tjtjtjtjtj	fkr¼|  
||	¡\}}| |¡ qF|	d tjtjfkrì|  ||	¡\}}| |¡ qF|	d tjtjfk�r|  ||¡\}}| |¡ qF|	d tjtjtjfk�rX|  ||	d ¡\}}| |¡ qF|	d tjk�r‚|  |¡\}}| |¡ qF|	d tjk�r²t |¡\}}| t |¡¡ qF|	d tjk�sÐ|	d d	k�rêt |¡\}}| |¡ qFt |¡\}}z| | |¡¡ W qF tk
�r,   | |¡ Y qFX qFt |ƒS )
z(Parse values from a binary result packetr²   r)   r†   c                 S  s   g | ]}t |ƒ‘qS r3   )rV   )rF   rµ   r3   r3   r4   r¦     s     z6MySQLProtocol._parse_binary_values.<locals>.<listcomp>r   Nr   é?   )!rE   Ú	enumeraterV   rQ   r   r¼   r½   r¾   r¿   rÀ   rÄ   rÆ   ÚFLOATrÇ   ÚDECIMALZ
NEWDECIMALrÊ   rÖ   ÚDATEr×   rÛ   ÚTIMErã   ZVECTORr   r“   r   Z_vector_to_pythonr   ZBINARYr<   ÚUnicodeDecodeErrorÚtuple)
rŸ   rä   r�   rl   Znull_bitmap_lengthÚnull_bitmaprN   rÉ   Úposr·   r3   r3   r4   Ú_parse_binary_valuesþ  s\    $
ûýz"MySQLProtocol._parse_binary_valueszDTuple[List[Tuple[BinaryProtocolType, ...]], Optional[EofPacketType]])r°   Úcolumnsr—   rl   r/   c           
      C  s¸   g }d}d}d}|dk	rq°||kr$q°t | ¡ ƒ}	|	d dkrL|  |	¡}d}n&|	d dkrrd}|  ||	dd… |¡}|dkrŽ|dk	rŽ| |¡ n|dkr¦|dkr¦t|	ƒ‚|d7 }q||fS )zwRead MySQL binary protocol result

        Reads all or given number of binary resultset rows from the socket.
        Nr   r0   r(   r1   r   )r-   r³   r¢   rï   rQ   r   )
rŸ   r°   rð   r—   rl   r   r´   rN   rµ   r�   r3   r3   r4   Úread_binary_result8  s*    

z MySQLProtocol.read_binary_resultzDict[str, int]c              
   C  s²   | d dkst dƒ‚i }zht | dd… d¡\} |d< t | d¡\} |d< t | d¡\} |d	< | d
d… } t | d¡\} |d< W n, tk
r¬ } zt dƒ|‚W 5 d}~X Y nX |S )z(Parse a MySQL Binary Protocol OK packet.r0   r   zFailed parsing Binary OK packetr1   Nr~   r)   Znum_columnsZ
num_paramsr   r‘   )r   r   r?   r”   )r�   Zok_pktri   r3   r3   r4   Úparse_binary_prepare_ok]  s    z%MySQLProtocol.parse_binary_prepare_okzTuple[bytes, int, int])rÉ   r/   c                 C  s´   d}d}| dk rX| dkr$d}t j}q¢| dkr8d}t j}q¢| dkrLd}t j}q¢d	}t j}nJd
}| dkrpd}t j}n2| dkr„d}t j}n| dkr˜d}t j}n
t j}d}t || ¡||fS )z0Prepare an integer for the MySQL binary protocolNr   i€ÿÿÿr¸   i €ÿÿr¹   i   €rº   r»   é€   r*   rJ   iÿÿ  rp   l   ÿÿ rÐ   z<Q)r   r¼   r½   r¿   rÀ   rO   rP   )rÉ   rË   r›   rÂ   r3   r3   r4   Úprepare_binary_integero  s6    z$MySQLProtocol.prepare_binary_integerz'Union[datetime.date, datetime.datetime]c                 C  sÂ   t | tjƒrtj}nt | tjƒr(tj}ntdƒ‚t | j	¡t 
| j¡t 
| j¡g}t | tjƒr¢| t 
| j¡t 
| j¡t 
| j¡g¡ | jdkr¢| t | j¡¡ d |¡}t 
t|ƒ¡| |fS )aƒ  Prepare a timestamp object for the MySQL binary protocol

        This method prepares a timestamp of type datetime.datetime or
        datetime.date for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        z2Argument must a datetime.datetime or datetime.dater   rK   )Ú
isinstancerØ   r   rÖ   rÙ   ré   r”   r   rx   rÌ   rg   rÍ   rÎ   ÚextendrÒ   rÓ   rÔ   rÕ   rQ   rw   rS   rE   )rÉ   rË   ÚchunksÚpackedr3   r3   r4   Úprepare_binary_timestamp‘  s(    


ý


ýÿ

z&MySQLProtocol.prepare_binary_timestampz(Union[datetime.timedelta, datetime.time]c           
      C  s  t | tjtjfƒstdƒ‚tj}d}d}tg ƒ}t | tjƒr | jdk rJd}t	| j
dƒ\}}t	|dƒ\}}| t t| jƒ¡t |¡t |¡t |¡g¡ | j}n6| t d¡t | j¡t | j¡t | j¡g¡ | j}|rê| t |¡¡ | t |¡¡ d |¡}	t t|	ƒ¡|	 |fS )a�  Prepare a time object for the MySQL binary protocol

        This method prepares a time object of type datetime.timedelta or
        datetime.time for sending over the MySQL binary protocol.
        A tuple is returned with the prepared value and field type
        as elements.

        Raises ValueError when the argument value is of invalid type.

        Returns a tuple.
        z3Argument must a datetime.timedelta or datetime.timer   Nr   i  é<   rK   )rõ   rØ   rá   Útimer”   r   rê   r   rÜ   ÚdivmodrÝ   rö   r   rw   Úabsrg   rÞ   rÒ   rÓ   rÔ   rÕ   rQ   Ú
appendleftrS   rE   )
rÉ   rË   ÚnegativerÚ   r÷   rà   Ú	remainderZminsZsecsrø   r3   r3   r4   Úprepare_binary_time¼  s@    
üÿ


üÿ
z!MySQLProtocol.prepare_binary_time)Ú	statementÚparamr|   r/   c                 C  s   d  t | ¡t |¡|g¡S )zMPrepare long data for prepared statements

        Returns a string.
        rK   rv   )r  r  r|   r3   r3   r4   Úprepare_stmt_send_long_dataô  s    z)MySQLProtocol.prepare_stmt_send_long_datar3   zSequence[BinaryProtocolType]r   z Optional[Dict[int, Tuple[bool]]]z.Optional[List[Tuple[str, BinaryProtocolType]]])	r~   r|   Ú
parametersr›   Úlong_data_usedrl   Úquery_attrsÚconverter_str_fallbackr/   c	              	   C  s  d}	dgt |ƒd d  }
g }g }d}t |ƒ}g }|s:|n|t }|dkrNd}|dkrZi }|r”t|ƒ}|D ]\}}| |¡ qjdgt |ƒd d  }
|sž|�r*|t |ƒkr²td	ƒ‚t|ƒD �]l\}}d}|dk�r|
|d   d|d > O  < | t tj	¡t |¡ ¡ qº||k�r6|| d �r,tj
}ntj}�nšt|tƒ�r`|  |¡\}}}| |¡ �npt|tƒ�r˜| |¡}| t t |ƒ¡| ¡ tj}�n8t|tƒ�rÆ| t t |ƒ¡| ¡ tj}�n
t|tƒ�r| t t t|ƒ |¡ƒ¡t|ƒ |¡ ¡ tj}nÊt|tƒ�r,| t d
|¡¡ tj}n¤t|tjtjfƒ�rZ|  |¡\}}| |¡ nvt|tjtjfƒ�rˆ|  |¡\}}| |¡ nH|�r¼t|ƒ |¡}| t t |ƒ¡| ¡ tj}ntd|j j!› d�ƒ‚| t |¡t |¡ ¡ |rº|d |krº|||  d  |¡}| t t |ƒ¡| ¡ qºt "|¡t |¡t "|	¡g}|dk	�r^|t |ƒ }n|}|�r|dk	�r‚| t |¡¡ | #dd„ |
D ƒ¡ | t d¡¡ d}|D ]N}| |¡ |dk	�rò|d |k�rè| |||  ¡ n
| d¡ |d7 }�q®|D ]}| |¡ �qd $|¡S )z6Make a MySQL packet with the Statement Execute commandr   r   r²   r†   rK   Zutf8mb4rÈ   NzTFailed executing prepared statement: data values does not match number of parametersrÅ   z&MySQL binary protocol can not handle 'z	' objectsc                 S  s   g | ]}t  d |¡‘qS )ÚB)rO   rP   )rF   Úbitr3   r3   r4   r¦   m  s     z3MySQLProtocol.make_stmt_execute.<locals>.<listcomp>r6   )%rE   r   ÚlistrQ   r   ræ   r   rg   r   ZNULLZBLOBÚSTRINGrõ   rV   rô   rZ   rR   Zlc_intr-   r   rè   ÚfloatrO   rP   rÆ   rØ   rÙ   rù   rá   rû   r  r   Ú	__class__Ú__name__rw   rö   rS   )rŸ   r~   r|   r  r›   r  rl   r  r  Ziteration_countrí   rN   Útypesrø   Zdata_lenZquery_attr_namesrš   Zattr_valrî   rÉ   Ú_flagsrË   re   r�   Zparameter_countr—   Za_typeZa_valuer3   r3   r4   Úmake_stmt_executeü  sÄ    
ÿ
ÿ

ü


ÿÿÿý




zMySQLProtocol.make_stmt_execute)NFN)N)r   )r‡   )T)r   )rÈ   )r‡   )r   r‡   )r3   r3   r   NrÈ   NF)%r  Ú
__module__Ú__qualname__Ú__doc__Ústaticmethodr5   r>   rB   rU   rY   rj   ÚDEFAULT_CHARSET_IDÚDEFAULT_MAX_ALLOWED_PACKETru   ry   r}   r€   r�   r•   r˜   rœ   r¢   r¯   r¶   rÄ   rÇ   rÊ   rÛ   rã   rï   rñ   rò   rô   rù   r  r  r  r3   r3   r3   r4   r,   V   s¨      ø"Aó,zý 3  ÿ, ÿ ü>  û%!*7
       ÷r,   )<r  Ú
__future__r   rØ   rO   Úcollectionsr   Údecimalr   r   Útypingr   r   r   r	   r
   r   r   r   r   rD   r   Ú	constantsr   r   r   r   r   Ú
conversionr   Úerrorsr   r   r   r   r   Zpluginsr   r   Zplugins.caching_sha2_passwordr   r  r   r    r!   r"   r#   r$   r%   Únetworkr&   rŠ   r:   r2   Z	OK_STATUSr@   Z
ERR_STATUSr  r  r,   r3   r3   r3   r4   Ú<module>   s2   ,$
