U Yzf_@sdZddlZddlZddlmZzddlZdZWnek rHdZYnXddl m Z m Z ddl m Z mZmZmZdd lmZmZmZmZmZmZdd lmZmZdd lmZdd lmZmZm Z m!Z!m"Z"d Z#dZ$Gddde%Z&Gddde%Z'Gddde%Z(Gddde%Z)dS)z4Implementation of the X protocol for MySQL servers. N)BytesIOTF) STRING_TYPES INT_TYPES)InterfaceErrorNotSupportedErrorOperationalErrorProgrammingError) ExprParser build_expr build_scalarbuild_bool_scalarbuild_int_scalarbuild_unsigned_int_scalar)encode_to_bytesget_item_or_attr)Column)CRUD_PREPARE_MAPPINGSERVER_MESSAGESPROTOBUF_REPEATED_TYPESMessage mysqlxpb_enumi) lz4_messagedeflate_streamc@s(eZdZdZddZddZddZdS) CompressorzImplements compression/decompression using `lz4_message` and `deflate_stream` algorithms. Args: algorithm (str): Compression algorithm. .. versionadded:: 8.0.21 cCs4||_|dkr$t|_t|_n d|_d|_dS)Nr) _algorithmzlib compressobj _compressobj decompressobj_decompressobjself algorithmr$g/private/var/folders/n9/53xbvtmd7sjg1q1l55xmpg58n4mgng/T/pip-unpacked-wheel-47tvuv7y/mysqlx/protocol.py__init__Ds   zCompressor.__init__c Csh|jdkrFtj(}|}|||7}||7}W5QRX|S|j|}||jtj 7}|S)zCompresses data and returns it. Args: data (str, bytes or buffer object): Data to be compressed. Returns: bytes: Compressed data. r) rlz4frameZLZ4FrameCompressorbegincompressflushrr Z_SYNC_FLUSH)r"dataZ compressor compressedr$r$r%r*Ms   zCompressor.compressc CsP|jdkr.tj}||}W5QRX|S|j|}||jtj7}|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) rr'r(ZLZ4FrameDecompressor decompressr r+rr,)r"r-Z decompressor decompressedr$r$r%r/bs   zCompressor.decompressN)__name__ __module__ __qualname____doc__r&r*r/r$r$r$r%r:s  rc@s8eZdZdZddZddZddZdd Zd d Zd S) MessageReaderzImplements a Message Reader. Args: socket_stream (mysqlx.connection.SocketStream): `SocketStream` object. .. versionadded:: 8.0.21 cCs||_d|_d|_g|_dSN)_stream _compressor_msg _msg_queuer"Z socket_streamr$r$r%r&~szMessageReader.__init__c Cs|jr|jdStd|jd\}}|dkr:td|j|d}|tkr`td ||dkrx|d krx| St ||}|d kr|d }t |j|d }d}||krtd|d\}} ||d} |jt | | ||d 7}q|jr|jdSdS|S)aReads 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. rd?Z"d@dAZ#dGdBdCZ$dS)HProtocolzImplements 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 cCs||_||_d|_dSr6)_reader_writer_compression_algorithm)r"readerwriterr$r$r%r&szProtocol.__init__cCs|jS)z'str: The compresion algorithm. )rc)r"r$r$r%compression_algorithmszProtocol.compression_algorithmcCsX|jr||d<|jr*|d||jrB|d||jrT||d<dS)zApply filter. Args: msg (mysqlx.protobuf.Message): The MySQL X Protobuf Message. stmt (Statement): A `Statement` based type object. ZcriteriaordergroupingZgrouping_criteriaN) Z has_whereZget_where_exprZhas_sortextendZ get_sort_exprZ has_group_byZ get_groupingZ has_havingZ get_having)r"rQstmtr$r$r% _apply_filter%s zProtocol._apply_filtercCst|tr2td|d}tdd|d}tdd|dSt|trNtddt|dSt|tr|d krrtddt|dStddt|dSt|trt |d kr|\}}td || |d }td | gd}tdd |dSt|t st|t tfrt|d t rg}|D]h} g} | D],\} }td | | |d }| | qtd | d} tdd | d} || q td}||d<tdd|dSt|t rg} |D],\} }td | | |d }| | qtd | d} tdd | d} | SdS)zCreate any. Args: arg (object): Arbitrary object. Returns: mysqlx.protobuf.Message: MySQL X Protobuf Message. zMysqlx.Datatypes.Scalar.StringvaluezMysqlx.Datatypes.Scalar)typeZv_stringMysqlx.Datatypes.Anyr)roscalarr#Mysqlx.Datatypes.Object.ObjectFieldkeyrmMysqlx.Datatypes.ObjectZfldroobjzMysqlx.Datatypes.Arrayrm)roarrayN) isinstancerrboolr rrrtupler[ _create_any get_messagedictlistitemsrL)r"argrmrqZarg_key arg_valueobj_fldryZ array_valuesrobj_fldsrumsg_objmsg_anyrQr$r$r%r5sp         zProtocol._create_anyTc sfdd|}|}|dkr8fdd|DSt|}|dg}|t|kr^td|D]2\}}||krtd|||} ||| <qf|S)aReturns 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. csrt|S|Sr6)r rrrl) is_scalarr"r$r%}sz,Protocol._get_binding_args..Ncsg|] }|qSr$r$.0rm) build_valuer$r% sz.Protocol._get_binding_args..z;The number of bind parameters and placeholders do not matchz-Unable to find placeholder for parameter: {0}) get_bindingsZget_binding_mapr[r rrJ) r"rjrZbindingsZ binding_mapcountargsnamermposr$)rrr"r%_get_binding_argsos"  zProtocol._get_binding_argscCs|ddkr2td|d}||j|j|jn|ddkrPtd|dn|ddkrtd|d}|d td kr|d d |d Dnht|d t t r|d dn|d }|d tdkr| t |dn |d tdkr| t |ddS)zProcess frame. Args: msg (mysqlx.protobuf.Message): A MySQL X Protobuf Message. result (Result): A `Result` based type object. rorzMysqlx.Notice.WarningrCrrz$Mysqlx.Notice.SessionVariableChangedrzz!Mysqlx.Notice.SessionStateChangedparamzBMysqlx.Notice.SessionStateChanged.Parameter.GENERATED_DOCUMENT_IDScSs g|]}tt|ddqS)Zv_octetsrm)rdecoderr$r$r%rs z+Protocol._process_frame..rmrz9Mysqlx.Notice.SessionStateChanged.Parameter.ROWS_AFFECTEDZv_unsigned_intz?Mysqlx.Notice.SessionStateChanged.Parameter.GENERATED_INSERT_IDN)rZ from_messageZappend_warninglevelcoderQrZset_generated_idsr|r~rZset_rows_affectedrZset_generated_insert_id)r"rQresultZwarn_msgZsess_state_msgZsess_state_valuer$r$r%_process_framesR   zProtocol._process_framecCs|j}|jdkr(t|d|dq|jdkrVz|||WqYqYqXq|jdkrddS|jdkrz|dq|jd kr|dq|jd kr|dqqqq|S) z`Read message. Args: result (Result): A `Result` based type object. Mysqlx.ErrorrQrMysqlx.Notice.FramezMysqlx.Sql.StmtExecuteOkNzMysqlx.Resultset.FetchDoneTz(Mysqlx.Resultset.FetchDoneMoreResultsetsMysqlx.Resultset.Row)rarRrorrZ set_closedZset_has_more_resultsZ set_has_datar"rrQr$r$r%rKs&           zProtocol._read_messagecCs"||_|j||j|dS)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)rcrarUrbr!r$r$r%rUs  zProtocol.set_compressioncCsZtd}|jtd||j}|jdkr:|j}q$|jdkrVt|d|d|S)zkGet capabilities. Returns: mysqlx.protobuf.Message: MySQL X Protobuf Message. z!Mysqlx.Connection.CapabilitiesGetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_GETrrrQr)rrbr_rrarRrorrPr$r$r%get_capabilitess    zProtocol.get_capabilitesc Ks"|sdStd}|D]\}}td}||d<t|tr|}g}|D]*}td||||d} || qFtd|d} td d | d } | |d <n|||d <|d |gqtd} || d <|j t d| z | WSt k r} z| j dkr W5d} ~ XYnXdS)zSet capabilities. Args: **kwargs: Arbitrary keyword arguments. Returns: mysqlx.protobuf.Message: MySQL X Protobuf Message. NzMysqlx.Connection.CapabilitieszMysqlx.Connection.Capabilityrrsrtrvrwrprrrxrm capabilitiesz!Mysqlx.Connection.CapabilitiesSetz/Mysqlx.ClientMessages.Type.CON_CAPABILITIES_SETi)rrr|rrrLrrirbr_rread_okrerrno)r"kwargsrrurmZ capabilityrritemrrrrQerrr$r$r%set_capabilitiess@      zProtocol.set_capabilitiesNcCsFtd}||d<|dk r ||d<|dk r0||d<|jtd|dS)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_datainitial_responsez2Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_STARTrrbr_r)r"methodrrrQr$r$r%send_auth_start%szProtocol.send_auth_startcCs:|j}|jdkr |j}q |jdkr2td|dS)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)rarRrorrPr$r$r%read_auth_continue6s    zProtocol.read_auth_continuecCs"td|d}|jtd|dS)zeSend authenticate continue. Args: auth_data (str): Authentication data. r)rz5Mysqlx.ClientMessages.Type.SESS_AUTHENTICATE_CONTINUENr)r"rrQr$r$r%send_auth_continueHszProtocol.send_auth_continuecCs0|j}|jdkrq,|jdkrt|jqdS)z~Read authenticate OK. Raises: :class:`mysqlx.InterfaceError`: If message type is `Mysqlx.Error`. zMysqlx.Session.AuthenticateOkrN)rarRrorrQrPr$r$r% read_auth_okSs    zProtocol.read_auth_okc CsB|jr|jdkr|jdkr*||\}}nB|jdkrD||\}}n(|jdkr^||\}}ntd|t|}t d}t d}t d||d |d <|jdkrt d||d d |d <||d <t |\}} t d} t || d<|| | <t d} |j | d<| | d<|j t d| z |Wntk r<tYnXdS)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.InsertMysqlx.Crud.FindMysqlx.Crud.UpdateMysqlx.Crud.DeletezInvalid message type: {}z!Mysqlx.Expr.Expr.Type.PLACEHOLDERzMysqlx.Crud.LimitExprzMysqlx.Expr.Expr)roposition row_countroffsetZ limit_expr#Mysqlx.Prepare.Prepare.OneOfMessagerozMysqlx.Prepare.Preparestmt_idrjz*Mysqlx.ClientMessages.Type.PREPARE_PREPAREN) has_limitro build_find build_update build_deleterIrJr[rrrrrrbr_rrr) r"rOrQrj_r placeholderZmsg_limit_expr oneof_typeoneof_op msg_oneofZ msg_preparer$r$r%send_prepare_prepare`sH           zProtocol.send_prepare_preparec Cst|\}}td}t||d<|||<td}|j|d<|j|dd}|rZ|d||jr|d|| ||  g|j td|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 rrozMysqlx.Prepare.ExecuterFrrz*Mysqlx.ClientMessages.Type.PREPARE_EXECUTEN) rrrrrrirrget_limit_row_countrget_limit_offsetrbr_) r"rOrQrjrrrZ msg_executerr$r$r%send_prepare_executes$   zProtocol.send_prepare_executecCs.td}||d<|jtd||dS)z Send prepare deallocate statement. Args: stmt_id (int): Statement ID. .. versionadded:: 8.0.16 zMysqlx.Prepare.Deallocaterz-Mysqlx.ClientMessages.Type.PREPARE_DEALLOCATEN)rrbr_rr)r"rZ msg_deallocr$r$r%send_prepare_deallocates z Protocol.send_prepare_deallocatecCsx|jr8td}||d<|jdkr0||d<||d<|dkrDdnd}|j||d }|rh|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 zMysqlx.Crud.Limitrrrlimit+Mysqlx.ClientMessages.Type.SQL_STMT_EXECUTEFTrrN)rrrrorrrisend_msg)r"rOrQrjZ msg_limitrrr$r$r%send_msg_without_pss    zProtocol.send_msg_without_pscCs|jt||dS)z Send a message. Args: msg_type (str): Message ID string. msg (mysqlx.protobuf.Message): MySQL X Protobuf Message. .. versionadded:: 8.0.16 N)rbr_r)r"rOrQr$r$r%rs zProtocol.send_msgcCst|rdnd}td|jj|jjd}td||d}|jrJ||d<|||| rltd|d <n| rtd |d <|j d kr|j |d <d |fS)aBuild 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.DOCUMENTMysqlx.Crud.DataModel.TABLEMysqlx.Crud.Collectionrschemar data_model collection projectionz'Mysqlx.Crud.Find.RowLock.EXCLUSIVE_LOCKZlockingz$Mysqlx.Crud.Find.RowLock.SHARED_LOCKrZlocking_optionsz$Mysqlx.ClientMessages.Type.CRUD_FIND) r is_doc_basedrtargetrrZhas_projectionZget_projection_exprrkZis_lock_exclusiveZis_lock_sharedZlock_contentionr"rjrrrQr$r$r%rs0    zProtocol.build_findcCst|rdnd}td|jj|jjd}td||d}||||D]P\}}td}|j |d<|j |d <|j d k rt |j |d <|d |gqPd |fS) aBuild 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 rrrrrrzMysqlx.Crud.UpdateOperation operationsourceNrmz&Mysqlx.ClientMessages.Type.CRUD_UPDATE)rrrrrrrkZget_update_opsrZ update_typerrmr rir)r"rjrrrQrZ update_oprr$r$r%rs*    zProtocol.build_updatecCsLt|rdnd}td|jj|jjd}td||d}|||d|fS)aBuild 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 rrrrrrz&Mysqlx.ClientMessages.Type.CRUD_DELETE)rrrrrrrkrr$r$r%r5s  zProtocol.build_deletec Cs|td||dd}|rtg}|D]*\}}td|||d}||q td|d} tdd | d } | g|d <d |fS) aBuild 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 zMysqlx.Sql.StmtExecuteF) namespacerjZcompact_metadatarsrtrvrwrprrrxrr)rrrrLr) r"rrjfieldsrQrrurmrrrr$r$r%build_execute_statementNs z Protocol.build_execute_statementc Cst|rdnd}td|jj|jjd}td||d}t|drv|jD],}t||  }|d | gqH| D]f}td }t |tr|D]} |d  t|  gqn|d  t| g|d  | gq~t|d r||d <d|fS)aBuild 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 rrrrrr_fieldsrzMysqlx.Crud.Insert.TypedRowfieldrow is_upsertZupsertz&Mysqlx.ClientMessages.Type.CRUD_INSERT)rrrrrrhasattrrr Zparse_table_insert_fieldrirZ get_valuesr|rr r) r"rjrrrQrexprrmrvalr$r$r% build_insertls4      zProtocol.build_insertcCs||}|dk rtddS)zClose the result. Args: result (Result): A `Result` based type object. Raises: :class:`mysqlx.OperationalError`: If message read is None. NzExpected to close the result)rKrrr$r$r% close_results zProtocol.close_resultcCs4||}|dkrdS|jdkr$|S|j|dS)z\Read row. Args: result (Result): A `Result` based type object. Nr)rKrorarSrr$r$r%read_rows   zProtocol.read_rowcCsg}||}|dkrq|jdkr0|j|q|jdkrBtdt|d|d|d|d|d |d |d |d d |dd|dd|dd|d }||q|S)zReturns column metadata. Args: result (Result): A `Result` based type object. Raises: :class:`mysqlx.InterfaceError`: If unexpected message. NrzMysqlx.Resultset.ColumnMetaDatazUnexpected msg typerocatalogrtableZoriginal_tabler original_namelengthZ collationrZfractional_digitsflags content_type)rKrorarSrrgetrL)r"rcolumnsrQcolr$r$r%get_column_metadatas,          zProtocol.get_column_metadatacCsD|j}|jdkr.td|d|dd|jdkr@tddS) zeRead OK. Raises: :class:`mysqlx.InterfaceError`: If unexpected message. rzMysqlx.Error: {}rQr)rz Mysqlx.OkzUnexpected message encounteredN)rarRrorrJrPr$r$r%rs   zProtocol.read_okcCstd}|jtd|dS)zSend connection close.zMysqlx.Connection.Closez$Mysqlx.ClientMessages.Type.CON_CLOSENrrPr$r$r%send_connection_closes zProtocol.send_connection_closecCstd}|jtd|dS)z Send close.zMysqlx.Session.Closez%Mysqlx.ClientMessages.Type.SESS_CLOSENrrPr$r$r% send_closes zProtocol.send_closecCsLtd}td}||d<d|d<td}|g|d<|jtd|d S) zSend expectation.z3Mysqlx.Expect.Open.Condition.Key.EXPECT_FIELD_EXISTzMysqlx.Expect.Open.ConditionZ condition_keyz6.1Zcondition_valuezMysqlx.Expect.OpenZcondz&Mysqlx.ClientMessages.Type.EXPECT_OPENN)rrrrbr_)r"Zcond_keyZmsg_ocZmsg_eor$r$r%send_expect_openszProtocol.send_expect_opencCsttd}|dkrBz||d}Wntk r@d}YnX|rNd|d<|jtd|||rpdSdS)zSend reset session message. Returns: boolean: ``True`` if the server will keep the session open, otherwise ``False``. zMysqlx.Session.ResetNTF keep_openz%Mysqlx.ClientMessages.Type.SESS_RESET)rrrrrbr_r)r"rrQr$r$r% send_resets& zProtocol.send_reset)T)NN)N)N)%r1r2r3r4r&propertyrfrkrrrrKrUrrrrrrrrrrrrrrrrrrrrrrrrr$r$r$r%r`sD : $(-   7  '" ,  r`)*r4rFriorZ lz4.framer'ZHAVE_LZ4 ImportErrorcompatrrerrorsrrrr rr r r r rrZhelpersrrrrZprotobufrrrrrrXZ_COMPRESSION_ALGORITHMSobjectrr5rVr`r$r$r$r%s(    <b9