U
    4Je                     @   s   U d Z ddlZddl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 ddl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mZ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&m'Z' dZ(e)e*d< G dd dZ+dS )z,Implements the MySQL Client/Server protocol.    N)DecimalDecimalException)AnyDictListOptionalSequenceTupleUnion   )utils)get_auth_plugin)PARAMETER_COUNT_AVAILABLE
ClientFlag	FieldFlag	FieldType	ServerCmd)DatabaseErrorInterfaceErrorProgrammingErrorget_exception)
ConnAttrsTypeDescriptionTypeEofPacketTypeHandShakeTypeOkPacketType%ParseValueFromBinaryResultPacketTypes
SocketTypeStatsPacketType
StrOrBytes!SupportedMysqlBinaryProtocolTypes
   PROTOCOL_VERSIONc                   @   s*  e Zd ZdZeeee edddZ	eeee
 ee ee eeee eed	ddZd_ee ee
 ee ee eeeeee ee ee edddZeeedddZed`eeeedddZedaeee edddZedbeeedddZdceee
 ee ee eeeee ee ee edddZeeed d!d"Zeeeeef d d#d$Zeeed d%d&Zeeee d d'd(Zeddeeed*d+d,Zeed d-d.Zedeeee d0d1d2Z!dfe"eed3f eee#eee d3f  ee f d4d5d6Z$eeeeeef d7d8d9Z%eeeeee&f d7d:d;Z'edgeeeee(f d=d>d?Z)eeeeeee*e+j,e+j+f  f d@dAdBZ-eeeee+j.f d dCdDZ/dhe#e eeee0d3f dEdFdGZ1die"e#e eeee#ee0d3f  ee f dHdIdJZ2eee3eef d dKdLZ4eeeeeef dMdNdOZ5ee*e+j,e+j+f eeef dMdPdQZ6ee*e+j.e+j7f eeef dMdRdSZ8eeeeedTdUdVZ9djee:e; e:e< eee3eee f  eee#eee<f   eedX	dYdZZ=eeeeef d d[d\Z>eeed d]d^Z?dS )kMySQLProtocolzRImplements MySQL client/server protocol

    Create and parses MySQL packets.
    )client_flagsdatabasereturnc                 C   s    | t j@ r|r|dd S dS )z.Prepare database string for handshake responseutf8    )r   ZCONNECT_WITH_DBencode)r$   r%    r*   </tmp/pip-unpacked-wheel-7_167w8m/mysql/connector/protocol.py_connect_with_dbG   s    zMySQLProtocol._connect_with_db)	r$   usernamepasswordr%   auth_plugin_classauth_plugin	auth_datassl_enabledr&   c              
   C   s   |sdS z$t |||||||d}| }	W n6 ttfk
rb }
 ztd|
 |
W 5 d}
~
X Y nX | tj@ rt|	}td||	 }n|	d }|S )z#Prepare the authentication responser(   )r-   r.   r%   r2   zFailed authentication: N<B)	r   auth_response	TypeErrorr   r   SECURE_CONNECTIONlenstructpack)r$   r-   r.   r%   r/   r0   r1   r2   authZplugin_auth_responseerrZresplenr4   r*   r*   r+   _auth_responseN   s$    "
zMySQLProtocol._auth_responseN-   r      @F)	handshaker-   r.   r%   charsetr$   max_allowed_packetr2   r0   
conn_attrsr/   r&   c                 C   s*  |dkri }z|d }|	p |d }	W n8 t tfk
r\ } ztd| ddW 5 d}~X Y nX |sfd}z|d}W n tk
r   |}Y nX d}t|}td	| | d
||||}|| ||||||	||7 }|| 	||7 }|t
j@ r||	dd 7 }|t
j@ r&|
dk	r&|| |
7 }|S )z"Make a MySQL Authentication packetNr1   r0   &Handshake misses authentication info ()    r'   Zxxxxxxxxxxxxxxxxxxxxxxz<IIHsxr(   )r5   KeyErrorr   r)   AttributeErrorr7   r8   r9   r<   r,   r   PLUGIN_AUTHCONNECT_ARGSmake_conn_attrs)selfr?   r-   r.   r%   r@   r$   rA   r2   r0   rB   r/   r1   r;   username_bytesZfillerusername_lenpacketr*   r*   r+   	make_auths   sT    

zMySQLProtocol.make_auth)rB   r&   c                    s    D ]} | dkrd |< qt  fdd D t   t   }td|} D ]P}|tdt|7 }||d7 }|tdt | 7 }| | d7 }q\|S )z Encode the connection attributesN c                 3   s"   | ]}t |t  |  V  qd S )N)r7   ).0xrB   r*   r+   	<genexpr>   s     z0MySQLProtocol.make_conn_attrs.<locals>.<genexpr>r3   r'   )sumr7   keysvaluesr8   r9   r)   )rB   	attr_nameZconn_attrs_lenZconn_attrs_packetr*   rT   r+   rK      s     


zMySQLProtocol.make_conn_attrs)r@   r$   rA   r&   c                 C   s"   t |t | t |  d S )z Make a SSL authentication packets                         r   	int4store	int2store)r@   r$   rA   r*   r*   r+   make_auth_ssl   s    zMySQLProtocol.make_auth_ssl)commandargumentr&   c                 C   s   t | }|dk	r||7 }|S )z(Make a MySQL packet containing a commandN)r   	int1store)r^   r_   datar*   r*   r+   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   r[   )rc   rd   r*   r*   r+   make_stmt_fetch   s    zMySQLProtocol.make_stmt_fetch)r?   r-   r.   r%   r@   r$   r2   r0   rB   r/   r&   c                 C   s"  z|d }|p|d }W n8 t tfk
rP } ztd| ddW 5 d}~X Y nX |sZd}z|d}W n tk
r   |}Y nX t|}td| d	tj	|}|| 
|||||
|||7 }|| ||7 }|td
|7 }|tj@ r||dd 7 }|tj@ r|	dk	r|| |	7 }|S )z0Make a MySQL packet with the Change User commandr1   r0   rC   rD   NrE   r'   r3   rF   <Hr(   )r5   rG   r   r)   rH   r7   r8   r9   r   ZCHANGE_USERr<   r,   r   rI   rJ   rK   )rL   r?   r-   r.   r%   r@   r$   r2   r0   rB   r/   r1   r;   rM   rN   rO   r*   r*   r+   make_change_user   sL    



zMySQLProtocol.make_change_user)rO   r&   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|rt
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      protocolz$Protocol mismatch; server version = z, client version = Nr(   endZserver_version_originalz<I8sx2sBH2sBxxxxxxxxxx   Zserver_threadidr@   Zserver_statusrE         z5.5.8r0   utf-8Zmysql_native_passwordr1   capabilities)r8   unpackr"   r   r   read_stringdecodeZintreadr   r6   minrI   
startswith)	rO   resZ
auth_data1Zcapabilities1Zcapabilities2Zauth_data_lengthrr   Z
auth_data2sizer*   r*   r+   parse_handshake  sP    
 zMySQLProtocol.parse_handshakec                 C   s@   t | d\} }|dkr tdt j| dd\} }| |dfS )z$Parse a MySQL AuthNextFactor packet.r      z.Failed parsing AuthNextFactor packet (invalid)r(   rk   rq   )r   read_intr   rt   ru   )rO   statusr0   r*   r*   r+   parse_auth_next_factorR  s
    z$MySQLProtocol.parse_auth_next_factorc              
   C   s   | d dkst di }ztd| dd d |d< t| dd \} |d< t| \} |d	< td
| dd \|d< |d< | dd } | rt| \} |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-packet   r   z#Failed parsing OK packet (invalid).rh   ri   Zfield_countNZaffected_rowsZ	insert_idz<HHstatus_flagwarning_countZinfo_msgrq   zFailed parsing OK packet.)r   r8   rs   r   read_lc_intread_lc_stringru   
ValueError)rO   Z	ok_packetr;   r*   r*   r+   parse_ok[  s$    zMySQLProtocol.parse_okc              
   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 setr   Nr   zFailed parsing column count)r   r   r8   errorr   r   )rO   countr;   r*   r*   r+   parse_column_countr  s
    z MySQLProtocol.parse_column_countrq   )rO   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-packetr   Nz	<xHIBHBxxz!Failed parsing column information)	r   r   r8   rs   r   r   ru   r   ZNOT_NULL)rO   r   _namer@   Zcolumn_typeflagsr*   r*   r+   parse_column{  s6    

zMySQLProtocol.parse_columnc              
   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-packetr   r   zFailed parsing EOF packet.z<xxxBBHHNr      	   r{   r      r   )r   r8   rs   r   r   r7   )rL   rO   err_msgrx   unpackedr;   r*   r*   r+   	parse_eof  s    
zMySQLProtocol.parse_eofT)rO   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 informationrE   r   Ns     c                 S   s   g | ]}|  qS r*   )strip)rR   vr*   r*   r+   
<listcomp>  s     z2MySQLProtocol.parse_statistics.<locals>.<listcomp>   :r{   rq   z (:rD   )	splitr   r   ru   intrG   r   r   repr)	rO   r   errmsgrx   pairsZlblpairvalr;   r*   r*   r+   parse_statistics  s*    

:zMySQLProtocol.parse_statistics.)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td|
}n>|	d dkr|	d dk r| |	}d}nd}t|	dd }|dkr|dk	r|| n|dkr|dkrt|	|d7 }q||fS )	zRead 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   r   rE   r      r   )	recvrw   appendr   Zread_lc_string_list	bytearrayjoinr   r   )rL   r   r   r   r   rd   eofZrowdatairO   Zdatasr*   r*   r+   read_text_result  s6    




zMySQLProtocol.read_text_result)rO   fieldr&   c                 C   s   |d t jkrd}d}nL|d t jkr0d}d}n4|d t jt jfkrNd}d}n|d t jkrdd}d}|d	 tj@ rz| }| |d
 t	
|| d| d fS )z%Parse an integer from a binary packetr   <b<hr{   <ir   <qro   r   Nr   )r   TINYSHORTINT24LONGLONGLONGr   ZUNSIGNEDupperr8   rs   )rO   r   format_lengthr*   r*   r+   _parse_binary_integer  s    z#MySQLProtocol._parse_binary_integerc                 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   ro   <dr   z<fNr   )r   DOUBLEr8   rs   )rO   r   r   r   r*   r*   r+   _parse_binary_float  s    z!MySQLProtocol._parse_binary_floatr'   )rO   r@   r&   c                 C   s    t | \} }| t||fS )z(Parse a New Decimal from a binary packet)r   r   r   ru   )rO   r@   valuer*   r*   r+   _parse_binary_new_decimal  s    z'MySQLProtocol._parse_binary_new_decimal)rO   
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}qtj|||d}np|dkrd}|d	krt 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   Nr   rf   r   r   )yearmonthdayr      <Iro   ri      )r   r   r   hourminutesecondmicrosecond)r8   rs   r   DATETIME	TIMESTAMPdatetimedate)rO   r   r   r   r   r   r   mcsr*   r*   r+   _parse_binary_timestamp#  s.    
z%MySQLProtocol._parse_binary_timestampc                 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   Nro   r   ri   rp   r   r   )dayssecondsmicrosecondsminuteshours)r   	timedeltar8   rs   )rO   r   ra   r   r   tmpr*   r*   r+   _parse_binary_timeC  s$    z MySQLProtocol._parse_binary_time)fieldsrO   r@   r&   c           
   	   C   s  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| |\}}|| qFt|\}}z||| W qF tk
r   || Y qFX qFt|S )	z(Parse values from a binary result packetr   r{   ro   c                 S   s   g | ]}t |qS r*   )r   )rR   r   r*   r*   r+   r   b  s     z6MySQLProtocol._parse_binary_values.<locals>.<listcomp>r   Nr   )r7   	enumerater   r   r   r   r   r   r   r   r   r   FLOATr   DECIMALZ
NEWDECIMALr   r   DATEr   r   TIMEr   r   r   ru   UnicodeDecodeErrortuple)
rL   r   rO   r@   Znull_bitmap_lengthnull_bitmaprX   r   posr   r*   r*   r+   _parse_binary_valuesZ  sP    $
z"MySQLProtocol._parse_binary_values)r   columnsr   r@   r&   c           
      C   s   g }d}d}d}|dk	rq||kr$q|  }	|	d dkrH| |	}d}n&|	d dkrnd}| ||	dd |}|dkr|dk	r|| n|dkr|dkrt|	|d7 }q||fS )zwRead MySQL binary protocol result

        Reads all or given number of binary resultset rows from the socket.
        Nr   r   r   ri   r   )r   r   r   r   r   )
rL   r   r   r   r@   rd   r   rX   r   rO   r*   r*   r+   read_binary_result  s*    

z MySQLProtocol.read_binary_resultc              
   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 packetr   r   zFailed parsing Binary OK packetri   Nrc   r{   Znum_columnsZ
num_paramsr   r   )r   r   r|   r   )rO   Zok_pktr;   r*   r*   r+   parse_binary_prepare_ok  s    z%MySQLProtocol.parse_binary_prepare_ok)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}qd	}t j}nJd
}| dkrpd}t j}n2| dkrd}t j}n| dkrd}t j}n
t j}d}t|| ||fS )z0Prepare an integer for the MySQL binary protocolNr   ir   i r   i   r   r         r3   i  rf   l    r   z<Q)r   r   r   r   r   r8   r9   )r   r   r   r   r*   r*   r+   prepare_binary_integer  s6    z$MySQLProtocol.prepare_binary_integerc                 C   s   t | tjrtj}nt | tjr(tj}ntdt| j	t
| j t
| j }t | tjr|t
| j t
| j t
| j }| jdkr|t| j7 }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   )
isinstancer   r   r   r   r   r   r   r\   r   r`   r   r   r   r   r   r   r[   r7   )r   r   packedr*   r*   r+   prepare_binary_timestamp  s0    






z&MySQLProtocol.prepare_binary_timestampc           	      C   s  t | tjtjfstdtj}d}d}d}t | tjr| jdk rFd}t| j	d\}}t|d\}}|t
t| jt
| t
| t
| 7 }| j}n8|t
dt
| j t
| j t
| j 7 }| j}|r|t
|7 }t
|| }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   NrE   r   i  <   )r   r   r   timer   r   r   r   divmodr   r   r[   absr`   r   r   r   r   r   r7   )	r   r   negativer   r   r   	remainderZminsZsecsr*   r*   r+   prepare_binary_time  sH    



z!MySQLProtocol.prepare_binary_time)	statementparamra   r&   c                 C   s   t | t | | }|S )zMPrepare long data for prepared statements

        Returns a string.
        rZ   )r   r   ra   rO   r*   r*   r+   prepare_stmt_send_long_dataB  s    z)MySQLProtocol.prepare_stmt_send_long_datar*   )	rc   ra   
parametersr   long_data_usedr@   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 }|rt|}|D ]\}}|| qjdgt |d d  }
|s|r*|t |krt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}nt|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}nt|tr,|td
| tj}nt|tjtjfrZ| |\}}|| nvt|tjtjfr| |\}}|| nH|rt||}|tt ||  tj}ntd|j j! d|t|t|  |r|d |kr|||  d |}|tt ||  qt"|t| t"|	 }|dk	r`|t | }n|}|r
|dk	r|t|7 }|d#dd |
D td 7 }d}|D ]H}||7 }|dk	r|d |kr||||  7 }n|d7 }|d7 }q|D ]}||7 }q|S )z6Make a MySQL packet with the Statement Execute commandr   r   r   ro   rE   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)r8   r9   )rR   bitr*   r*   r+   r     s     z3MySQLProtocol.make_stmt_execute.<locals>.<listcomp>r(   )$r7   r   listr   r   r   r   r`   r   ZNULLZBLOBSTRINGr   r   r   strr)   Zlc_intbytesr   r   floatr8   r9   r   r   r   r   r   r   r   r   	__class____name__r[   r   )rL   rc   ra   r   r   r   r@   r   r   Ziteration_countr   rX   typesr   Zdata_lenZquery_attr_namesr   Zattr_valr   r   _flagsr   r   rO   Zparameter_countr   Za_typeZa_valuer*   r*   r+   make_stmt_executeM  s    









zMySQLProtocol.make_stmt_executec                 C   sX   | d dkst dtj| dd dd\} }| rJ| d d	krJ| dd } |d
| fS )z&Parse a MySQL AuthSwitchRequest-packetr   r   z'Failed parsing AuthSwitchRequest packetri   Nr(   rk   rp   r   r'   )r   r   rt   ru   )rO   Zplugin_namer*   r*   r+   parse_auth_switch_request  s    z'MySQLProtocol.parse_auth_switch_requestc                 C   s    | d dkst d| dd S )z!Parse a MySQL AuthMoreData-packetr   r   z"Failed parsing AuthMoreData packetri   N)r   )rO   r*   r*   r+   parse_auth_more_data  s    z"MySQLProtocol.parse_auth_more_data)
NNNr=   r   r>   FNNN)r=   r   r>   )N)r   )	NNNr=   r   FNNN)rq   )T)r   )r'   )rq   )r   rq   )r*   r*   r   Nr'   NF)@r  
__module____qualname____doc__staticmethodr   r   r   r   r,   r   boolr<   r   r   rP   rK   r   r]   rb   re   rg   rz   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   r   r    r   r  r  r  r*   r*   r*   r+   r#   A   sj  '          A                =3   
 ) 
 
  
 
7  %!
(
2          r#   ),r
  r   r8   decimalr   r   typingr   r   r   r   r   r	   r
   rQ   r   Zauthenticationr   	constantsr   r   r   r   r   errorsr   r   r   r   r  r   r   r   r   r   r   r   r   r   r    r"   r   __annotations__r#   r*   r*   r*   r+   <module>   s   $0