3
(h0                 @   s<  d Z ddlZddlZddlmZ yddlZdZW n ek
rH   dZY nX yddl	Z
dZW n ek
rr   dZY nX ddl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 dd
lmZmZ ddlmZ ddl m!Z!m"Z"m#Z#m$Z$m%Z% dZ&G dd de'Z(G dd de'Z)G dd de'Z*G dd de'Z+dS )z4Implementation of the X protocol for MySQL servers.
    N)BytesIOTF   )STRING_TYPES	INT_TYPES)InterfaceErrorNotSupportedErrorOperationalErrorProgrammingError)
ExprParser
build_exprbuild_scalarbuild_bool_scalarbuild_int_scalarbuild_unsigned_int_scalar)encode_to_bytesget_item_or_attr)Column)CRUD_PREPARE_MAPPINGSERVER_MESSAGESPROTOBUF_REPEATED_TYPESMessagemysqlxpb_enumi  c               @   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j | _tj | _n*|dkrBtj | _tj | _nd | _d | _d S )Nzstd_streamZdeflate_stream)	
_algorithmzstdZZstdCompressor_compressobjZZstdDecompressor_decompressobjzlibcompressobjdecompressobj)self	algorithm r#   C/tmp/pip-install-q3hcpn_q/mysql-connector-python/mysqlx/protocol.py__init__I   s    

zCompressor.__init__c          
   C   s~   | j dkr| jj|S | j dkr\tjj (}|j }||j|7 }||j 7 }W dQ R X |S | jj|}|| 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_messageN)
r   r   compresslz4frameZLZ4FrameCompressorbeginflushr   Z_SYNC_FLUSH)r!   dataZ
compressor
compressedr#   r#   r$   r'   U   s    	

zCompressor.compressc          
   C   sf   | j dkr| jj|S | j dkrDtjj }|j|}W dQ R X |S | jj|}|| 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&   N)	r   r   
decompressr(   r)   ZLZ4FrameDecompressorr+   r   r,   )r!   r-   Zdecompressordecompressedr#   r#   r$   r/   l   s    	

zCompressor.decompressN)__name__
__module____qualname____doc__r%   r'   r/   r#   r#   r#   r$   r   ?   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!   socket_streamr#   r#   r$   r%      s    zMessageReader.__init__c             C   s  | j r| j jdS tjd| jjd\}}|dkr:td| jj|d }|tkr`tdj	||dkrx|d	krx| j
 S tj||}|d
kr|d }t| jj|d }d}xP||k rtjd|jd\}}	|j|d }
| j jtj|	|
 ||d 7 }qW | j r| j 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   z<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format_read_messager   Zfrom_server_messager   r7   r/   append)r!   
frame_sizeZ
frame_typeZframe_payloadZ	frame_msgr@   streamZbytes_processedZpayload_sizemsg_typerA   r#   r#   r$   rI      s.    

zMessageReader._read_messagec             C   s"   | j dk	r| j }d| _ |S | j 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   )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#   r$   set_compression   s    
zMessageReader.set_compressionN)	r1   r2   r3   r4   r%   rI   rO   rP   rQ   r#   r#   r#   r$   r5      s   .r5   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 )N)r6   r7   )r!   r:   r#   r#   r$   r%      s    zMessageWriter.__init__c             C   s  |j |}| jr|tkrt|j }tjd|d |}| jjdj||g}t	d}||d< |d |d< t	d}||d< djt|j
 d	d t|j
 g}	td}
tjdt|	d |
}| jjdj||	g n4t|j }tjd|d |}| jjdj||g d	S )zWrite message.

        Args:
            msg_type (int): The message type.
            msg (mysqlx.protobuf.Message): MySQL X Protobuf Message.
        z<LBr   r>   zMysqlx.Connection.CompressionZclient_messagesr;   r@   rA   N   z&Mysqlx.ClientMessages.Type.COMPRESSION)Z	byte_sizer7   _COMPRESSION_THRESHOLDr   Zserialize_to_stringrD   packr'   joinr   Zserialize_partial_to_stringr   lenr6   sendall)r!   rM   rN   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.
        N)r   r7   )r!   r"   r#   r#   r$   rQ     s    zMessageWriter.set_compressionN)r1   r2   r3   r4   r%   r\   rQ   r#   r#   r#   r$   rR      s   "rR   c               @   s  e Zd ZdZdd Zedd Z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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 | _d S )N)_reader_writer_compression_algorithm)r!   readerwriterr#   r#   r$   r%   &  s    zProtocol.__init__c             C   s   | j S )z'str: The compresion algorithm.
        )r`   )r!   r#   r#   r$   compression_algorithm+  s    zProtocol.compression_algorithmc             C   sX   |j r|j |d< |jr*|d j|j  |jrB|d j|j  |jrT|j |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)r!   rN   stmtr#   r#   r$   _apply_filter1  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|| j
|d}td|j gd}tdd
|dS t |tst |ttfrt |d	 trg }xt|D ]l}	g }
x8|	j D ],\}}td|| j
|d}|
j|j  qW td|
d}tdd
|d}|j|j  qW td}||d< tdd|dS t |trg }
x4|D ],\}}td|| j
|d}|
j|j  qW t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_stringzMysqlx.Datatypes.Anyr   )rk   scalarr   rS   z#Mysqlx.Datatypes.Object.ObjectField)keyri   zMysqlx.Datatypes.Object)fld)rk   objzMysqlx.Datatypes.Arrayri      )rk   arrayN)
isinstancer   r   boolr   r   r   r   tuplerX   _create_anyget_messagedictlistitemsrJ   )r!   argri   rl   Zarg_key	arg_valueobj_fldro   Zarray_valuesry   obj_fldsrm   msg_objmsg_anyrN   r#   r#   r$   ru   A  sZ    	



zProtocol._create_anyTc       
         s   fdd |j  }|j }|dkr8 fdd|D S t|}|dg }|t|kr^tdx>|j D ]2\}}||krtdj||| }	 |||	< qhW |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 | j S j| j S )N)r   rv   ru   )ri   )	is_scalarr!   r#   r$   <lambda>  s    z,Protocol._get_binding_args.<locals>.<lambda>Nc                s   g | ]} |qS r#   r#   ).0ri   )build_valuer#   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: {0})get_bindingsZget_binding_maprX   r	   ry   rH   )
r!   rg   r   ZbindingsZbinding_mapcountargsnameri   posr#   )r   r   r!   r$   _get_binding_args{  s     
zProtocol._get_binding_argsc             C   s  |d dkr2t jd|d }|j|j|j|j n|d dkrPt jd|d  n|d dkrt jd|d }|d	 td
kr|jdd |d D  nht|d t	t
r|d d n|d }|d	 tdkr|jt|d n |d	 tdkr|jt|d dS )zProcess frame.

        Args:
            msg (mysqlx.protobuf.Message): A MySQL X Protobuf Message.
            result (Result): A `Result` based type object.
        rk   r   zMysqlx.Notice.WarningrA   rS   z$Mysqlx.Notice.SessionVariableChangedrp   z!Mysqlx.Notice.SessionStateChangedparamzBMysqlx.Notice.SessionStateChanged.Parameter.GENERATED_DOCUMENT_IDSc             S   s    g | ]}t t |d dj qS )Zv_octetsri   )r   decode)r   ri   r#   r#   r$   r     s   z+Protocol._process_frame.<locals>.<listcomp>ri   r   z9Mysqlx.Notice.SessionStateChanged.Parameter.ROWS_AFFECTEDZv_unsigned_intz?Mysqlx.Notice.SessionStateChanged.Parameter.GENERATED_INSERT_IDN)r   Zfrom_messageZappend_warninglevelcoderN   r   Zset_generated_idsrr   rt   r   Zset_rows_affectedr   Zset_generated_insert_id)r!   rN   resultZwarn_msgZsess_state_msgZsess_state_valuer#   r#   r$   _process_frame  s4    
zProtocol._process_framec          	   C   s   x| j j }|jdkr*t|d |d q|jdkrVy| j|| W q   wY qX q|jdkrddS |jdkrz|jd q|jd	kr|jd q|jd
kr|jd P qP qW |S )z`Read message.

        Args:
            result (Result): A `Result` based type object.
        zMysqlx.ErrorrN   r   zMysqlx.Notice.FramezMysqlx.Sql.StmtExecuteOkNzMysqlx.Resultset.FetchDoneTz(Mysqlx.Resultset.FetchDoneMoreResultsetszMysqlx.Resultset.Row)r^   rO   rk   r   r   Z
set_closedZset_has_more_resultsZset_has_data)r!   r   rN   r#   r#   r$   rI     s(    








zProtocol._read_messagec             C   s"   || _ | jj| | 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^   rQ   r_   )r!   r"   r#   r#   r$   rQ     s    
zProtocol.set_compressionc             C   s^   t d}| jjtd| | jj }x|jdkr<| jj }q&W |jdkrZt|d |d |S )zkGet capabilities.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        z!Mysqlx.Connection.CapabilitiesGetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_GETzMysqlx.Notice.FramezMysqlx.ErrorrN   r   )r   r_   r\   r   r^   rO   rk   r   )r!   rN   r#   r#   r$   get_capabilites  s    

zProtocol.get_capabilitesc             K   s(  |sdS t d}x|j D ]\}}t d}||d< t|tr|}g }x2|D ]*}t d|| j|| d}	|j|	j  qJW t d|d}
t d	d
|
d}|j |d< n| j||d< |d j|j g qW t d}||d< | jj	t
d| y| j S  tk
r" } z|jdkr W Y dd}~X 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   z#Mysqlx.Datatypes.Object.ObjectField)rm   ri   zMysqlx.Datatypes.Object)rn   zMysqlx.Datatypes.AnyrS   )rk   ro   ri   capabilitiesz!Mysqlx.Connection.CapabilitiesSetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_SETi  )r   ry   rr   rw   ru   rJ   rv   rf   r_   r\   r   read_okr   errno)r!   kwargsr   rm   ri   Z
capabilityry   r}   itemr|   r~   r   rN   errr#   r#   r$   set_capabilities  s<    	

zProtocol.set_capabilitiesNc             C   sF   t d}||d< |dk	r ||d< |dk	r0||d< | j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   rN   r#   r#   r$   send_auth_start1  s    zProtocol.send_auth_startc             C   s>   | j j }x|jdkr"| j j }qW |jdkr6td|d S )zRead authenticate continue.

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

        Returns:
            str: The authentication data.
        zMysqlx.Notice.Framez#Mysqlx.Session.AuthenticateContinuez>Unexpected message encountered during authentication handshaker   )r^   rO   rk   r   )r!   rN   r#   r#   r$   read_auth_continueB  s    


zProtocol.read_auth_continuec             C   s"   t d|d}| jjtd| dS )zeSend authenticate continue.

        Args:
            auth_data (str): Authentication data.
        z#Mysqlx.Session.AuthenticateContinue)r   z5Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_CONTINUEN)r   r_   r\   r   )r!   r   rN   r#   r#   r$   send_auth_continueT  s    zProtocol.send_auth_continuec             C   s4   x.| j j }|jdkrP |jdkrt|jqW dS )z~Read authenticate OK.

        Raises:
            :class:`mysqlx.InterfaceError`: If message type is `Mysqlx.Error`.
        zMysqlx.Session.AuthenticateOkzMysqlx.ErrorN)r^   rO   rk   r   rN   )r!   rN   r#   r#   r$   read_auth_ok_  s    


zProtocol.read_auth_okc             C   sB  |j r|jdkr|jdkr*| j|\}}nB|jdkrD| j|\}}n(|jdkr^| j|\}}ntdj|t|j }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jt	d| y| j  W n tk
r<   t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
        zMysqlx.Crud.InsertzMysqlx.Crud.FindzMysqlx.Crud.UpdatezMysqlx.Crud.DeletezInvalid message type: {}z!Mysqlx.Expr.Expr.Type.PLACEHOLDERzMysqlx.Crud.LimitExprzMysqlx.Expr.Expr)rk   position	row_countr   offsetZ
limit_exprz#Mysqlx.Prepare.Prepare.OneOfMessagerk   zMysqlx.Prepare.Preparestmt_idrg   z*Mysqlx.ClientMessages.Type.PREPARE_PREPAREN)	has_limitrk   
build_findbuild_updatebuild_deleterG   rH   rX   r   r   r   r   r   r_   r\   r   r   r   )r!   rM   rN   rg   _r   placeholderZmsg_limit_expr
oneof_typeoneof_op	msg_oneofZmsg_preparer#   r#   r$   send_prepare_preparel  sB    




zProtocol.send_prepare_preparec       	      C   s   t | \}}td}t||d< |||< td}|j|d< | j|dd}|rZ|d j| |jr|d j| j|j j	 | j|j
 j	 g | j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
        z#Mysqlx.Prepare.Prepare.OneOfMessagerk   zMysqlx.Prepare.Executer   F)r   r   z*Mysqlx.ClientMessages.Type.PREPARE_EXECUTEN)r   r   r   r   r   rf   r   ru   get_limit_row_countrv   get_limit_offsetr_   r\   )	r!   rM   rN   rg   r   r   r   Zmsg_executer   r#   r#   r$   send_prepare_execute  s     
zProtocol.send_prepare_executec             C   s.   t d}||d< | jjtd| | j  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   sx   |j r8td}|j |d< |jdkr0|j |d< ||d< |dkrDdnd}| j||d	}|rh|d
 j| | j|| 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   zMysqlx.Crud.Findr   limitz+Mysqlx.ClientMessages.Type.SQL_STMT_EXECUTEFT)r   r   N)r   r   r   rk   r   r   rf   send_msg)r!   rM   rN   rg   Z	msg_limitr   r   r#   r#   r$   send_msg_without_ps  s    
zProtocol.send_msg_without_psc             C   s   | j 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   rN   r#   r#   r$   r     s    
zProtocol.send_msgc             C   s   t |j rdnd}td|jj|jjd}td||d}|jrJ|j |d< | j|| |j	 rlt d|d	< n|j
 rt d
|d	< |jdkr|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
        zMysqlx.Crud.DataModel.DOCUMENTzMysqlx.Crud.DataModel.TABLEzMysqlx.Crud.Collection)r   schemazMysqlx.Crud.Find)
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_exprrh   Zis_lock_exclusiveZis_lock_sharedZlock_contention)r!   rg   r   r   rN   r#   r#   r$   r     s$    

zProtocol.build_findc             C   s   t |j rdnd}td|jj|jjd}td||d}| j|| x`|j j D ]P\}}td}|j	|d< |j
|d	< |jd
k	rt|j|d< |d j|j g qRW d|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
        zMysqlx.Crud.DataModel.DOCUMENTzMysqlx.Crud.DataModel.TABLEzMysqlx.Crud.Collection)r   r   zMysqlx.Crud.Update)r   r   zMysqlx.Crud.UpdateOperation	operationsourceNri   z&Mysqlx.ClientMessages.Type.CRUD_UPDATE)r   r   r   r   r   r   rh   Zget_update_opsry   Zupdate_typer   ri   r   rf   rv   )r!   rg   r   r   rN   r   Z	update_opr   r#   r#   r$   r     s"    


zProtocol.build_updatec             C   sL   t |j rdnd}td|jj|jjd}td||d}| j|| 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
        zMysqlx.Crud.DataModel.DOCUMENTzMysqlx.Crud.DataModel.TABLEzMysqlx.Crud.Collection)r   r   zMysqlx.Crud.Delete)r   r   z&Mysqlx.ClientMessages.Type.CRUD_DELETE)r   r   r   r   r   r   rh   )r!   rg   r   r   rN   r#   r#   r$   r   A  s    
zProtocol.build_deletec             C   s   t d||dd}|rxg }x6|j D ]*\}}t d|| j|d}|j|j  q"W t d|d}	t dd	|	d
}
|
j 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)	namespacerg   Zcompact_metadataz#Mysqlx.Datatypes.Object.ObjectField)rm   ri   zMysqlx.Datatypes.Object)rn   zMysqlx.Datatypes.AnyrS   )rk   ro   r   z+Mysqlx.ClientMessages.Type.SQL_STMT_EXECUTE)r   ry   ru   rJ   rv   )r!   r   rg   fieldsrN   r}   rm   ri   r|   r~   r   r#   r#   r$   build_execute_statementZ  s    z Protocol.build_execute_statementc       
      C   s  t |j rdnd}td|jj|jjd}td||d}t|drzx6|jD ],}t||j  j	 }|d j
|j g qJW xv|j D ]j}td	}t|trx>|D ]}	|d
 j
t|	j g qW n|d
 j
t|j g |d j
|j g qW t|dr
|j |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
        zMysqlx.Crud.DataModel.DOCUMENTzMysqlx.Crud.DataModel.TABLEzMysqlx.Crud.Collection)r   r   zMysqlx.Crud.Insert)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_fieldrf   rv   Z
get_valuesrr   rx   r   r   )
r!   rg   r   r   rN   r   exprri   r   valr#   r#   r$   build_insertx  s,    


zProtocol.build_insertc             C   s   | j |}|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   rN   r#   r#   r$   close_result  s    	
zProtocol.close_resultc             C   s4   | j |}|dkrdS |jdkr$|S | jj| dS )z\Read row.

        Args:
            result (Result): A `Result` based type object.
        NzMysqlx.Resultset.Row)rI   rk   r^   rP   )r!   r   rN   r#   r#   r$   read_row  s    

zProtocol.read_rowc             C   s   g }x| j |}|dkrP |jdkr2| jj| P |jdkrDtdt|d |d |d |d |d	 |d
 |d |jdd|jdd|jdd|jdd|jd}|j| qW |S )zReturns column metadata.

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

        Raises:
            :class:`mysqlx.InterfaceError`: If unexpected message.
        NzMysqlx.Resultset.RowzMysqlx.Resultset.ColumnMetaDatazUnexpected msg typerk   catalogr   tableZoriginal_tabler   original_namelength   Z	collationr   Zfractional_digitsflags   content_type)rI   rk   r^   rP   r   r   getrJ   )r!   r   columnsrN   colr#   r#   r$   get_column_metadata  s(    	






zProtocol.get_column_metadatac             C   sD   | j j }|jdkr.tdj|d |d d|jdkr@tddS )	zeRead OK.

        Raises:
            :class:`mysqlx.InterfaceError`: If unexpected message.
        zMysqlx.ErrorzMysqlx.Error: {}rN   r   )r   z	Mysqlx.OkzUnexpected message encounteredN)r^   rO   rk   r   rH   )r!   rN   r#   r#   r$   r     s    


zProtocol.read_okc             C   s   t d}| jjtd| dS )zSend connection close.zMysqlx.Connection.Closez$Mysqlx.ClientMessages.Type.CON_CLOSEN)r   r_   r\   r   )r!   rN   r#   r#   r$   send_connection_close  s    zProtocol.send_connection_closec             C   s   t d}| jjtd| dS )zSend close.zMysqlx.Session.Closez%Mysqlx.ClientMessages.Type.SESS_CLOSEN)r   r_   r\   r   )r!   rN   r#   r#   r$   
send_close  s    zProtocol.send_closec             C   sL   t d}td}||d< d|d< td}|j g|d< | j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   rv   r_   r\   )r!   Zcond_keyZmsg_ocZmsg_eor#   r#   r$   send_expect_open  s    zProtocol.send_expect_openc             C   st   t d}|dkrBy| j  | j  d}W n tk
r@   d}Y nX |rNd|d< | jjtd| | j  |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   rN   r#   r#   r$   
send_reset  s     

zProtocol.send_reset)T)NN)N)N)%r1   r2   r3   r4   r%   propertyrc   rh   ru   r   r   rI   rQ   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]     sB   :
$(-
7 '"
,r]   ),r4   rD   r   ior   Z	lz4.framer(   ZHAVE_LZ4ImportErrorZ	zstandardr   Z	HAVE_ZSTDcompatr   r   errorsr   r   r   r	   r   r
   r   r   r   r   r   helpersr   r   r   r   Zprotobufr   r   r   r   r   rU   objectr   r5   rR   r]   r#   r#   r#   r$   <module>   s0   

 Cb9