3
K^(m                 @   s   d Z ddlZddl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 ddlmZ ddlmZmZ dd	lmZ G d
d deZdS )z,Implements the MySQL Client/Server protocol
    N)Decimal   )	FieldFlag	ServerCmd	FieldType
ClientFlagMAX_MYSQL_TABLE_COLUMNS)errorsutils)get_auth_plugin)PY2struct_unpack)get_exceptionc               @   s  e Zd ZdZdd Zdd ZdAddZdBddZdCddZdDddZ	dd Z
dd Zdd ZdEddZdd ZdFdd ZdGd"d#Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- ZdHd.d/Zd0d1 Zd2d3 Zd4d5 Zd6d7 Zd8d9 Zf f ddd:fd;d<Zd=d> Zd?d@ ZdS )IMySQLProtocolzRImplements MySQL client/server protocol

    Create and parses MySQL packets.
    c             C   s    |t j@ r|r|jdd S dS )z.Prepare database string for handshake responseutf8    )r   ZCONNECT_WITH_DBencode)selfclient_flagsdatabase r   _/tmp/pip-unpacked-wheel-jty9dxb9/mysql_connector-2.2.9.data/purelib/mysql/connector/protocol.py_connect_with_db-   s    zMySQLProtocol._connect_with_dbc             C   s   |sdS y"t ||||||d}|j }	W n< ttjfk
rf }
 ztjdjt|
W Y dd}
~
X nX |tj	@ rt
|	}tjd||	 }n|	d }|S )z#Prepare the authentication responser   )usernamepasswordr   ssl_enabledzFailed authentication: {0}Nz<B)r   auth_response	TypeErrorr	   InterfaceErrorProgrammingErrorformatstrr   SECURE_CONNECTIONlenstructpack)r   r   r   r   r   auth_plugin	auth_datar   authZplugin_auth_responseexcZresplenr   r   r   r   _auth_response3   s     "
zMySQLProtocol._auth_responseN!   r      @Fc
             C   s   y|d }
|	p|d }	W n6 t tfk
rN } ztjdj|W Y dd}~X nX |sXd}y|jd}W n tk
r~   |}Y nX tjdjdd	 t	|d
||||}|| j
|||||	|
|7 }|| j||7 }|tj@ r||	jdd 7 }|S )z"Make a MySQL Authentication packetr'   r&   z*Handshake misses authentication info ({0})N    r   z<IIB{filler}{usrlen}sxx   )Zfillerusrlenr   )r   KeyErrorr	   r   r    r   AttributeErrorr$   r%   r#   r*   r   r   PLUGIN_AUTH)r   	handshaker   r   r   charsetr   max_allowed_packetr   r&   r'   r)   username_bytespacketr   r   r   	make_authJ   s0    


zMySQLProtocol.make_authc             C   s&   t j|t j| t j| dd  S )z Make a SSL authentication packetr   r/   )r
   	int4store	int1store)r   r5   r   r6   r   r   r   make_auth_sslo   s    zMySQLProtocol.make_auth_sslc             C   s   t j|}|dk	r||7 }|S )z(Make a MySQL packet containing a commandN)r
   r;   )r   commandargumentdatar   r   r   make_commandw   s    
zMySQLProtocol.make_commandc	             C   s   y|d }	|p|d }W n6 t tfk
rN }
 ztjdj|
W Y dd}
~
X nX |sXd}y|jd}W n tk
r~   |}Y nX tjdjt	|dt
j|}|| j||||||	|7 }|| j||7 }|tjd	|7 }|tj@ r||jdd
 7 }|S )z0Make a MySQL packet with the Change User commandr'   r&   z*Handshake misses authentication info ({0})Nr-   r   z<B{usrlen}sx)r0   z<Hr   )r   r1   r	   r   r    r   r2   r$   r%   r#   r   ZCHANGE_USERr*   r   r   r3   )r   r4   r   r   r   r5   r   r   r&   r'   r)   r7   r8   r   r   r   make_change_user~   s.    



zMySQLProtocol.make_change_userc       
   	   C   sf  i }t d|dd d |d< tj|dd dd\}|d< t d	|dd
 \|d< }}|d< |d< }}|d j |d< |d
d }tj|| }d}|tj@ r|rtd|d nd}	|d|	 }||	d }|d dkr|dd }|tj@ rFd|kr|d j	drd| }|d< ntj|dd\}|d< |d jd|d< nd|d< || |d< ||d< |S )zParse a MySQL Handshake-packetz<xxxxBr      protocolNr   )endZserver_version_originalz<I8sx2sBH2sBxxxxxxxxxx   Zserver_threadidr5   Zserver_statusr-         r   z5.5.8r&   zutf-8Zmysql_native_passwordr'   capabilitiesrI   )
r   r
   read_stringdecodeZintreadr   r"   minr3   
startswith)
r   r8   resZ
auth_data1Zcapabilities1Zcapabilities2Zauth_data_lengthrH   Z
auth_data2sizer   r   r   parse_handshake   s4    	,

zMySQLProtocol.parse_handshakec             C   s   |d dkst jdi }ytd|dd d |d< tj|dd \}|d< tj|\}|d	< td
|dd \|d< |d< |dd }|rtj|\}|d< |d jd|d< W n tk
r   t jdY nX |S )zParse a MySQL OK-packet   r   z#Failed parsing OK packet (invalid).z<xxxxBrB   Zfield_countNZaffected_rowsZ	insert_idz<HHstatus_flagwarning_countZinfo_msgzutf-8zFailed parsing OK packet.)r	   r   r   r
   read_lc_intread_lc_stringrK   
ValueError)r   r8   Z	ok_packetr   r   r   parse_ok   s    
zMySQLProtocol.parse_okc             C   sP   y&t j|dd d }|tkr$dS |S  tjtfk
rJ   tjdY nX dS )z=Parse a MySQL packet with the number of columns in result setrQ   Nr   zFailed parsing column count)r
   rT   r   r$   errorrV   r	   r   )r   r8   countr   r   r   parse_column_count   s    z MySQLProtocol.parse_column_countutf-8c             C   s   t j|dd \}}t j|\}}t j|\}}t j|\}}t j|\}}t j|\}}ytd|\}}}}}W n  tjk
r   tjdY nX |j||dddd| tj	@ |fS )zParse a MySQL column-packetrQ   Nz	<xHIBHBxxz!Failed parsing column information)
r
   rU   r   r$   rX   r	   r   rK   r   ZNOT_NULL)r   r8   r5   _name
field_typeflagsr   r   r   parse_column   s$    
zMySQLProtocol.parse_columnc             C   s   |d dkr| j |S d}i }ytd|}W n  tjk
rL   tj|Y nX |d dkodt|dksptj||d |d	< |d
 |d< |S )zParse a MySQL EOF-packetrQ   r   zFailed parsing EOF packet.z<xxxBBHHr      	      rS      rR   )rW   r   r$   rX   r	   r   r#   )r   r8   err_msgrN   unpackedr   r   r   	parse_eof  s    

zMySQLProtocol.parse_eofTc       	      C   s   d}i }|r |dd j d}n
|j d}x|D ]}ydd |j ddD \}}W n   tj|Y nX |jd	}yt|||< W q0   yt|jd	||< W n    tjd
j|||Y nX Y q0X q0W |S )zParse the statistics packetz)Failed getting COM_STATISTICS informationrQ   Ns     c             S   s   g | ]}|j  qS r   )strip).0vr   r   r   
<listcomp>%  s    z2MySQLProtocol.parse_statistics.<locals>.<listcomp>   :rc   zutf-8z{0} ({1}:{2}).)splitr	   r   rK   intr   r    )	r   r8   Zwith_headererrmsgrN   pairspairZlblvalr   r   r   parse_statistics  s(    


 zMySQLProtocol.parse_statisticsr   c             C   s^  g }d}d}d}|dk}x:|s(||kr*P |j  }	|	jdr|	dd g}
|j  }	x(|	jdrz|
j|	dd  |j  }	qTW |
j|	dd  tjtdj|
}nj|	d dkr|	d dk r| j|	}d}nB|r|	d dkr|	d d	kr| j|	}d}nd}tj|	dd }|dkr.|dk	r.|j| n|dkrJ|dkrJt	|	|d
7 }qW ||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   rB      s   rQ   r-   ra   rb   r   )rB   rt   rB   )
recvrM   appendr
   Zread_lc_string_list	bytearrayjoinrg   rW   r   )r   sockversionrY   rowseofZrowdataiZeof57r8   Zdatasr   r   r   read_text_result5  s>    


zMySQLProtocol.read_text_resultc             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|j }||d
 t	||d| d fS )z%Parse an integer from a binary packetr   bhrc   r}   rQ   qrG   rt   Nr   )
r   TINYSHORTINT24LONGLONGLONGr   ZUNSIGNEDupperr   )r   r8   fieldformat_lengthr   r   r   _parse_binary_integer_  s    z#MySQLProtocol._parse_binary_integerc             C   sB   |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   rG   drQ   fNr   )r   DOUBLEr   )r   r8   r   r   r   r   r   r   _parse_binary_floats  s    z!MySQLProtocol._parse_binary_floatc          	   C   s   |d }d}|dkr@t jtd|dd d |d |d d}nl|dkrd}|d	krnt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   NrQ   Hr   rd   )yearmonthdayrt      IrG   rB      )r   r   r   hourminutesecondmicrosecond)datetimedater   )r   r8   r   r   valuemcsr   r   r   _parse_binary_timestamp~  s(    z%MySQLProtocol._parse_binary_timestampc             C   s   |d }|d|d  }d}|dkr:t d|dd d }t d|dd d }|d dkrd|d
9 }tj||d ||d |d d	}||d d |fS )z'Parse a time value from a binary packetr   r   rG   r   NrB   rt   r   )dayssecondsmicrosecondsminuteshoursrI   )r   r   	timedelta)r   r8   r   r   r?   r   r   tmpr   r   r   _parse_binary_time  s    z MySQLProtocol._parse_binary_timec       	      C   st  t |d d d }dd |d| D }||d }g }x.t|D ] \}}|t|d d  d|d d > @ r|jd qFqF|d tjtjtjtjtj	fkr| j
||\}}|j| qF|d tjtjfkr| j||\}}|j| qF|d tjtjtjfkr$| j||\}}|j| qF|d tjkrP| j||\}}|j| qFtj|\}}|j| qFW t|S )	z(Parse values from a binary result packetrt   rc   rG   c             S   s   g | ]}t |qS r   )rn   )ri   r}   r   r   r   rk     s    z6MySQLProtocol._parse_binary_values.<locals>.<listcomp>r   Nr   )r#   	enumeratern   rv   r   r   r   r   r   r   r   r   FLOATr   DATETIMEDATEZ	TIMESTAMPr   TIMEr   r
   rU   tuple)	r   fieldsr8   Znull_bitmap_lengthnull_bitmapvaluesposr   r   r   r   r   _parse_binary_values  s4    $
z"MySQLProtocol._parse_binary_valuesc       	      C   s   g }d}d}d}x|dk	rP ||kr&P |j  }|d dkrJ| j|}d}n$|d dkrnd}| j||dd }|dkr|dk	r|j| n|dkr|dkrt||d7 }qW ||fS )zwRead MySQL binary protocol result

        Reads all or given number of binary resultset rows from the socket.
        Nr   rQ   ra   rB   r   )ru   rg   r   rv   r   )	r   ry   columnsrY   r{   r|   r   r}   r8   r   r   r   read_binary_result  s,    
z MySQLProtocol.read_binary_resultc             C   s   |d dkst jdi }yhtj|dd d\}|d< tj|d\}|d< tj|d\}|d	< |d
d }tj|d\}|d< W n tk
r   t jdY nX |S )z'Parse a MySQL Binary Protocol OK packetrQ   r   zFailed parsing Binary OK packetrB   Nstatement_idrc   Znum_columnsZ
num_paramsr   rS   )r	   r   r
   Zread_intrV   )r   r8   Zok_pktr   r   r   parse_binary_prepare_ok  s    
z%MySQLProtocol.parse_binary_prepare_okc             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j||||fS )z0Prepare an integer for the MySQL binary protocolNr      r   i   r   l        r}   r      Bi  r   l    r   Qii i   )r   r   r   r   r   r$   r%   )r   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|j	tj
|j tj
|j }t |tjr|tj
|j tj
|j tj
|j }|jdkr|tj|j7 }tj
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   rV   r
   	int2storer   r;   r   r   r   r   r   r   r:   r#   )r   r   r^   packedr   r   r   _prepare_binary_timestamp  s    
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
jt|jt
j| t
j| t
j|	 7 }|j}n8|t
jdt
j|j t
j|j t
j|j 7 }|j}|r|t
j|7 }t
j|| }t
j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-   r   i  <   )r   r   r   timerV   r   r   r   divmodr   r
   r:   absr;   r   r   r   r   r   r#   )
r   r   r^   negativer   r   r   	remainderZminsZsecsr   r   r   _prepare_binary_time8  s2    
" z"MySQLProtocol._prepare_binary_timec             C   s   t j|t j| | }|S )zMPrepare long data for prepared statements

        Returns a string.
        )r
   r:   r   )r   Z	statementparamr?   r8   r   r   r   _prepare_stmt_send_long_datae  s    z*MySQLProtocol._prepare_stmt_send_long_datar   c             C   s6  d}dgt |d d  }g }	g }
d}|dkr2i }|o8|rt |t |krVtjdxlt|D ]^\}}|| }d}|dkr||d   d|d > O  < |
jtjtjtj|  qbn||kr|| d rtj	}ntj
}nt|tr| j|\}}}|	j| nt|trftr:|	jtjt ||  n"|j|}|	jtjt ||  tj}nBt|tr|	jtjt ||  tj	}ntrt|tr|j|}|	jtjt ||  tj}nt|tr|	jtjt t|j|t|j|  tj}nt|tr6|	jtjd| tj}nrt|tjtjfrd| j|\}}|	j| nDt|tjtjfr| j |\}}|	j| ntj!d	j"|j#j$d
|
jtj|tj|  qbW tj%|tj| tj%| dj&dd |D  tjd }x|
D ]}||7 }qW x|	D ]}||7 }q W |S )z6Make a MySQL packet with the Statement Execute commandr   r   rt   rG   r-   NzTFailed executing prepared statement: data values does not match number of parametersr   z:MySQL binary protocol can not handle '{classname}' objects)	classnamec             S   s   g | ]}t jd |qS )r   )r$   r%   )ri   bitr   r   r   rk     s    z3MySQLProtocol.make_stmt_execute.<locals>.<listcomp>)'r#   r	   r   r   rv   r
   r;   r   ZNULLZBLOBSTRINGr   rn   r   r!   r   Zlc_intr   ZVARCHARbytesunicoder   ZDECIMALfloatr$   r%   r   r   r   r   r   r   r   r   r    	__class____name__r:   rx   )r   r   r?   
parametersr_   Zlong_data_usedr5   Ziteration_countr   r   typesr   r   r\   r   r^   r8   Za_typeZa_valuer   r   r   make_stmt_executep  s    







0

zMySQLProtocol.make_stmt_executec             C   sZ   |d dkst jdtj|dd dd\}}|rL|d d	krL|dd }|jd
|fS )z&Parse a MySQL AuthSwitchRequest-packetrQ   ra   z'Failed parsing AuthSwitchRequest packetrB   Nr   )rD   r   r   r   rI   rI   )r	   r   r
   rJ   rK   )r   r8   Zplugin_namer   r   r   parse_auth_switch_request  s    z'MySQLProtocol.parse_auth_switch_requestc             C   s"   |d dkst jd|dd S )z!Parse a MySQL AuthMoreData-packetrQ   r   z"Failed parsing AuthMoreData packetrB   N)r	   r   )r   r8   r   r   r   parse_auth_more_data  s    z"MySQLProtocol.parse_auth_more_data)NNNr+   r   r,   FN)r+   r   r,   )N)NNNr+   r   FN)r[   )T)r   )r   )r   
__module____qualname____doc__r   r*   r9   r<   r@   rA   rP   rW   rZ   r`   rg   rs   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   '   sF      
" 

  
",



* 
!"-Yr   )r   r$   r   decimalr   	constantsr   r   r   r   r    r	   r
   Zauthenticationr   Zcatch23r   r   r   objectr   r   r   r   r   <module>   s   