o
    h                     @   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y3   dZY nw zddlZdZW n eyG   dZY nw 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                   @   sF   e Zd ZdZdeddfddZdedefdd	Zdedef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

    	algorithmreturnNc                 C   sV   || _ d | _d | _|dkrt | _t | _d S |dkr)t | _t | _d S d S )Nzstd_streamdeflate_stream)	
_algorithm_compressobj_decompressobjzstdZstdCompressorZstdDecompressorzlibcompressobjdecompressobjselfr/    r>   J/var/www/html/scripts/venv/lib/python3.10/site-packages/mysqlx/protocol.py__init__j   s   

zCompressor.__init__datac                 C   s   | j dkr| j|S | j dkr9tj }| }|||7 }|| 7 }W d   |S 1 s2w   Y  |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.
        r1   lz4_messageN)
r3   r4   compresslz4frameLZ4FrameCompressorbeginflushr9   Z_SYNC_FLUSH)r=   rA   
compressor
compressedr>   r>   r?   rC   v   s   
	

zCompressor.compressc                 C   s|   | j dkr| j|S | j dkr-tj }||}W d   |S 1 s&w   Y  |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.
        r1   rB   N)	r3   r5   
decompressrD   rE   LZ4FrameDecompressorrH   r9   rI   )r=   rA   decompressordecompressedr>   r>   r?   rL      s   
	

zCompressor.decompress)
__name__
__module____qualname____doc__strr@   r-   bytesrC   rL   r>   r>   r>   r?   r.   _   s
    
r.   c                   @   sb   e Zd ZdZdeddfddZdefddZdefd	d
ZdeddfddZ	de
ddfddZdS )MessageReaderzImplements a Message Reader.

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

    .. versionadded:: 8.0.21
    socket_streamr0   Nc                 C   s   || _ d | _d | _g | _d S N)_stream_compressor_msg
_msg_queuer=   rW   r>   r>   r?   r@         
zMessageReader.__init__c                 C   s  | j r	| j dS td| jd\}}|dkrtd| j|d }|tvr0td| |dkr<|d	kr<| 	 S t
||}|d
kr|d }t| j|d }d}||k rtd|d\}}	||d }
| j t
|	|
 ||d 7 }||k sZ| 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)r\   popstructunpackrY   readr   r   
ValueError_read_messager   from_server_messager   rZ   rL   append)r=   
frame_size
frame_typeframe_payload	frame_msgre   streambytes_processedpayload_sizemsg_typerf   r>   r>   r?   rm      s2   zMessageReader._read_messagec                 C   s"   | j dur| j }d| _ |S |  S )zgRead message.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        N)r[   rm   r=   msgr>   r>   r?   read_message   s
   
zMessageReader.read_messagery   c                 C   s   | j du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)r[   r   rx   r>   r>   r?   push_message   s   
	
zMessageReader.push_messager/   c                 C      |r	t || _dS 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.   rZ   r<   r>   r>   r?   set_compression   s   
zMessageReader.set_compression)rP   rQ   rR   rS   r+   r@   r'   rm   rz   r{   rT   r~   r>   r>   r>   r?   rV      s    /rV   c                   @   sJ   e Zd ZdZdeddfddZdededdfd	d
Zde	ddfddZ
dS )MessageWriterzImplements a Message Writer.

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

    .. versionadded:: 8.0.21

    rW   r0   Nc                 C   s   || _ d | _d S rX   )rY   rZ   r]   r>   r>   r?   r@     s   
zMessageWriter.__init__rw   ry   c                 C   s  | |}| jrk|tkrkt| }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 d	S t| }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	   rc   zMysqlx.Connection.Compressionclient_messagesr`   re   rf   Nz&Mysqlx.ClientMessages.Type.COMPRESSION)	byte_sizerZ   _COMPRESSION_THRESHOLDr   serialize_to_stringri   packrC   joinr   serialize_partial_to_stringr   lenrY   sendall)r=   rw   ry   msg_sizemsg_strheaderrK   msg_first_fieldsmsg_payloadoutputmsg_comp_idr>   r>   r?   write_message  s.   


	zMessageWriter.write_messager/   c                 C   r|   )zCreates a :class:`mysqlx.protocol.Compressor` object based on the
        compression algorithm.

        Args:
            algorithm (str): Compression algorithm.
        Nr}   r<   r>   r>   r?   r~   :  s   zMessageWriter.set_compression)rP   rQ   rR   rS   r+   r@   intr'   r   rT   r~   r>   r>   r>   r?   r     s
    	%r   c                   @   s(  e Zd ZdZdededdfddZedee	 fdd	Z
ed
ededdfddZdedee fddZ	dVdeeef dedeed eeeef  f fddZd
ededdfddZdedee fddZde	ddfddZdefddZdeddfd d!Z		dWd"e	d#ee	 d$ee	 ddfd%d&Zdefd'd(Z d#e	ddfd)d*Z!dXd+d,Z"d-e	d
edee#e$e%e&e'e(f ddfd.d/Z)d-e	d
ededdfd0d1Z*d2e+ddfd3d4Z,d-e	d
edeeef ddfd5d6Z-d-e	d
eddfd7d8Z.dee#e&f de/e	ef fd9d:Z0dee%e(f de/e	ef fd;d<Z1dee$e'f de/e	ef fd=d>Z2	dYd?e	dee	e3f d@ee4e	ef  de/e	ef fdAdBZ5edee6e7f de/e	ef fdCdDZ8deddfdEdFZ9dedee fdGdHZ:dedee; fdIdJZ<dXdKdLZ=dXdMdNZ>dXdOdPZ?dXdQdRZ@dYdSee defdTdUZAdS )Z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
    readerwriterr0   Nc                 C   s   || _ || _d | _g | _d S rX   )_reader_writer_compression_algorithm	_warnings)r=   r   r   r>   r>   r?   r@   N  r^   zProtocol.__init__c                 C   s   | j S )zstr: The compresion algorithm.)r   )r=   r>   r>   r?   compression_algorithmT  s   zProtocol.compression_algorithmry   stmtc                 C   s\   |j r	| | d< |jr| d |  |jr!| d |  |jr,| | d< dS dS )zApply filter.

        Args:
            msg (mysqlx.protobuf.Message): The MySQL X Protobuf Message.
            stmt (Statement): A `Statement` based type object.
        criteriaordergroupinggrouping_criteriaN)		has_whereget_where_exprhas_sortextendget_sort_exprhas_group_byget_grouping
has_having
get_having)ry   r   r>   r>   r?   _apply_filterY  s   zProtocol._apply_filterargc                 C   s  t |trtd|d}tdd|d}tdd|dS t |tr'tddt|dS t |trB|d	k r9tddt|dS tddt|dS t |trkt	|d
krk|\}}td|| 
|d}td| gd}tdd
|dS t |ts~t |ttfrt |d	 trg }|D ]2}	g }
|	 D ]\}}td|| 
|d}|
|  qtd|
d}tdd
|d}||  qt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   )typev_stringMysqlx.Datatypes.Anyr	   )r   scalarr      #Mysqlx.Datatypes.Object.ObjectFieldkeyr   Mysqlx.Datatypes.Objectfldr   objzMysqlx.Datatypes.Arrayr      )r   arrayN)
isinstancerT   r   boolr   r   r   r   tupler   _create_anyget_messagedictlistitemsro   )r=   r   r   r   arg_key	arg_valueobj_fldr   array_valuesr   obj_fldsr   msg_objmsg_anyry   r>   r>   r?   r   j  s~   
	




zProtocol._create_anyT	is_scalarc           
         s   dt dtttf ffdd | }| }|du r% fdd|D S t|}|dg }|t|kr8td| D ]\}}||vrKtd	| || }	 |||	< q<|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   r0   c                    s    rt |  S |  S rX   )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_bindingsget_binding_mapr   r   r   )
r=   r   r   bindingsbinding_mapcountargsnamer   posr>   )r   r   r=   r?   _get_binding_args  s.   

zProtocol._get_binding_argsresultc                 C   s  |d dkr*t d|d }| j|j td|j|j ||j	|j|j dS |d dkr:t d|d  dS |d dkrt d	|d }|d
 t
dkr^|dd |d D  dS |d  }|d
 t
dkrv|t|d dS |d
 t
dkr|t|d dS dS 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.Warningrf   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 )v_octetsr   )r   decoder   r>   r>   r?   r     s    
z+Protocol._process_frame.<locals>.<listcomp>r   z9Mysqlx.Notice.SessionStateChanged.Parameter.ROWS_AFFECTEDv_unsigned_intz?Mysqlx.Notice.SessionStateChanged.Parameter.GENERATED_INSERT_IDN)r   from_messager   ro   ry   r   warningcodeappend_warninglevelr   set_generated_idsrh   set_rows_affectedr   set_generated_insert_id)r=   ry   r   warn_msgsess_state_msgsess_state_valuer>   r>   r?   _process_frame  sL   	zProtocol._process_framec              
   C   s  	 z| j  }W n$ ty, } zt| }|r"t| d| |W Y d}~nd}~ww |jdkr;t|d |d |jdkrTz| || W n8 tt	fyS   Y q w |jdkr[dS |jd	krf|
d n|jd
krq|d n|jdkr~|d 	 |S 	 |S q)z`Read message.

        Args:
            result (Result): A `Result` based type object.
        Tz	 reason: NMysqlx.Errorry   r   Mysqlx.Notice.FramezMysqlx.Sql.StmtExecuteOkzMysqlx.Resultset.FetchDonez(Mysqlx.Resultset.FetchDoneMoreResultsetsMysqlx.Resultset.Row)r   rz   RuntimeErrorreprget_warningsr   r   r   AttributeErrorKeyError
set_closedset_has_more_resultsset_has_data)r=   r   ry   errwarningsr>   r>   r?   rm     s>   






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   r~   r   r<   r>   r>   r?   r~   3  s   
zProtocol.set_compressionc                 C   sb   t d}| jtd| | j }|jdkr!| j }|jdks|jdkr/t|d |d |S )zkGet capabilities.

        Returns:
            mysqlx.protobuf.Message: MySQL X Protobuf Message.
        z!Mysqlx.Connection.CapabilitiesGetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_GETr   r   ry   r   )r   r   r   r   r   rz   r   r   rx   r>   r>   r?   get_capabilitesA  s   




zProtocol.get_capabiliteskwargsc              
   K   s  |sdS t d}| D ]R\}}t d}||d< t|trM|}g }|D ]}t d|| || d}	||	  q#t d|d}
t d	d
|
d}| |d< n| ||d< |d | g qt d}||d< | j	t
d| z|  W S  ty } z|jdkr W Y d}~dS d}~ww )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   ro   r   r   r   r   r   read_okr
   errno)r=   r   r   r   r   
capabilityr   r   itemr   r   r   ry   r   r>   r>   r?   set_capabilitiesU  sH   	



zProtocol.set_capabilitiesmethod	auth_datainitial_responsec                 C   sF   t d}||d< |dur||d< |dur||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.AuthenticateStart	mech_nameNr  r  z2Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_STARTr   r   r   r   )r=   r   r  r  ry   r>   r>   r?   send_auth_start  s   zProtocol.send_auth_startc                 C   sB   | j  }|jdkr| j  }|jdks
|jdkrt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   rz   r   r
   rx   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  ry   r>   r>   r?   send_auth_continue  s
   zProtocol.send_auth_continuec                 C   s0   	 | j  }|jdkrdS |jdkrt|jq)z~Read authenticate OK.

        Raises:
            :class:`mysqlx.InterfaceError`: If message type is `Mysqlx.Error`.
        TzMysqlx.Session.AuthenticateOkr   N)r   rz   r   r
   ry   rx   r>   r>   r?   read_auth_ok  s   



zProtocol.read_auth_okrw   c              
   C   sD  |j ra|jdkra|jdkr| |\}}n!|jdkr"| |\}}n|jdkr/| |\}}ntd| t| }td}t	d}t	d||d	|d
< |jdkr]t	d||d d	|d< ||d< t
| \}}	t	d}
t||
d< ||
|	< t	d}|j|d< |
|d< | jtd| z|   W dS  ty } zt|d}~ww )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	   offset
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_deleterl   r   r   r   r   r   r  r   r   r   r
   r   )r=   rw   ry   r   _r  placeholdermsg_limit_expr
oneof_typeoneof_op	msg_oneofmsg_preparer   r>   r>   r?   send_prepare_prepare  sH   







zProtocol.send_prepare_preparec           	      C   s   t | \}}td}t||d< |||< td}|j|d< | j|dd}|r-|d | |jrG|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=   rw   ry   r   r  r  r  msg_executer   r>   r>   r?   send_prepare_execute  s&   
zProtocol.send_prepare_executer  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  msg_deallocr>   r>   r?   send_prepare_deallocate2  s   	z Protocol.send_prepare_deallocatec                 C   sp   |j rtd}| |d< |jdkr| |d< ||d< |dk}| j||d}|r0|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=   rw   ry   r   	msg_limitr   r   r>   r>   r?   send_msg_without_psC  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=   rw   ry   r>   r>   r?   r*  _  s   
zProtocol.send_msgc                 C   s   t | rdnd}td|jj|jjd}td||d}|jr%| |d< | || |	 r6t d|d	< n
|
 r@t d
|d	< |jjdkrL|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_LOCKlockingz$Mysqlx.Crud.Find.RowLock.SHARED_LOCKr   locking_optionsz$Mysqlx.ClientMessages.Type.CRUD_FIND)r   is_doc_basedr   targetr   r1  has_projectionget_projection_exprr   is_lock_exclusiveis_lock_sharedlock_contentionr   r=   r   r3  r4  ry   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 ](\}}td}|j	|d< |j
|d	< |jd
urFt|j|d< |d | g q(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
        r-  r.  r/  r0  r  r2  zMysqlx.Crud.UpdateOperation	operationsourceNr   z&Mysqlx.ClientMessages.Type.CRUD_UPDATE)r   r8  r   r9  r   r1  r   get_update_opsr   update_typerA  r   r   r   r   )r=   r   r3  r4  ry   r  	update_opr@  r>   r>   r?   r    s,   


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/  r0  r  r2  z&Mysqlx.ClientMessages.Type.CRUD_DELETE)r   r8  r   r9  r   r1  r   r?  r>   r>   r?   r    s   zProtocol.build_delete	namespacefieldsc                 C   s|   t d||dd}|r:g }| 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)rE  r   compact_metadatar   r   r   r   r   r   r   r   r)  )r   r   r   ro   r   )r=   rE  r   rF  ry   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r;| jD ]}t||   	 }|d 
| g q$|  D ]3}td	}t|tr\|D ]}|d
 
t| g qLn|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/  r0  r  r2  _fieldsr5  zMysqlx.Crud.Insert.TypedRowfieldrow	is_upsertupsertz&Mysqlx.ClientMessages.Type.CRUD_INSERT)r   r8  r   r9  r   r1  hasattrrI  r   parse_table_insert_fieldr   r   
get_valuesr   r   r   rL  )	r   r3  r4  ry   rJ  exprr   rK  valr>   r>   r?   build_insert	  s@   




zProtocol.build_insertc                 C   s   |  |}|du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)rm   r   r=   r   ry   r>   r>   r?   close_result>  s   
	zProtocol.close_resultc                 C   s4   |  |}|du rdS |jdkr|S | j| dS )z\Read row.

        Args:
            result (Result): A `Result` based type object.
        Nr   )rm   r   r   r{   rT  r>   r>   r?   read_rowK  s   

zProtocol.read_rowc                 C   s   g }	 |  |}|du r	 |S |jdkr| j| 	 |S |jdkr&tdt|d |d |d |d	 |d
 |d |d |dd|dd|dd|dd|d}|| q)zReturns column metadata.

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

        Raises:
            :class:`mysqlx.InterfaceError`: If unexpected message.
        TNr   zMysqlx.Resultset.ColumnMetaDatazUnexpected msg typer   catalogr1  tableoriginal_tabler   original_namelength   	collationr   fractional_digitsflags   content_type)rm   r   r   r{   r
   r   getro   )r=   r   columnsry   colr>   r>   r?   get_column_metadataY  s8   	







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: ry   r   )r   z	Mysqlx.OkzUnexpected message encounteredNr  rx   r>   r>   r?   r   }  s   


zProtocol.read_okc                 C      t d}| jtd| dS )zSend connection close.zMysqlx.Connection.Closez$Mysqlx.ClientMessages.Type.CON_CLOSENr  rx   r>   r>   r?   send_connection_close     zProtocol.send_connection_closec                 C   rf  )zSend close.zMysqlx.Session.Closez%Mysqlx.ClientMessages.Type.SESS_CLOSENr  rx   r>   r>   r?   
send_close  rh  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.Conditioncondition_keyz6.1condition_valuezMysqlx.Expect.Opencondz&Mysqlx.ClientMessages.Type.EXPECT_OPENN)r   r   r   r   r   )r=   cond_keymsg_ocmsg_eor>   r>   r?   send_expect_open  s   zProtocol.send_expect_open	keep_openc                 C   sr   t d}|du r z|   |   d}W n ty   d}Y nw |r&d|d< | jtd| |   |r7dS dS )zSend reset session message.

        Returns:
            boolean: ``True`` if the server will keep the session open,
                     otherwise ``False``.
        zMysqlx.Session.ResetNTFrq  z%Mysqlx.ClientMessages.Type.SESS_RESET)r   rp  r   r
   r   r   r   )r=   rq  ry   r>   r>   r?   
send_reset  s$   zProtocol.send_reset)T)NN)r0   NrX   )BrP   rQ   rR   rS   rV   r   r@   propertyr   rT   r   staticmethodr'   r   r   r   r   r   r$   r   r   r)   r(   r   r*   r   rm   r~   r   r   r  rU   r  r	  r
  r   r   r!   r"   r#   r%   r   r%  r   r'  r,  r*  r   r  r  r  r,   r   rH  r   r    rS  rU  rV  r&   re  r   rg  ri  rp  rr  r>   r>   r>   r?   r   D  s    	K

.0!3


D
%




*


)


%


*

4
$


r   )CrS   ri   r9   ior   typingr   r   r   r   r   r   	lz4.framerD   HAVE_LZ4ImportError	zstandardr6   	HAVE_ZSTDerrorsr
   r   r   r   rQ  r   r   r   r   r   r   helpersr   r   r   protobufr   r   r   r   r   r   	statementr   r   r   r   r    r!   r"   r#   r$   r%   typesr&   r'   r(   r)   r*   r+   r,   r-   r   r.   rV   r   r   r>   r>   r>   r?   <module>   s<     0(Dd=