1 /*
2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, version 2.0,
6  * as published by the Free Software Foundation.
7  *
8  * This program is also distributed with certain software (including
9  * but not limited to OpenSSL) that is licensed under separate terms,
10  * as designated in a particular file or component or in included license
11  * documentation.  The authors of MySQL hereby grant you an additional
12  * permission to link the program and your derivative works with the
13  * separately licensed software that they have included with MySQL.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License, version 2.0, for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23  */
24 
25 // MySQL DB access module, for use by plugins and others
26 // For the module that implements interactive DB functionality see mod_db
27 
28 #ifndef PLUGIN_X_CLIENT_MYSQLXCLIENT_XPROTOCOL_H_
29 #define PLUGIN_X_CLIENT_MYSQLXCLIENT_XPROTOCOL_H_
30 
31 #include <functional>
32 #include <memory>
33 #include <string>
34 #include <utility>
35 #include <vector>
36 
37 #include "mysqlxclient/xmessage.h"
38 
39 #include "mysqlxclient/xargument.h"
40 #include "mysqlxclient/xcompression.h"
41 #include "mysqlxclient/xconnection.h"
42 #include "mysqlxclient/xerror.h"
43 #include "mysqlxclient/xquery_result.h"
44 
45 #ifdef USE_MYSQLX_FULL_PROTO
46 #define HAVE_MYSQLX_FULL_PROTO(Y, N) Y
47 #else
48 #define HAVE_MYSQLX_FULL_PROTO(Y, N) N
49 #endif
50 
51 #define XCL_CLIENT_ID_NOT_VALID 0
52 #define XCL_SESSION_ID_NOT_VALID 0
53 #define XCL_HANDLER_ID_NOT_VALID -1
54 
55 namespace xcl {
56 
57 /**
58   Enum that defines result of dispatching a message or a notice
59   to handler registred by user or XSession.
60 */
61 enum class Handler_result {
62   /**
63     No action, dispatch the message/notice to next handler or
64     return the message.
65   */
66   Continue,
67   /**
68     Message consumed. Stop dispatching the message. Requester
69     is going to wait for next message/notice.
70   */
71   Consumed,
72   /**
73     Message consumed. Stop dispatching the message. Requester
74     is going to receive an error.
75   */
76   Error
77 };
78 
79 /**
80   Enum that defines the position inside priority group
81   where the handler is going to be appended.
82 */
83 enum class Handler_position {
84   Begin,
85   End,
86 };
87 
88 /**
89   Enum that defines a execution priority of a handler.
90 
91   User handlers should be pushed on stack with "medium" priority. To overwrite
92   behavior defined by XSession, XQuery_result, XProtocol objects, user can push
93   their handler to other priorities.
94 */
95 enum Handler_priority {
96   /** Priority used by XSession object */
97   Handler_priority_high = 100,
98   /** Priority for handlers added by user */
99   Handler_priority_medium = 200,
100   /** Priority used by XSession object */
101   Handler_priority_low = 300,
102 };
103 
104 /**
105   Interface defining X Protocol operations.
106 
107   It is responsible for building, serialization, deserialization of protobuf
108   messages also it defines some basic X Protocol flows. The interface can be
109   used for:
110 
111   * all X Protocol specific featured CRUD, pipelining, notices
112   * sending messages that were recently added to proto files and 'send'
113     method was not created for them
114   * flows that were not implemented in XSession or XProtocol
115 */
116 class XProtocol {
117  public:
118   /** Data type used on the wire for transferring Message_type_id */
119   using Header_message_type_id = uint8_t;
120 
121   /** Aliases for types that represents different X Protocols message */
122   using Server_message_type_id = Mysqlx::ServerMessages::Type;
123   using Client_message_type_id = Mysqlx::ClientMessages::Type;
124 
125   /** Identification (representation) of notice handler placed in queue */
126   using Handler_id = int;
127 
128   /** Alias for type that is able to hold X Plugins client identifier */
129   using Client_id = uint64_t;
130 
131   /** Alias for protobuf message type used by the lite or
132       full version of the library */
133   using Message = HAVE_MYSQLX_FULL_PROTO(::google::protobuf::Message,
134                                          ::google::protobuf::MessageLite);
135 
136   /** Function wrapper that can be used for X Protocol notice processing */
137   using Notice_handler = std::function<Handler_result(
138       XProtocol *protocol, const bool, const Mysqlx::Notice::Frame::Type,
139       const char *, const uint32_t)>;
140 
141   /** Function wrapper that can be used for X Protocol message processing. */
142   using Client_message_handler = std::function<Handler_result(
143       XProtocol *protocol, const Client_message_type_id, const Message &)>;
144   using Server_message_handler = std::function<Handler_result(
145       XProtocol *protocol, const Server_message_type_id, const Message &)>;
146 
147   using Capabilities = ::Mysqlx::Connection::Capabilities;
148 
149  public:
150   virtual ~XProtocol() = default;
151 
152   /**
153     Add handler to the notice-handler list.
154 
155     Notice handlers are going to be held on a three different priority lists.
156     Handler can be pushed at front or back of the list. Each notice/message
157     received through this interface is going through all pushed handler
158     in sequence defined by priorities and order of front/back pushes.
159     Handlers are called in case when the message type is a notice and "message
160     recv-handlers" didn't drop the message. When the handler returns:
161 
162     * "Handler_continue", the received notice is processed as usual.
163     * "Handler_consumed", the dispatch to next handler is stopped. Received
164        notice is dropped causing the receive function to wait for next notice.
165     * "Handler_error", the dispatch to next handler is stopped. Received message
166        is dropped and the receive functions gets and error
167     CR_X_INTERNAL_ABORTED.
168 
169     @param handler     callback which is going to be called on each
170                        notice received through current instance of XProtocol
171     @param position    chooses where the handler is going to be inserted at
172                        "begin" or "end" of selected priority list
173     @param priority    chooses to which priority list the handler is going
174                        to be added
175 
176     @return position ID of notice handler
177   */
178   virtual Handler_id add_notice_handler(
179       Notice_handler handler,
180       const Handler_position position = Handler_position::Begin,
181       const Handler_priority priority = Handler_priority_medium) = 0;
182 
183   /**
184     Removes a handler represented by 'id' from the notice hander container.
185 
186     @param id          id of header which should be removed
187   */
188   virtual void remove_notice_handler(const Handler_id id) = 0;
189 
190   /**
191     Add handler to the recv-handler list.
192 
193     Received message handlers are going to be held on a three different
194     priority lists. Handler can be pushed at front or back of the list.
195     Each message received through this interface is going through all pushed
196     handler in sequence defined by priorities and order of front/back pushes.
197     Handlers are called after message deserialization. When the handler
198     returns:
199 
200     * "Handler_continue", the received message is processed as usual.
201     * "Handler_consumed", the dispatch to next handler is stopped, received
202        message is dropped causing the receive function to wait for next message.
203     * "Handler_error", the dispatch to next handler is stopped, received message
204        is dropped and the receive functions gets and error
205     CR_X_INTERNAL_ABORTED.
206 
207     @param handler     callback which is going to be called on each
208                        message received through current instance of XProtocol
209     @param position    chooses where the handler is going to be inserted at
210                        "begin" or "end" of selected priority list
211     @param priority    chooses to which priority list the handler is going
212                        to be added
213 
214     @return position ID of notice handler
215   */
216   virtual Handler_id add_received_message_handler(
217       Server_message_handler handler,
218       const Handler_position position = Handler_position::Begin,
219       const Handler_priority priority = Handler_priority_medium) = 0;
220 
221   /**
222     Removes a handler represented by 'id' from the received
223     handler container.
224 
225     @param id          id of header which should be removed
226   */
227   virtual void remove_received_message_handler(const Handler_id id) = 0;
228 
229   /**
230     Add handler to the send-handler list.
231 
232     Send message handlers are going to be held on a three different
233     priority lists. Handler can be pushed at front or back of the list.
234     Each message send through this interface is going through all pushed
235     handler in sequence defined by priorities and order of front/back pushes.
236     Handlers are called before message serialization. Handlers return value
237     is ignored.
238 
239     @param handler     callback which is going to be called on each
240                        message sent through current instance of XProtocol
241     @param position    chooses where the handler is going to be inserted:
242                        "begin" or "end" of selected priority list
243     @param priority    chooses to which priority list the handler is going
244                        to be added
245 
246     @return position ID of notice handler
247   */
248   virtual Handler_id add_send_message_handler(
249       Client_message_handler handler,
250       const Handler_position position = Handler_position::Begin,
251       const Handler_priority priority = Handler_priority_medium) = 0;
252 
253   /**
254     Removes a handler represented by 'id' from the send
255     handler container.
256 
257     @param id          id of header which should be removed
258   */
259   virtual void remove_send_message_handler(const Handler_id id) = 0;
260 
261   /**
262     Get connection layer of XProtocol.
263 
264     The lower layer can by used do direct I/O operation on the
265     socket.
266   */
267   virtual XConnection &get_connection() = 0;
268 
269   //
270   // Methods that send or receive single message
271 
272   /**
273     Read and deserialize single message.
274 
275     Message is read using XConnection, and deserialized in implementation
276     of this interface. Received message before returning is going to be
277     dispatched through "message handlers" and if it is a "notice" then it is
278     going to be dispatched through "notice handlers". The handlers are going
279     to decide what to do with the current message: ignore, allow, fail.
280     When the message is ignored the  function is going to wait for next
281     message.
282     Following errors can occur while reading message/abort reading of the
283     message:
284 
285     * I/O error from XConnection
286     * timeout error from XConnection
287     * error from dispatchers (notice, message)
288 
289     @param[out] out_mid    return received message identifier
290     @param[out] out_error  if error occurred, this argument if going to be set
291                            to its code and description
292 
293     @return Deserialized protobuf message
294       @retval != nullptr   OK
295       @retval == nullptr   I/O error, timeout error or dispatcher
296                            error occurred
297   */
298   virtual std::unique_ptr<Message> recv_single_message(
299       Server_message_type_id *out_mid, XError *out_error) = 0;
300 
301   /**
302     Receive raw payload (of X Protocol message).
303 
304     This method receives a X Protocol message which consists of 'header' and
305     'payload'. The header is received first, it holds message identifier and
306     payload size(buffer size), payload(content of 'buffer') is received after
307     the header. The method blocks until header and whole payload is stored
308     inside user provided buffer. The length of the payload is limited by
309     2^32 (length field uint32) - 5 (header size).
310     When the value of expression '*buffer' is set to 'nullptr', then the method
311     is going to allocate the buffer for the payload. User needs to release the
312     buffer by calling 'delete[]' on it.
313     Message payload received using this method isn't dispatched through
314     "message handler" nor "notice handlers".
315 
316     @param[out]    out_mid     message identifier of received message
317     @param[in,out] buffer      buffer for the message payload
318     @param[in,out] buffer_size size of the buffer, after the call it is going
319                                to hold payload length
320 
321     @return Error code with description
322       @retval != true     OK
323       @retval == true     I/O error occurred
324   */
325   virtual XError recv(Header_message_type_id *out_mid, uint8_t **buffer,
326                       std::size_t *buffer_size) = 0;
327 
328   /**
329     Deserialize X Protocol message from raw payload.
330 
331     This method deserializes the raw payload acquired by
332     `XProtocol::recv` method.
333 
334     @param mid          message identifier
335     @param payload      message payload
336     @param payload_size message payloads size
337     @param out_error    deserialization error
338 
339     @return Error code with description
340       @retval != true     OK
341       @retval == true     deserialization error occurred
342   */
343   virtual std::unique_ptr<Message> deserialize_received_message(
344       const Header_message_type_id mid, const uint8_t *payload,
345       const std::size_t payload_size, XError *out_error) = 0;
346 
347   /**
348     Serialize and send protobuf message.
349 
350     This method builds message payload when serializing 'msg' and prepends it
351     with a 'header' holding the message identifier and payload size.
352     Such construction is send using XConnection interface.
353 
354     @param mid      message identifier
355     @param msg      message to be serialized and sent
356 
357     @return Error code with description
358       @retval != true     OK
359       @retval == true     I/O error or timeout error occurred
360   */
361   virtual XError send(const Client_message_type_id mid, const Message &msg) = 0;
362 
363   /**
364     Send the raw payload as message.
365 
366     This method sends a X Protocol message which consist from 'header' and
367     'payload'.  The header is send first, it holds message identifier and
368     payload size(buffer size), payload(content of 'buffer') is send after
369     the header. The method blocks until header and payload is fully queued
370     inside TCP stack. The length of the payload is limited by
371     2^32 (length field uint32) - 5 (header size).
372 
373     @param mid      message identifier
374     @param buffer   already serialized message payload
375     @param length   size of the custom payload
376 
377     @return Error code with description
378       @retval != true     OK
379       @retval == true     I/O error occurred
380   */
381   virtual XError send(const Header_message_type_id mid, const uint8_t *buffer,
382                       const std::size_t length) = 0;
383 
384   /**
385     Serialize, compress and send protobuf message.
386 
387     This method compresses 'message', and places it into 'payload'
388     field of `Compression` message. `Compression` message is serialized
389     and send to the wire.
390     Such construction is send using XConnection interface.
391 
392     @param message_id   message identifier
393     @param message      to be serialized and sent
394 
395     @return Error code with description
396       @retval != true     OK
397       @retval == true     I/O error or timeout error occurred
398   */
399   virtual XError send_compressed_frame(const Client_message_type_id message_id,
400                                        const Message &message) = 0;
401 
402   /**
403     Serialize, compress and send multiple protobuf message of different type.
404 
405     This method builds "Compression" message that encodes and compresses all
406     'messages' into "payload" field. Later on "Compression" message is
407     serialized and send to the wire. size. Such construction is send using
408     XConnection interface.
409 
410     @param messages     messages to be serialized, compressed and sent
411 
412     @return Error code with description
413       @retval != true     OK
414       @retval == true     I/O error or timeout error occurred
415   */
416   virtual XError send_compressed_multiple_frames(
417       const std::vector<std::pair<Client_message_type_id, const Message *>>
418           &messages) = 0;
419 
420   /**
421     Serialize and send protobuf message.
422 
423     @param m      message to be serialized and sent
424 
425     @return Error code with description
426       @retval != true     OK
427       @retval == true     I/O error occurred
428   */
429   virtual XError send(const Mysqlx::Session::AuthenticateStart &m) = 0;
430 
431   /**
432     Serialize and send protobuf message.
433 
434     @param m      message to be serialized and sent
435 
436     @return Error code with description
437       @retval != true     OK
438       @retval == true     I/O error occurred
439   */
440   virtual XError send(const Mysqlx::Session::AuthenticateContinue &m) = 0;
441 
442   /**
443     Serialize and send protobuf message.
444 
445     @param m      message to be serialized and sent
446 
447     @return Error code with description
448       @retval != true     OK
449       @retval == true     I/O error occurred
450   */
451   virtual XError send(const Mysqlx::Session::Reset &m) = 0;
452 
453   /**
454     Serialize and send protobuf message.
455 
456     @param m      message to be serialized and sent
457 
458     @return Error code with description
459       @retval != true     OK
460       @retval == true     I/O error occurred
461   */
462   virtual XError send(const Mysqlx::Session::Close &m) = 0;
463 
464   /**
465     Serialize and send protobuf message.
466 
467     @param m      message to be serialized and sent
468 
469     @return Error code with description
470       @retval != true     OK
471       @retval == true     I/O error occurred
472   */
473   virtual XError send(const Mysqlx::Sql::StmtExecute &m) = 0;
474 
475   /**
476     Serialize and send protobuf message.
477 
478     @param m      message to be serialized and sent
479 
480     @return Error code with description
481       @retval != true     OK
482       @retval == true     I/O error occurred
483   */
484   virtual XError send(const Mysqlx::Crud::Find &m) = 0;
485 
486   /**
487     Serialize and send protobuf message.
488 
489     @param m      message to be serialized and sent
490 
491     @return Error code with description
492       @retval != true     OK
493       @retval == true     I/O error occurred
494   */
495   virtual XError send(const Mysqlx::Crud::Insert &m) = 0;
496 
497   /**
498     Serialize and send protobuf message.
499 
500     @param m      message to be serialized and sent
501 
502     @return Error code with description
503       @retval != true     OK
504       @retval == true     I/O error occurred
505   */
506   virtual XError send(const Mysqlx::Crud::Update &m) = 0;
507 
508   /**
509     Serialize and send protobuf message.
510 
511     @param m      message to be serialized and sent
512 
513     @return Error code with description
514       @retval != true     OK
515       @retval == true     I/O error occurred
516   */
517   virtual XError send(const Mysqlx::Crud::Delete &m) = 0;
518 
519   /**
520     Serialize and send protobuf message.
521 
522     @param m      message to be serialized and sent
523 
524     @return Error code with description
525       @retval != true     OK
526       @retval == true     I/O error occurred
527   */
528   virtual XError send(const Mysqlx::Crud::CreateView &m) = 0;
529 
530   /**
531     Serialize and send protobuf message.
532 
533     @param m      message to be serialized and sent
534 
535     @return Error code with description
536       @retval != true     OK
537       @retval == true     I/O error occurred
538   */
539   virtual XError send(const Mysqlx::Crud::ModifyView &m) = 0;
540 
541   /**
542     Serialize and send protobuf message.
543 
544     @param m      message to be serialized and sent
545 
546     @return Error code with description
547       @retval != true     OK
548       @retval == true     I/O error occurred
549   */
550   virtual XError send(const Mysqlx::Crud::DropView &m) = 0;
551 
552   /**
553     Serialize and send protobuf message.
554 
555     @param m      message to be serialized and sent
556 
557     @return Error code with description
558       @retval != true     OK
559       @retval == true     I/O error occurred
560   */
561   virtual XError send(const Mysqlx::Expect::Open &m) = 0;
562 
563   /**
564     Serialize and send protobuf message.
565 
566     @param m      message to be serialized and sent
567 
568     @return Error code with description
569       @retval != true     OK
570       @retval == true     I/O error occurred
571   */
572   virtual XError send(const Mysqlx::Expect::Close &m) = 0;
573 
574   /**
575     Serialize and send protobuf message.
576 
577     @param m      message to be serialized and sent
578 
579     @return Error code with description
580       @retval != true     OK
581       @retval == true     I/O error occurred
582   */
583   virtual XError send(const Mysqlx::Connection::CapabilitiesGet &m) = 0;
584 
585   /**
586     Serialize and send protobuf message.
587 
588     @param m      message to be serialized and sent
589 
590     @return Error code with description
591       @retval != true     OK
592       @retval == true     I/O error occurred
593   */
594   virtual XError send(const Mysqlx::Connection::CapabilitiesSet &m) = 0;
595 
596   /**
597     Serialize and send protobuf message.
598 
599     @param m      message to be serialized and sent
600 
601     @return Error code with description
602       @retval != true     OK
603       @retval == true     I/O error occurred
604   */
605   virtual XError send(const Mysqlx::Connection::Close &m) = 0;
606 
607   /**
608     Serialize and send protobuf message.
609 
610     @param m      message to be serialized and sent
611 
612     @return Error code with description
613       @retval != true     OK
614       @retval == true     I/O error occurred
615   */
616   virtual XError send(const Mysqlx::Cursor::Open &m) = 0;
617 
618   /**
619     Serialize and send protobuf message.
620 
621     @param m      message to be serialized and sent
622 
623     @return Error code with description
624       @retval != true     OK
625       @retval == true     I/O error occurred
626   */
627   virtual XError send(const Mysqlx::Cursor::Close &m) = 0;
628 
629   /**
630     Serialize and send protobuf message.
631 
632     @param m      message to be serialized and sent
633 
634     @return Error code with description
635       @retval != true     OK
636       @retval == true     I/O error occurred
637   */
638   virtual XError send(const Mysqlx::Cursor::Fetch &m) = 0;
639 
640   /**
641     Serialize and send protobuf message.
642 
643     @param m      message to be serialized and sent
644 
645     @return Error code with description
646       @retval != true     OK
647       @retval == true     I/O error occurred
648   */
649   virtual XError send(const Mysqlx::Prepare::Prepare &m) = 0;
650 
651   /**
652     Serialize and send protobuf message.
653 
654     @param m      message to be serialized and sent
655 
656     @return Error code with description
657       @retval != true     OK
658       @retval == true     I/O error occurred
659   */
660   virtual XError send(const Mysqlx::Prepare::Execute &m) = 0;
661 
662   /**
663     Serialize and send protobuf message.
664 
665     @param m      message to be serialized and sent
666 
667     @return Error code with description
668       @retval != true     OK
669       @retval == true     I/O error occurred
670   */
671   virtual XError send(const Mysqlx::Prepare::Deallocate &m) = 0;
672 
673   /*
674     Methods that execute different message flows
675     with the server
676   */
677 
678   /**
679     Get an object that is capable of reading resultsets.
680 
681     Create and return an object without doing I/O operations.
682 
683     @return Object responsible for fetching "resultset/s" from the server
684       @retval != nullptr  OK
685       @retval == nullptr  error occurred
686   */
687   virtual std::unique_ptr<XQuery_result> recv_resultset() = 0;
688 
689   /**
690     Get an object that is capable of reading resultsets.
691 
692     Create and return an object which already fetched metadata.
693     If server returns an error or an I/O error occurred then
694     the function returns a valid object, the reason of doing so
695     is that before the error some warnings could be received.
696     User must have a possibility to investigate the warnings.
697 
698     @param[out] out_error  in case of error, the method is going to return error
699                            code and description
700 
701     @return Object responsible for fetching "resultset/s" from the server
702       @retval != nullptr  always valid object
703   */
704   virtual std::unique_ptr<XQuery_result> recv_resultset(XError *out_error) = 0;
705 
706   /**
707     Read "Mysqlx.Ok" message.
708 
709     Expect to receive "Ok" message.
710     * in case of any other message return out of sync error
711     * in case "Mysqlx.Error" message translate it to "XError"
712     "Ok" message is used in several different situations like: setting
713     capabilities, creating views, expectations.
714 
715     @return Error code with description
716       @retval != true     Received OK message
717       @retval == true     I/O error, timeout error, dispatch error
718                            or received "Mysqlx.Error" message
719    */
720   virtual XError recv_ok() = 0;
721 
722   /**
723     Execute session closing flow.
724 
725     Send "Mysqlx::Session::Close" message and expect successful confirmation
726     from the X Plugin by reception of "Mysqlx::Ok". Synchronization errors and
727     "Mysqlx::Error" are returned through return values.
728 
729     @return Error code with description
730       @retval != true     Received OK message
731       @retval == true     I/O error, timeout error, dispatch error
732                            or received "Mysqlx.Error" message
733    */
734   virtual XError execute_close() = 0;
735 
736   /**
737     Send custom message and expect resultset as response.
738 
739     @param mid             id of the message to be serialized
740     @param msg             message to be serialized and sent
741     @param[out] out_error  in case of error, the method is going to return error
742                            code and description
743 
744     @return Object responsible for fetching "resultset/s" from the server
745       @retval != nullptr  OK
746       @retval == nullptr  I/O error, timeout error, dispatch error
747                           or received "Mysqlx.Error" message
748   */
749   virtual std::unique_ptr<XQuery_result> execute_with_resultset(
750       const Client_message_type_id mid, const Message &msg,
751       XError *out_error) = 0;
752 
753   /**
754     Send statement execute and expect resultset as response.
755 
756     @param msg             "StmtExecute" message to be serialized and sent
757     @param[out] out_error  in case of error, the method is going to return error
758                            code and description
759     @return Object responsible for fetching "resultset/s" from the server
760       @retval != nullptr  OK
761       @retval == nullptr  I/O error, timeout error, dispatch error
762                           or received "Mysqlx.Error" message
763   */
764   virtual std::unique_ptr<XQuery_result> execute_stmt(
765       const Mysqlx::Sql::StmtExecute &msg, XError *out_error) = 0;
766 
767   /**
768     Send crud find and expect resultset as response.
769 
770     @param msg             "Find" message to be serialized and sent
771     @param[out] out_error  in case of error, the method is going to return error
772                            code and description
773 
774     @return Object responsible for fetching "resultset/s" from the server
775       @retval != nullptr  OK
776       @retval == nullptr  I/O error, timeout error, dispatch error
777                           or received "Mysqlx.Error" message
778   */
779   virtual std::unique_ptr<XQuery_result> execute_find(
780       const Mysqlx::Crud::Find &msg, XError *out_error) = 0;
781 
782   /**
783     Send crud update and expect resultset as response.
784 
785     @param msg             "Update" message to be serialized and sent
786     @param[out] out_error  in case of error, the method is going to return error
787                            code and description
788 
789     @return Object responsible for fetching "resultset/s" from the server
790       @retval != nullptr  OK
791       @retval == nullptr  I/O error, timeout error, dispatch error
792                           or received "Mysqlx.Error" message
793   */
794   virtual std::unique_ptr<XQuery_result> execute_update(
795       const Mysqlx::Crud::Update &msg, XError *out_error) = 0;
796 
797   /**
798     Send crud insert and expect resultset as response.
799 
800     @param msg             "Insert" message to be serialized and sent
801     @param[out] out_error  in case of error, the method is going to return error
802                            code and description
803 
804     @return Object responsible for fetching "resultset/s" from the server
805       @retval != nullptr  OK
806       @retval == nullptr  I/O error, timeout error, dispatch error
807                           or received "Mysqlx.Error" message
808   */
809   virtual std::unique_ptr<XQuery_result> execute_insert(
810       const Mysqlx::Crud::Insert &msg, XError *out_error) = 0;
811 
812   /**
813     Send crud delete and expect resultset as response.
814 
815     @param msg             "Delete" message to be serialized and sent
816     @param[out] out_error  in case of error, the method is going to return error
817                            code and description
818     @return Object responsible for fetching "resultset/s" from the server
819       @retval != nullptr  OK
820       @retval == nullptr  I/O error, timeout error, dispatch error
821                           or received "Mysqlx.Error" message
822   */
823   virtual std::unique_ptr<XQuery_result> execute_delete(
824       const Mysqlx::Crud::Delete &msg, XError *out_error) = 0;
825 
826   /**
827     Send prepared stmt execute and expect resultset as response.
828 
829     @param msg             "Execute" message to be serialized and sent
830     @param[out] out_error  in case of error, the method is going to return error
831                            code and description
832     @return Object responsible for fetching "resultset/s" from the server
833       @retval != nullptr  OK
834       @retval == nullptr  I/O error, timeout error, dispatch error
835                           or received "Mysqlx.Error" message
836   */
837   virtual std::unique_ptr<XQuery_result> execute_prep_stmt(
838       const Mysqlx::Prepare::Execute &msg, XError *out_error) = 0;
839 
840   /**
841     Send cursor open and expect resultset as response.
842 
843     @param msg             "Cursor::Open" message to be serialized and sent
844     @param[out] out_error  in case of error, the method is going to return error
845                            code and description
846     @return Object responsible for fetching "resultset/s" from the server
847       @retval != nullptr  OK
848       @retval == nullptr  I/O error, timeout error, dispatch error
849                           or received "Mysqlx.Error" message
850   */
851   virtual std::unique_ptr<XQuery_result> execute_cursor_open(
852       const Mysqlx::Cursor::Open &msg, XError *out_error) = 0;
853 
854   /**
855     Send cursor fetch and expect resultset as response.
856 
857     @param msg                 "Cursor::Fetch" message to be serialized and sent
858     @param cursor_open_result  result of a Cursor.Open operation which should
859                                contain metadata used by the fetch command
860     @param[out] out_error      in case of error, the method is going to return
861                                error code and description
862     @return Object responsible for fetching "resultset/s" from the server
863       @retval != nullptr  OK
864       @retval == nullptr  I/O error, timeout error, dispatch error
865                           or received "Mysqlx.Error" message
866   */
867   virtual std::unique_ptr<XQuery_result> execute_cursor_fetch(
868       const Mysqlx::Cursor::Fetch &msg,
869       std::unique_ptr<XQuery_result> cursor_open_result, XError *out_error) = 0;
870 
871   /**
872     Send "CapabilitiesGet" and expect Capabilities as response.
873 
874     @param[out] out_error  in case of error, the method is going to return error
875                            code and description
876 
877     @return X Protocol message containing capabilities available exposed
878             by X Plugin
879       @retval != nullptr  OK
880       @retval == nullptr  I/O error, timeout error, dispatch error
881                           or received "Mysqlx.Error" message
882   */
883   virtual std::unique_ptr<Capabilities> execute_fetch_capabilities(
884       XError *out_error) = 0;
885 
886   /**
887     Execute "CapabilitiesSet" and expect "Ok" as response.
888 
889     @param capabilities   message containing cababilities to be set
890 
891     @return Error code with description
892       @retval != true     OK
893       @retval == true     I/O error, timeout error, dispatch error
894                           or received "Mysqlx.Error" message
895   */
896   virtual XError execute_set_capability(
897       const Mysqlx::Connection::CapabilitiesSet &capabilities) = 0;
898 
899   /**
900     Execute authentication flow
901 
902     @param user    MySQL Server account name
903     @param pass    MySQL Server accounts authentication string
904     @param schema  schema which should be "used"
905     @param method  X Protocol authentication method, for example:
906                   "PLAIN", "MYSQL41"
907 
908     @return Error code with description
909       @retval != true     OK
910       @retval == true     I/O error, timeout error, dispatch error
911                           or received "Mysqlx.Error" message
912   */
913   virtual XError execute_authenticate(const std::string &user,
914                                       const std::string &pass,
915                                       const std::string &schema,
916                                       const std::string &method = "") = 0;
917 
918   virtual void use_compression(const Compression_algorithm algo) = 0;
919 
920   virtual void use_compression(const Compression_algorithm algo,
921                                const int32_t level) = 0;
922 };
923 
924 }  // namespace xcl
925 
926 #endif  // PLUGIN_X_CLIENT_MYSQLXCLIENT_XPROTOCOL_H_
927