U
    4Je                     @   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
mZ zddlZdZW n ek
rh   dZY nX zddlZdZW n ek
r   dZY nX 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 dd
l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,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z= dZ>G dd dZ?G dd dZ@G dd dZAG dd dZBdS )z3Implementation of the X protocol for MySQL servers.    N)BytesIO)AnyDictListOptionalTupleUnionTF   )InterfaceErrorNotSupportedErrorOperationalErrorProgrammingError)
ExprParserbuild_bool_scalar
build_exprbuild_int_scalarbuild_scalarbuild_unsigned_int_scalar)encode_to_bytesget_item_or_attr)logger)CRUD_PREPARE_MAPPINGSERVER_MESSAGESMessagemysqlxpb_enum)Column)
AddStatementDeleteStatementFilterableStatementFindStatementInsertStatementModifyStatementReadStatementRemoveStatementSqlStatementUpdateStatement)
ColumnTypeMessageTypeProtobufMessageCextTypeProtobufMessageTypeResultBaseType
SocketTypeStatementType
StrOrBytesi  c                   @   s@   e Zd ZdZeddddZeedddZeedd	d
Z	dS )
CompressorzImplements compression/decompression using `zstd_stream`, `lz4_message`
    and `deflate_stream` algorithms.

    Args:
        algorithm (str): Compression algorithm.

    .. versionadded:: 8.0.21

    N	algorithmreturnc                 C   sP   || _ d | _d | _|dkr0t | _t | _n|dkrLt | _t | _d S )Nzstd_streamZdeflate_stream)	
_algorithm_compressobj_decompressobjzstdZZstdCompressorZZstdDecompressorzlibcompressobjdecompressobjselfr0    r<   3/tmp/pip-unpacked-wheel-7_167w8m/mysqlx/protocol.py__init__j   s    

zCompressor.__init__)datar1   c              	   C   s~   | j dkr| j|S | j dkr\tj (}| }|||7 }|| 7 }W 5 Q R X |S | j|}|| jtj	7 }|S )zCompresses data and returns it.

        Args:
            data (str, bytes or buffer object): Data to be compressed.

        Returns:
            bytes: Compressed data.
        r2   lz4_message)
r3   r4   compresslz4frameZLZ4FrameCompressorbeginflushr7   Z_SYNC_FLUSH)r;   r?   Z
compressor
compressedr<   r<   r=   rA   v   s    	

zCompressor.compressc              	   C   sf   | j dkr| j|S | j dkrDtj }||}W 5 Q R X |S | j|}|| jtj7 }|S )zDecompresses a frame of data and returns it as a string of bytes.

        Args:
            data (str, bytes or buffer object): Data to be compressed.

        Returns:
            bytes: Decompresssed data.
        r2   r@   )	r3   r5   
decompressrB   rC   ZLZ4FrameDecompressorrE   r7   rF   )r;   r?   Zdecompressordecompressedr<   r<   r=   rH      s    	

zCompressor.decompress)
__name__
__module____qualname____doc__strr>   r-   bytesrA   rH   r<   r<   r<   r=   r.   _   s   
r.   c                   @   s\   e Zd ZdZeddddZedddZedd	d
ZeddddZ	e
ddddZdS )MessageReaderzImplements a Message Reader.

    Args:
        socket_stream (mysqlx.connection.SocketStream): `SocketStream` object.

    .. versionadded:: 8.0.21
    Nsocket_streamr1   c                 C   s   || _ d | _d | _g | _d S N)_stream_compressor_msg
_msg_queuer;   rR   r<   r<   r=   r>      s    zMessageReader.__init__r1   c                 C   s  | j r| j dS td| jd\}}|dkr:td| j|d }|tkr`td| |dkrx|d	krx| 	 S t
||}|d
kr|d }t| j|d }d}||k rtd|d\}}	||d }
| j t
|	|
 ||d 7 }q| j r| j dS dS |S )a  Reads X Protocol messages from the stream and returns a
        :class:`mysqlx.protobuf.Message` object.

        Raises:
            :class:`mysqlx.ProgrammingError`: If e connected server does not
                                              have the MySQL X protocol plugin
                                              enabled.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        r   <LB   
   z[The connected server does not have the MySQL X protocol plugin enabled or protocol mismatchr	   zUnknown message type:           uncompressed_sizepayload   N)rW   popstructunpackrT   readr   r   
ValueError_read_messager   Zfrom_server_messager   rU   rH   append)r;   
frame_sizeZ
frame_typeZframe_payloadZ	frame_msgr`   streamZbytes_processedZpayload_sizemsg_typera   r<   r<   r=   rh      s0    
zMessageReader._read_messagec                 C   s"   | j dk	r| j }d| _ |S |  S )zgRead message.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        N)rV   rh   r;   msgr<   r<   r=   read_message   s
    
zMessageReader.read_message)rn   r1   c                 C   s   | j dk	rtd|| _ dS )zPush message.

        Args:
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.

        Raises:
            :class:`mysqlx.OperationalError`: If message push slot is full.
        NzMessage push slot is full)rV   r   rm   r<   r<   r=   push_message   s    	
zMessageReader.push_messager/   c                 C   s   |rt |nd| _dS )zCreates a :class:`mysqlx.protocol.Compressor` object based on the
        compression algorithm.

        Args:
            algorithm (str): Compression algorithm.

        .. versionadded:: 8.0.21

        Nr.   rU   r:   r<   r<   r=   set_compression   s    
zMessageReader.set_compression)rJ   rK   rL   rM   r+   r>   r'   rh   ro   rp   rN   rr   r<   r<   r<   r=   rP      s   /rP   c                   @   sB   e Zd ZdZeddddZeeddddZe	dd	d
dZ
dS )MessageWriterzImplements a Message Writer.

    Args:
        socket_stream (mysqlx.connection.SocketStream): `SocketStream` object.

    .. versionadded:: 8.0.21

    NrQ   c                 C   s   || _ d | _d S rS   )rT   rU   rX   r<   r<   r=   r>     s    zMessageWriter.__init__rl   rn   r1   c                 C   s  | |}| jr|tkrt| }td|d |}| jd||g}t	d}||d< |d |d< t	d}||d< dt|
 d	d
 t|
 g}	td}
tdt|	d |
}| jd||	g n4t| }td|d |}| jd||g d	S )zWrite message.

        Args:
            msg_type (int): The message type.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.
        rZ   r	   r^   zMysqlx.Connection.CompressionZclient_messagesr[   r`   ra   Nz&Mysqlx.ClientMessages.Type.COMPRESSION)Z	byte_sizerU   _COMPRESSION_THRESHOLDr   Zserialize_to_stringrd   packrA   joinr   Zserialize_partial_to_stringr   lenrT   sendall)r;   rl   rn   Zmsg_sizeZmsg_strheaderrG   Zmsg_first_fieldsZmsg_payloadoutputZmsg_comp_idr<   r<   r=   write_message  s.    

	zMessageWriter.write_messager/   c                 C   s   |rt |nd| _dS )zCreates a :class:`mysqlx.protocol.Compressor` object based on the
        compression algorithm.

        Args:
            algorithm (str): Compression algorithm.
        Nrq   r:   r<   r<   r=   rr   :  s    zMessageWriter.set_compression)rJ   rK   rL   rM   r+   r>   intr'   r}   rN   rr   r<   r<   r<   r=   rs     s   	%rs   c                	   @   s  e Zd ZdZeeddddZeee	 dddZ
eeedd	d
dZeee dddZdUeeef eeed eeeef  f dddZeeddddZeee dddZe	ddddZedddZedddd ZdVe	ee	 ee	 dd!d"d#Zedd$d%Z e	dd&d'd(Z!ddd)d*Z"e	eee#e$e%e&e'e(f dd+d,d-Z)e	eedd+d.d/Z*e+dd0d1d2Z,e	eeeef dd+d3d4Z-e	edd5d6d7Z.ee#e&f e/e	ef d8d9d:Z0ee%e(f e/e	ef d8d;d<Z1ee$e'f e/e	ef d8d=d>Z2dWe	ee	e3f ee4e	ef  e/e	ef d?d@dAZ5eee6e7f e/e	ef d8dBdCZ8edddDdEZ9eee ddFdGZ:eee; ddHdIZ<dddJdKZ=dddLdMZ>dddNdOZ?dddPdQZ@dXee edRdSdTZAdS )YProtocolzImplements the MySQL X Protocol.

    Args:
        read (mysqlx.protocol.MessageReader): A Message Reader object.
        writer (mysqlx.protocol.MessageWriter): A Message Writer object.

    .. versionchanged:: 8.0.21
    N)readerwriterr1   c                 C   s   || _ || _d | _g | _d S rS   )_reader_writer_compression_algorithm	_warnings)r;   r   r   r<   r<   r=   r>   N  s    zProtocol.__init__rY   c                 C   s   | j S )zstr: The compresion algorithm.)r   )r;   r<   r<   r=   compression_algorithmT  s    zProtocol.compression_algorithm)rn   stmtr1   c                 C   sX   |j r| | d< |jr*| d |  |jrB| d |  |jrT| | d< dS )zApply filter.

        Args:
            msg (mysqlx.protobuf.Message): The MySQL X Protobuf Message.
            stmt (Statement): A `Statement` based type object.
        ZcriteriaordergroupingZgrouping_criteriaN)	Z	has_whereZget_where_exprZhas_sortextendZget_sort_exprZhas_group_byZget_groupingZ
has_havingZ
get_having)rn   r   r<   r<   r=   _apply_filterY  s    zProtocol._apply_filter)argr1   c                 C   s  t |tr2td|d}tdd|d}tdd|dS t |trNtddt|dS t |tr|d	k rrtddt|dS tddt|dS t |trt	|d
kr|\}}td|| 
|d}td| gd}tdd
|dS t |tst |ttfrt |d	 trg }|D ]h}	g }
|	 D ],\}}td|| 
|d}|
|  qtd|
d}tdd
|d}||  q
td}||d< tdd|dS t |trg }
|D ],\}}td|| 
|d}|
|  qtd|
d}tdd
|d}|S dS )zCreate any.

        Args:
            arg (object): Arbitrary object.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        zMysqlx.Datatypes.Scalar.StringvaluezMysqlx.Datatypes.Scalar   )typeZv_stringMysqlx.Datatypes.Anyr	   )r   scalarr      #Mysqlx.Datatypes.Object.ObjectFieldkeyr   Mysqlx.Datatypes.ObjectZfldr   objzMysqlx.Datatypes.Arrayr      )r   arrayN)
isinstancerN   r   boolr   r~   r   r   tuplery   _create_anyget_messagedictlistitemsri   )r;   r   r   r   Zarg_key	arg_valueobj_fldr   Zarray_valuesr   obj_fldsr   msg_objmsg_anyrn   r<   r<   r=   r   j  s    	

  
zProtocol._create_anyT)r   	is_scalarr1   c           
         s   t tttf dfdd | }| }|dkrH fdd|D S t|}|dg }|t|krntd| D ]2\}}||krtd| || }	 |||	< qv|S )	a  Returns the binding any/scalar.

        Args:
            stmt (Statement): A `Statement` based type object.
            is_scalar (bool): `True` to return scalar values.

        Raises:
            :class:`mysqlx.ProgrammingError`: If unable to find placeholder for
                                              parameter.

        Returns:
            list: A list of ``Any`` or ``Scalar`` objects.
        )r   r1   c                    s    rt |  S |  S rS   )r   r   r   r   )r   r;   r<   r=   build_value  s    z/Protocol._get_binding_args.<locals>.build_valueNc                    s   g | ]} |qS r<   r<   .0r   )r   r<   r=   
<listcomp>  s     z.Protocol._get_binding_args.<locals>.<listcomp>z;The number of bind parameters and placeholders do not matchz*Unable to find placeholder for parameter: )	r   r   r)   r(   get_bindingsZget_binding_mapry   r   r   )
r;   r   r   ZbindingsZbinding_mapcountargsnamer   posr<   )r   r   r;   r=   _get_binding_args  s*    

zProtocol._get_binding_args)rn   resultr1   c                 C   s  |d dkrRt d|d }| j|j td|j|j ||j	|j|j n|d dkrpt d|d  n|d dkrt d	|d }|d
 t
dkr|dd |d D  nP|d  }|d
 t
dkr|t|d n"|d
 t
dkr|t|d dS )zProcess frame.

        Args:
            msg (mysqlx.protobuf.Message): A MySQL X Protobuf Message.
            result (Result): A `Result` based type object.
        r   r	   zMysqlx.Notice.Warningra   z:Protocol.process_frame Received Warning Notice code %s: %sr   z$Mysqlx.Notice.SessionVariableChangedr   z!Mysqlx.Notice.SessionStateChangedparamzBMysqlx.Notice.SessionStateChanged.Parameter.GENERATED_DOCUMENT_IDSc                 S   s    g | ]}t t |d d qS )Zv_octetsr   )r   decoder   r<   r<   r=   r     s
    z+Protocol._process_frame.<locals>.<listcomp>r   z9Mysqlx.Notice.SessionStateChanged.Parameter.ROWS_AFFECTEDZv_unsigned_intz?Mysqlx.Notice.SessionStateChanged.Parameter.GENERATED_INSERT_IDN)r   Zfrom_messager   ri   rn   r   warningcodeZappend_warninglevelr   Zset_generated_idsrc   Zset_rows_affectedr   Zset_generated_insert_id)r;   rn   r   Zwarn_msgZsess_state_msgZsess_state_valuer<   r<   r=   _process_frame  sJ     	zProtocol._process_frame)r   r1   c              
   C   s  z| j  }W nF tk
rT } z(t| }|rDt| d| |W 5 d}~X Y nX |jdkrrt|d |d |jdkrz| || W n tt	fk
r   Y q Y nX q |jdkrdS |jdkr|
d	 q |jd
kr|d	 q |jdkr|d	 qq qq |S )z`Read message.

        Args:
            result (Result): A `Result` based type object.
        z	 reason: NMysqlx.Errorrn   r   Mysqlx.Notice.FramezMysqlx.Sql.StmtExecuteOkzMysqlx.Resultset.FetchDoneTz(Mysqlx.Resultset.FetchDoneMoreResultsetsMysqlx.Resultset.Row)r   ro   RuntimeErrorreprZget_warningsr   r   r   AttributeErrorKeyErrorZ
set_closedZset_has_more_resultsZset_has_data)r;   r   rn   errwarningsr<   r<   r=   rh     s0    &





zProtocol._read_messager/   c                 C   s"   || _ | j| | j| dS )zSets the compression algorithm to be used by the compression
        object, for uplink and downlink.

        Args:
            algorithm (str): Algorithm to be used in compression/decompression.

        .. versionadded:: 8.0.21

        N)r   r   rr   r   r:   r<   r<   r=   rr   3  s    
zProtocol.set_compressionc                 C   sZ   t d}| jtd| | j }|jdkr:| j }q$|jdkrVt|d |d |S )zkGet capabilities.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        z!Mysqlx.Connection.CapabilitiesGetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_GETr   r   rn   r   )r   r   r}   r   r   ro   r   r   rm   r<   r<   r=   get_capabilitesA  s    


zProtocol.get_capabilites)kwargsr1   c              
   K   s"  |sdS t d}| D ]\}}t d}||d< t|tr|}g }|D ]*}t d|| || d}	||	  qFt d|d}
t d	d
|
d}| |d< n| ||d< |d | g qt d}||d< | j	t
d| z
|  W S  tk
r } z|jdkr W 5 d}~X Y nX dS )zSet capabilities.

        Args:
            **kwargs: Arbitrary keyword arguments.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        NzMysqlx.Connection.CapabilitieszMysqlx.Connection.Capabilityr   r   r   r   r   r   r   r   r   capabilitiesz!Mysqlx.Connection.CapabilitiesSetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_SETi  )r   r   r   r   r   ri   r   r   r   r}   r   read_okr
   errno)r;   r   r   r   r   Z
capabilityr   r   itemr   r   r   rn   r   r<   r<   r=   set_capabilitiesU  sB    	

zProtocol.set_capabilities)method	auth_datainitial_responser1   c                 C   sF   t d}||d< |dk	r ||d< |dk	r0||d< | jtd| dS )zSend authenticate start.

        Args:
            method (str): Message method.
            auth_data (Optional[str]): Authentication data.
            initial_response (Optional[str]): Initial response.
        z Mysqlx.Session.AuthenticateStartZ	mech_nameNr   r   z2Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_STARTr   r   r}   r   )r;   r   r   r   rn   r<   r<   r=   send_auth_start  s    zProtocol.send_auth_startc                 C   s:   | j  }|jdkr | j  }q
|jdkr2td|d S )zRead authenticate continue.

        Raises:
            :class:`InterfaceError`: If the message type is not
                                     `Mysqlx.Session.AuthenticateContinue`

        Returns:
            str: The authentication data.
        r   #Mysqlx.Session.AuthenticateContinuez>Unexpected message encountered during authentication handshaker   r   ro   r   r
   rm   r<   r<   r=   read_auth_continue  s    



zProtocol.read_auth_continue)r   r1   c                 C   s"   t d|d}| jtd| dS )zeSend authenticate continue.

        Args:
            auth_data (str): Authentication data.
        r   )r   z5Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_CONTINUENr   )r;   r   rn   r<   r<   r=   send_auth_continue  s
    zProtocol.send_auth_continuec                 C   s0   | j  }|jdkrq,|jdkr t|jq dS )z~Read authenticate OK.

        Raises:
            :class:`mysqlx.InterfaceError`: If message type is `Mysqlx.Error`.
        zMysqlx.Session.AuthenticateOkr   N)r   ro   r   r
   rn   rm   r<   r<   r=   read_auth_ok  s
    


zProtocol.read_auth_ok)rl   rn   r   r1   c              
   C   sR  |j r|jdkr|jdkr*| |\}}nB|jdkrD| |\}}n(|jdkr^| |\}}ntd| t| }td}t	d}t	d||d	|d
< |jdkrt	d||d d	|d< ||d< t
| \}}	t	d}
t||
d< ||
|	< t	d}|j|d< |
|d< | jtd| z|   W n* tk
rL } z
t|W 5 d}~X Y nX dS )a  
        Send prepare statement.

        Args:
            msg_type (str): Message ID string.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.
            stmt (Statement): A `Statement` based type object.

        Raises:
            :class:`mysqlx.NotSupportedError`: If prepared statements are not
                                               supported.

        .. versionadded:: 8.0.16
        Mysqlx.Crud.InsertMysqlx.Crud.FindMysqlx.Crud.UpdateMysqlx.Crud.DeletezInvalid message type: z!Mysqlx.Expr.Expr.Type.PLACEHOLDERzMysqlx.Crud.LimitExprzMysqlx.Expr.Expr)r   position	row_countr	   offsetZ
limit_expr#Mysqlx.Prepare.Prepare.OneOfMessager   zMysqlx.Prepare.Preparestmt_idr   z*Mysqlx.ClientMessages.Type.PREPARE_PREPAREN)	has_limitr   
build_findbuild_updatebuild_deleterg   ry   r   r   r   r   r   r   r}   r   r
   r   )r;   rl   rn   r   _r   placeholderZmsg_limit_expr
oneof_typeoneof_op	msg_oneofZmsg_preparer   r<   r<   r=   send_prepare_prepare  sL    


  

  

zProtocol.send_prepare_preparec           	      C   s   t | \}}td}t||d< |||< td}|j|d< | j|dd}|rZ|d | |jr|d | | 	 | |
 	 g | jtd| d	S )
a  
        Send execute statement.

        Args:
            msg_type (str): Message ID string.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.
            stmt (Statement): A `Statement` based type object.

        .. versionadded:: 8.0.16
        r   r   zMysqlx.Prepare.Executer   Fr   r   z*Mysqlx.ClientMessages.Type.PREPARE_EXECUTEN)r   r   r   r   r   r   r   r   get_limit_row_countr   get_limit_offsetr   r}   )	r;   rl   rn   r   r   r   r   Zmsg_executer   r<   r<   r=   send_prepare_execute  s&    
zProtocol.send_prepare_execute)r   r1   c                 C   s.   t d}||d< | jtd| |   dS )z
        Send prepare deallocate statement.

        Args:
            stmt_id (int): Statement ID.

        .. versionadded:: 8.0.16
        zMysqlx.Prepare.Deallocater   z-Mysqlx.ClientMessages.Type.PREPARE_DEALLOCATEN)r   r   r}   r   r   )r;   r   Zmsg_deallocr<   r<   r=   send_prepare_deallocate2  s    	z Protocol.send_prepare_deallocatec                 C   sp   |j r8td}| |d< |jdkr0| |d< ||d< |dk}| j||d}|r`|d | | || d	S )
a)  
        Send a message without prepared statements support.

        Args:
            msg_type (str): Message ID string.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.
            stmt (Statement): A `Statement` based type object.

        .. versionadded:: 8.0.16
        zMysqlx.Crud.Limitr   r   r   limit+Mysqlx.ClientMessages.Type.SQL_STMT_EXECUTEr   r   N)r   r   r   r   r   r   r   send_msg)r;   rl   rn   r   Z	msg_limitr   r   r<   r<   r=   send_msg_without_psC  s    
zProtocol.send_msg_without_psrt   c                 C   s   | j t|| dS )z
        Send a message.

        Args:
            msg_type (str): Message ID string.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        N)r   r}   r   )r;   rl   rn   r<   r<   r=   r   _  s    
zProtocol.send_msg)r   r1   c                 C   s   t | rdnd}td|jj|jjd}td||d}|jrJ| |d< | || |	 rlt d|d	< n|
 rt d
|d	< |jjdkr|jj|d< d|fS )a  Build find/read message.

        Args:
            stmt (Statement): A :class:`mysqlx.ReadStatement` or
                              :class:`mysqlx.FindStatement` object.

        Returns:
            (tuple): Tuple containing:

                * `str`: Message ID string.
                * :class:`mysqlx.protobuf.Message`: MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        Mysqlx.Crud.DataModel.DOCUMENTMysqlx.Crud.DataModel.TABLEMysqlx.Crud.Collectionr   schemar   
data_model
collection
projectionz'Mysqlx.Crud.Find.RowLock.EXCLUSIVE_LOCKZlockingz$Mysqlx.Crud.Find.RowLock.SHARED_LOCKr   Zlocking_optionsz$Mysqlx.ClientMessages.Type.CRUD_FIND)r   is_doc_basedr   targetr   r   Zhas_projectionZget_projection_exprr   Zis_lock_exclusiveZis_lock_sharedZlock_contentionr   r;   r   r   r   rn   r<   r<   r=   r   k  s*    zProtocol.build_findc                 C   s   t | rdnd}td|jj|jjd}td||d}| || |  D ]P\}}td}|j	|d< |j
|d	< |jd
k	rt|j|d< |d | g qPd|fS )a  Build update message.

        Args:
            stmt (Statement): A :class:`mysqlx.ModifyStatement` or
                              :class:`mysqlx.UpdateStatement` object.

        Returns:
            (tuple): Tuple containing:

                * `str`: Message ID string.
                * :class:`mysqlx.protobuf.Message`: MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        r   r   r   r   r   r   zMysqlx.Crud.UpdateOperation	operationsourceNr   z&Mysqlx.ClientMessages.Type.CRUD_UPDATE)r   r   r   r   r   r   r   Zget_update_opsr   Zupdate_typer   r   r   r   r   )r;   r   r   r   rn   r   Z	update_opr   r<   r<   r=   r     s0      


zProtocol.build_updatec                 C   sL   t | rdnd}td|jj|jjd}td||d}| || d|fS )a  Build delete message.

        Args:
            stmt (Statement): A :class:`mysqlx.DeleteStatement` or
                              :class:`mysqlx.RemoveStatement` object.

        Returns:
            (tuple): Tuple containing:

                * `str`: Message ID string.
                * :class:`mysqlx.protobuf.Message`: MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        r   r   r   r   r   r   z&Mysqlx.ClientMessages.Type.CRUD_DELETE)r   r   r   r   r   r   r   r   r<   r<   r=   r     s"      zProtocol.build_delete)	namespacer   fieldsr1   c                 C   s|   t d||dd}|rtg }| D ]*\}}t d|| |d}||  q t d|d}	t dd	|	d
}
|
 g|d< d|fS )a  Build execute statement.

        Args:
            namespace (str): The namespace.
            stmt (Statement): A `Statement` based type object.
            fields (Optional[dict]): The message fields.

        Returns:
            (tuple): Tuple containing:

                * `str`: Message ID string.
                * :class:`mysqlx.protobuf.Message`: MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        zMysqlx.Sql.StmtExecuteF)r   r   Zcompact_metadatar   r   r   r   r   r   r   r   r   )r   r   r   ri   r   )r;   r   r   r  rn   r   r   r   r   r   r   r<   r<   r=   build_execute_statement  s&    z Protocol.build_execute_statementc           	      C   s  t |  rdnd}td| jj| jjd}td||d}t| drv| jD ],}t||   	 }|d 
| g qH|  D ]f}td	}t|tr|D ]}|d
 
t| g qn|d
 
t| g |d 
| g q~t| dr|  |d< d|fS )a  Build insert statement.

        Args:
            stmt (Statement): A :class:`mysqlx.AddStatement` or
                              :class:`mysqlx.InsertStatement` object.

        Returns:
            (tuple): Tuple containing:

                * `str`: Message ID string.
                * :class:`mysqlx.protobuf.Message`: MySQL X Protobuf Message.

        .. versionadded:: 8.0.16
        r   r   r   r   r   r   _fieldsr   zMysqlx.Crud.Insert.TypedRowfieldrow	is_upsertZupsertz&Mysqlx.ClientMessages.Type.CRUD_INSERT)r   r   r   r   r   r   hasattrr  r   Zparse_table_insert_fieldr   r   Z
get_valuesr   r   r   r  )	r   r   r   rn   r  exprr   r  valr<   r<   r=   build_insert	  s@      

 

zProtocol.build_insertc                 C   s   |  |}|dk	rtddS )zClose the result.

        Args:
            result (Result): A `Result` based type object.

        Raises:
            :class:`mysqlx.OperationalError`: If message read is None.
        NzExpected to close the result)rh   r   r;   r   rn   r<   r<   r=   close_result>  s    	
zProtocol.close_resultc                 C   s4   |  |}|dkrdS |jdkr$|S | j| dS )z\Read row.

        Args:
            result (Result): A `Result` based type object.
        Nr   )rh   r   r   rp   r  r<   r<   r=   read_rowK  s    

zProtocol.read_rowc                 C   s   g }|  |}|dkrq|jdkr0| j| q|jdkrBtdt|d |d |d |d |d	 |d
 |d |dd|dd|dd|dd|d}|| q|S )zReturns column metadata.

        Args:
            result (Result): A `Result` based type object.

        Raises:
            :class:`mysqlx.InterfaceError`: If unexpected message.
        Nr   zMysqlx.Resultset.ColumnMetaDatazUnexpected msg typer   catalogr   tableZoriginal_tabler   original_namelength   Z	collationr   Zfractional_digitsflags   content_type)rh   r   r   rp   r
   r   getri   )r;   r   columnsrn   colr<   r<   r=   get_column_metadataY  s2    	






zProtocol.get_column_metadatac                 C   sD   | j  }|jdkr.td|d  |d d|jdkr@tddS )	zeRead OK.

        Raises:
            :class:`mysqlx.InterfaceError`: If unexpected message.
        r   zMysqlx.Error: rn   r   )r   z	Mysqlx.OkzUnexpected message encounteredNr   rm   r<   r<   r=   r   }  s
    


zProtocol.read_okc                 C   s   t d}| jtd| dS )zSend connection close.zMysqlx.Connection.Closez$Mysqlx.ClientMessages.Type.CON_CLOSENr   rm   r<   r<   r=   send_connection_close  s
     zProtocol.send_connection_closec                 C   s   t d}| jtd| dS )zSend close.zMysqlx.Session.Closez%Mysqlx.ClientMessages.Type.SESS_CLOSENr   rm   r<   r<   r=   
send_close  s
     zProtocol.send_closec                 C   sL   t d}td}||d< d|d< td}| g|d< | jt d| d	S )
zSend expectation.z3Mysqlx.Expect.Open.Condition.Key.EXPECT_FIELD_EXISTzMysqlx.Expect.Open.ConditionZcondition_keyz6.1Zcondition_valuezMysqlx.Expect.OpenZcondz&Mysqlx.ClientMessages.Type.EXPECT_OPENN)r   r   r   r   r}   )r;   Zcond_keyZmsg_ocZmsg_eor<   r<   r=   send_expect_open  s     zProtocol.send_expect_open)	keep_openr1   c                 C   st   t d}|dkrBz|   |   d}W n tk
r@   d}Y nX |rNd|d< | jtd| |   |rpdS dS )zSend reset session message.

        Returns:
            boolean: ``True`` if the server will keep the session open,
                     otherwise ``False``.
        zMysqlx.Session.ResetNTFr  z%Mysqlx.ClientMessages.Type.SESS_RESET)r   r  r   r
   r   r}   r   )r;   r  rn   r<   r<   r=   
send_reset  s$    
 zProtocol.send_reset)T)NN)N)N)BrJ   rK   rL   rM   rP   rs   r>   propertyr   rN   r   staticmethodr'   r   r   r   r   r   r$   r   r   r)   r(   r   r*   r   rh   rr   r   r   r   rO   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   D  s   	K 
 .0!3  E  %


+

*

% 

*

4$r   )CrM   rd   r7   ior   typingr   r   r   r   r   r   Z	lz4.framerB   ZHAVE_LZ4ImportErrorZ	zstandardr6   Z	HAVE_ZSTDerrorsr
   r   r   r   r  r   r   r   r   r   r   Zhelpersr   r   r   Zprotobufr   r   r   r   r   r   Z	statementr   r   r   r   r    r!   r"   r#   r$   r%   typesr&   r'   r(   r)   r*   r+   r,   r-   rv   r.   rP   rs   r   r<   r<   r<   r=   <module>   s6    

 0(Dd=