U
    ec՜                     @   s6  d Z ddlZddlZddlZddlmZ zddlZdZW n e	k
rP   dZY nX zddl
ZdZW n e	k
rz   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mZmZm Z m!Z! ddl"m#Z# dZ$e%dZ&G dd dZ'G dd dZ(G dd dZ)G dd dZ*dS )z3Implementation of the X protocol for MySQL servers.    N)BytesIOTF   )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)CRUD_PREPARE_MAPPINGPROTOBUF_REPEATED_TYPESSERVER_MESSAGESMessagemysqlxpb_enum)Columni  Zmysqlxc                   @   s(   e Zd ZdZdd Zdd Z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

    c                 C   sR   || _ |dkr$t | _t | _n*|dkrBt | _t | _nd | _d | _d S )Nzstd_streamZdeflate_stream)	
_algorithmzstdZZstdCompressor_compressobjZZstdDecompressor_decompressobjzlibcompressobjdecompressobjself	algorithm r"   3/tmp/pip-unpacked-wheel-ix8dg7li/mysqlx/protocol.py__init__Z   s    

zCompressor.__init__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.
        r   lz4_message)
r   r   compresslz4frameZLZ4FrameCompressorbeginflushr   Z_SYNC_FLUSH)r    dataZ
compressor
compressedr"   r"   r#   r&   f   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.
        r   r%   )	r   r   
decompressr'   r(   ZLZ4FrameDecompressorr*   r   r+   )r    r,   Zdecompressordecompressedr"   r"   r#   r.   }   s    	

zCompressor.decompressN)__name__
__module____qualname____doc__r$   r&   r.   r"   r"   r"   r#   r   O   s   
r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )MessageReaderzImplements a Message Reader.

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

    .. versionadded:: 8.0.21
    c                 C   s   || _ d | _d | _g | _d S N)_stream_compressor_msg
_msg_queuer    Zsocket_streamr"   r"   r#   r$      s    zMessageReader.__init__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)r9   popstructunpackr6   readr   r   
ValueError_read_messager   Zfrom_server_messager   r7   r.   append)r    
frame_sizeZ
frame_typeZframe_payloadZ	frame_msgrA   streamZbytes_processedZpayload_sizemsg_typerB   r"   r"   r#   rI      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)r8   rI   r    msgr"   r"   r#   read_message   s
    
zMessageReader.read_messagec                 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)r8   r   rN   r"   r"   r#   push_message   s    	
zMessageReader.push_messagec                 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   r7   r   r"   r"   r#   set_compression   s    
zMessageReader.set_compressionN)	r0   r1   r2   r3   r$   rI   rP   rQ   rS   r"   r"   r"   r#   r4      s   /r4   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	MessageWriterzImplements a Message Writer.

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

    .. versionadded:: 8.0.21

    c                 C   s   || _ d | _d S r5   )r6   r7   r:   r"   r"   r#   r$     s    zMessageWriter.__init__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.
        r;   r   r?   zMysqlx.Connection.CompressionZclient_messagesr<   rA   rB   Nz&Mysqlx.ClientMessages.Type.COMPRESSION)Z	byte_sizer7   _COMPRESSION_THRESHOLDr   Zserialize_to_stringrE   packr&   joinr   Zserialize_partial_to_stringr   lenr6   sendall)r    rM   rO   Zmsg_sizeZmsg_strheaderr-   Zmsg_first_fieldsZmsg_payloadoutputZmsg_comp_idr"   r"   r#   write_message  s.    

	zMessageWriter.write_messagec                 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.
        NrR   r   r"   r"   r#   rS   *  s    zMessageWriter.set_compressionN)r0   r1   r2   r3   r$   r]   rS   r"   r"   r"   r#   rT      s   	%rT   c                   @   s$  e Zd ZdZdd Zedd Zedd Zdd	 Z	dDddZ
dd Zdd Zdd Zdd Zdd ZdEddZdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd.d/ ZdFd0d1Zed2d3 Zd4d5 Zd6d7 Zd8d9 Z d:d; Z!d<d= Z"d>d? Z#d@dA Z$dGdBdCZ%dS )H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
    c                 C   s   || _ || _d | _g | _d S r5   )_reader_writer_compression_algorithm	_warnings)r    readerwriterr"   r"   r#   r$   >  s    zProtocol.__init__c                 C   s   | j S )zstr: The compresion algorithm.)ra   )r    r"   r"   r#   compression_algorithmD  s    zProtocol.compression_algorithmc                 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)rO   stmtr"   r"   r#   _apply_filterI  s    zProtocol._apply_filterc                 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   )rn   scalarr      #Mysqlx.Datatypes.Object.ObjectFieldkeyrl   Mysqlx.Datatypes.ObjectZfldrn   objzMysqlx.Datatypes.Arrayrl      )rn   arrayN)
isinstancestrr   boolr	   intr   r   tuplerY   _create_anyget_messagedictlistitemsrJ   )r    argrl   rp   Zarg_key	arg_valueobj_fldrx   Zarray_valuesr   obj_fldsrt   msg_objmsg_anyrO   r"   r"   r#   r   Z  s    	

  
zProtocol._create_anyTc           
         s   fdd |  }| }|dkr8 fdd|D S t|}|dg }|t|kr^td| D ]2\}}||krtd| || }	 |||	< qf|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.
        c                    s    rt |  S |  S r5   )r   r   r   rk   )	is_scalarr    r"   r#   build_value  s    z/Protocol._get_binding_args.<locals>.build_valueNc                    s   g | ]} |qS r"   r"   .0rl   )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: )get_bindingsZget_binding_maprY   r   r   )
r    ri   r   bindingsZbinding_mapcountargsnamerl   posr"   )r   r   r    r#   _get_binding_args  s&    
zProtocol._get_binding_argsc                 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  nlt|d ttr|d d n|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.
        rn   r   zMysqlx.Notice.WarningrB   z:Protocol.process_frame Received Warning Notice code %s: %srq   z$Mysqlx.Notice.SessionVariableChangedry   z!Mysqlx.Notice.SessionStateChangedparamzBMysqlx.Notice.SessionStateChanged.Parameter.GENERATED_DOCUMENT_IDSc                 S   s    g | ]}t t |d d qS )Zv_octetsrl   )r   decoder   r"   r"   r#   r     s
    z+Protocol._process_frame.<locals>.<listcomp>rl   r   z9Mysqlx.Notice.SessionStateChanged.Parameter.ROWS_AFFECTEDZv_unsigned_intz?Mysqlx.Notice.SessionStateChanged.Parameter.GENERATED_INSERT_IDN)r   Zfrom_messagerb   rJ   rO   _LOGGERwarningcodeZappend_warninglevelr   Zset_generated_idsr{   r   r   Zset_rows_affectedr   Zset_generated_insert_id)r    rO   resultZwarn_msgZsess_state_msgZsess_state_valuer"   r"   r#   _process_frame  sV      zProtocol._process_framec              
   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.ErrorrO   r   Mysqlx.Notice.FramezMysqlx.Sql.StmtExecuteOkzMysqlx.Resultset.FetchDoneTz(Mysqlx.Resultset.FetchDoneMoreResultsetsMysqlx.Resultset.Row)r_   rP   RuntimeErrorreprZget_warningsrn   r   r   AttributeErrorKeyErrorZ
set_closedZset_has_more_resultsZset_has_data)r    r   rO   errwarningsr"   r"   r#   rI     s0    &





zProtocol._read_messagec                 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)ra   r_   rS   r`   r   r"   r"   r#   rS   %  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   rO   r   )r   r`   r]   r   r_   rP   rn   r   rN   r"   r"   r#   get_capabilites3  s    


zProtocol.get_capabilitesc              
   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   rr   rs   ru   rv   ro   rq   rw   rl   capabilitiesz!Mysqlx.Connection.CapabilitiesSetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_SETi  )r   r   r{   r   r   rJ   r   rh   r`   r]   r   read_okr   errno)r    kwargsr   rt   rl   Z
capabilityr   r   itemr   r   r   rO   r   r"   r"   r#   set_capabilitiesG  sB    	

zProtocol.set_capabilitiesNc                 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_nameN	auth_datainitial_responsez2Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_STARTr   r`   r]   r   )r    methodr   r   rO   r"   r"   r#   send_auth_startw  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_   rP   rn   r   rN   r"   r"   r#   read_auth_continue  s    



zProtocol.read_auth_continuec                 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   rO   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_   rP   rn   r   rO   rN   r"   r"   r#   read_auth_ok  s
    


zProtocol.read_auth_okc              
   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)rn   position	row_countr   offsetZ
limit_expr#Mysqlx.Prepare.Prepare.OneOfMessagern   zMysqlx.Prepare.Preparestmt_idri   z*Mysqlx.ClientMessages.Type.PREPARE_PREPAREN)	has_limitrn   
build_findbuild_updatebuild_deleterH   rY   r   r   r   r   r   r`   r]   r   r   r   )r    rM   rO   ri   _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   rn   zMysqlx.Prepare.Executer   Fr   r   z*Mysqlx.ClientMessages.Type.PREPARE_EXECUTEN)r   r   r   r   r   rh   r   r   get_limit_row_countr   get_limit_offsetr`   r]   )	r    rM   rO   ri   r   r   r   Zmsg_executer   r"   r"   r#   send_prepare_execute  s&    
zProtocol.send_prepare_executec                 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_deallocate  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   rn   r   r   rh   send_msg)r    rM   rO   ri   Z	msg_limitr   r   r"   r"   r#   send_msg_without_ps"  s    
zProtocol.send_msg_without_psc                 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    rM   rO   r"   r"   r#   r   9  s    
zProtocol.send_msgc                 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_exprrj   Zis_lock_exclusiveZis_lock_sharedZlock_contentionrl   r    ri   r   r   rO   r"   r"   r#   r   E  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sourceNrl   z&Mysqlx.ClientMessages.Type.CRUD_UPDATE)r   r   r   r   r   r   rj   Zget_update_opsr   Zupdate_typer   rl   r
   rh   r   )r    ri   r   r   rO   r   Z	update_opr   r"   r"   r#   r   m  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   rj   r   r"   r"   r#   r     s"      zProtocol.build_deletec                 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)	namespaceri   Zcompact_metadatarr   rs   ru   rv   ro   rq   rw   r   r   )r   r   r   rJ   r   )r    r   ri   fieldsrO   r   rt   rl   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_fieldrh   r   Z
get_valuesr{   r   r
   r   )	ri   r   r   rO   r   exprrl   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)rI   r   r    r   rO   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   )rI   rn   r_   rQ   r   r"   r"   r#   read_row  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 typern   catalogr   tableZoriginal_tabler   original_namelength   Z	collationr   Zfractional_digitsflags   content_type)rI   rn   r_   rQ   r   r   getrJ   )r    r   columnsrO   colr"   r"   r#   get_column_metadata&  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: rO   r   )r   z	Mysqlx.OkzUnexpected message encounteredNr   rN   r"   r"   r#   r   J  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   rN   r"   r"   r#   send_connection_closeV  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   rN   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_opend  s     zProtocol.send_expect_openc                 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.ResetNTF	keep_openz%Mysqlx.ClientMessages.Type.SESS_RESET)r   r   r   r   r`   r]   r   )r    r   rO   r"   r"   r#   
send_resetr  s$    
 zProtocol.send_reset)T)NN)N)N)&r0   r1   r2   r3   r$   propertyre   staticmethodrj   r   r   r   rI   rS   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^   4  sH   	

J
*6!0
8#('
%
2$r^   )+r3   loggingrE   r   ior   Z	lz4.framer'   ZHAVE_LZ4ImportErrorZ	zstandardr   Z	HAVE_ZSTDerrorsr   r   r   r   r   r   r	   r
   r   r   r   Zhelpersr   r   Zprotobufr   r   r   r   r   r   r   rV   	getLoggerr   r   r4   rT   r^   r"   r"   r"   r#   <module>   s2   

 
Dd=