trilogy 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -601,4 +601,218 @@ void trilogy_free(trilogy_conn_t *conn);
601
601
  */
602
602
  int trilogy_discard(trilogy_conn_t *conn);
603
603
 
604
+ /* trilogy_stmt_prepare_send - Send a prepared statement prepare command to the server.
605
+ *
606
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
607
+ * undefined.
608
+ * stmt - A pointer to the buffer containing the statement to prepare.
609
+ * stmt_len - The length of the data buffer.
610
+ *
611
+ * Return values:
612
+ * TRILOGY_OK - The quit command was successfully sent to the server.
613
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
614
+ * for writeability using `conn->sock`. Then call
615
+ * trilogy_flush_writes.
616
+ * TRILOGY_SYSERR - A system error occurred, check errno.
617
+ */
618
+ int trilogy_stmt_prepare_send(trilogy_conn_t *conn, const char *stmt, size_t stmt_len);
619
+
620
+ /* trilogy_stmt_t - The trilogy client's prepared statement type.
621
+ */
622
+ typedef trilogy_stmt_ok_packet_t trilogy_stmt_t;
623
+
624
+ /* trilogy_stmt_prepare_recv - Read the prepared statement prepare command response
625
+ * from the MySQL-compatible server.
626
+ *
627
+ * This should be called after all data written by trilogy_stmt_prepare_send is flushed
628
+ * to the network. Calling this at any other time during the connection
629
+ * lifecycle is undefined.
630
+ *
631
+ * Following a successful call to this function, the caller will also need to read off
632
+ * `trilogy_stmt_t.column_count` parameters as column packets, then
633
+ * `trilogy_stmt_t.column_count` columns as column packets. This must be done before
634
+ * the socket will be command-ready again.
635
+ *
636
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
637
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
638
+ * stmt_out - A pointer to a pre-allocated trilogy_stmt_t.
639
+ *
640
+ * Return values:
641
+ * TRILOGY_OK - The prepare command response successfully read from
642
+ * the server.
643
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
644
+ * should wait for readability using `conn->sock`.
645
+ * Then call this function until it returns a
646
+ * different value.
647
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
648
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
649
+ * packet.
650
+ * TRILOGY_SYSERR - A system error occurred, check errno.
651
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
652
+ */
653
+ int trilogy_stmt_prepare_recv(trilogy_conn_t *conn, trilogy_stmt_t *stmt_out);
654
+
655
+ /* trilogy_stmt_bind_data_send - Send a prepared statement bind long data command to the server.
656
+ *
657
+ * There is no pairing `trilogy_stmt_bind_data_recv` fucntion to this one because the server
658
+ * doesn't send a response to this command.
659
+ *
660
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
661
+ * undefined.
662
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement for which
663
+ * to bind the supplied parameter data to.
664
+ * param_num - The parameter index for which the supplied data should be bound to.
665
+ * data - A pointer to the buffer containing the data to be bound.
666
+ * data_len - The length of the data buffer.
667
+ *
668
+ * Return values:
669
+ * TRILOGY_OK - The bind data command was successfully sent to the server.
670
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
671
+ * for writeability using `conn->sock`. Then call
672
+ * trilogy_flush_writes.
673
+ * TRILOGY_SYSERR - A system error occurred, check errno.
674
+ */
675
+ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint16_t param_num, uint8_t *data,
676
+ size_t data_len);
677
+
678
+ /* trilogy_stmt_execute_send - Send a prepared statement execute command to the server.
679
+ *
680
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
681
+ * undefined.
682
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
683
+ * requesting to execute.
684
+ * flags - The flags (TRILOGY_STMT_FLAGS_t) to be used with this execute command packet.
685
+ * binds - Pointer to an array of trilogy_binary_value_t's. The array size should match that
686
+ * of `trilogy_stmt_t.column_count`.
687
+ *
688
+ * Return values:
689
+ * TRILOGY_OK - The execute command was successfully sent to the server.
690
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
691
+ * for writeability using `conn->sock`. Then call
692
+ * trilogy_flush_writes.
693
+ * TRILOGY_SYSERR - A system error occurred, check errno.
694
+ */
695
+ int trilogy_stmt_execute_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint8_t flags, trilogy_binary_value_t *binds);
696
+
697
+ /* trilogy_stmt_execute_recv - Read the prepared statement execute command response
698
+ * from the MySQL-compatible server.
699
+ *
700
+ * This should be called after all data written by trilogy_stmt_execute_send is flushed
701
+ * to the network. Calling this at any other time during the connection
702
+ * lifecycle is undefined.
703
+ *
704
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
705
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
706
+ * column_count_out - Out parameter; A pointer to a pre-allocated uint64_t. Represents the
707
+ * number of columns in the response.
708
+ *
709
+ * Return values:
710
+ * TRILOGY_OK - The prepare command response successfully read from
711
+ * the server.
712
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
713
+ * should wait for readability using `conn->sock`.
714
+ * Then call this function until it returns a
715
+ * different value.
716
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
717
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
718
+ * packet.
719
+ * TRILOGY_SYSERR - A system error occurred, check errno.
720
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
721
+ */
722
+ int trilogy_stmt_execute_recv(trilogy_conn_t *conn, uint64_t *column_count_out);
723
+
724
+ /* trilogy_stmt_read_row - Read a row from the prepared statement execute response.
725
+ *
726
+ * This should only be called after a sucessful call to trilogy_stmt_execute_recv.
727
+ * You should continue calling this until TRILOGY_EOF is returned. Denoting the end
728
+ * of the result set.
729
+ *
730
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
731
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
732
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
733
+ * requesting to execute.
734
+ * columns - The list of columns from the prepared statement.
735
+ * column_count - The number of columns in prepared statement.
736
+ * values_out - Out parameter; A pointer to a pre-allocated array of
737
+ * trilogy_binary_value_t's. There must be enough space to fit all of the
738
+ * values. This can be computed with:
739
+ * `(sizeof(trilogy_binary_value_t) * column_count)`.
740
+ *
741
+ * Return values:
742
+ * TRILOGY_OK - The prepare command response successfully read from
743
+ * the server.
744
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
745
+ * should wait for readability using `conn->sock`.
746
+ * Then call this function until it returns a
747
+ * different value.
748
+ * TRILOGY_EOF - There are no more rows to read from the result set.
749
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
750
+ * TRILOGY_PROTOCOL_VIOLATION - Invalid length parsed for a TIME/DATETIME/TIMESTAMP value.
751
+ * TRILOGY_UNKNOWN_TYPE - An unsupported or unknown MySQL type was seen.
752
+ * TRILOGY_SYSERR - A system error occurred, check errno.
753
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
754
+ */
755
+ int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
756
+ trilogy_binary_value_t *values_out);
757
+
758
+ /* trilogy_stmt_reset_send - Send a prepared statement reset command to the server.
759
+ *
760
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
761
+ * undefined.
762
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
763
+ * requesting to reset.
764
+ *
765
+ * Return values:
766
+ * TRILOGY_OK - The reset command was successfully sent to the server.
767
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
768
+ * for writeability using `conn->sock`. Then call
769
+ * trilogy_flush_writes.
770
+ * TRILOGY_SYSERR - A system error occurred, check errno.
771
+ */
772
+ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
773
+
774
+ /* trilogy_stmt_reset_recv - Read the prepared statement reset command response
775
+ * from the MySQL-compatible server.
776
+ *
777
+ * This should be called after all data written by trilogy_stmt_reset_send is flushed
778
+ * to the network. Calling this at any other time during the connection
779
+ * lifecycle is undefined.
780
+ *
781
+ * conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
782
+ * a disconnected trilogy_conn_t will also return TRILOGY_OK.
783
+ *
784
+ * Return values:
785
+ * TRILOGY_OK - The reset command response successfully read from
786
+ * the server.
787
+ * TRILOGY_AGAIN - The socket wasn't ready for reading. The caller
788
+ * should wait for readability using `conn->sock`.
789
+ * Then call this function until it returns a
790
+ * different value.
791
+ * TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
792
+ * TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
793
+ * packet.
794
+ * TRILOGY_SYSERR - A system error occurred, check errno.
795
+ * TRILOGY_CLOSED_CONNECTION - The connection is closed.
796
+ */
797
+ int trilogy_stmt_reset_recv(trilogy_conn_t *conn);
798
+
799
+ /* trilogy_stmt_close_send - Send a prepared statement close command to the server.
800
+ *
801
+ * There is no pairing `trilogy_stmt_close_recv` fucntion to this one because the server
802
+ * doesn't send a response to this command.
803
+ *
804
+ * conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
805
+ * undefined.
806
+ * stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
807
+ * requesting to close.
808
+ *
809
+ * Return values:
810
+ * TRILOGY_OK - The close command was successfully sent to the server.
811
+ * TRILOGY_AGAIN - The socket wasn't ready for writing. The caller should wait
812
+ * for writeability using `conn->sock`. Then call
813
+ * trilogy_flush_writes.
814
+ * TRILOGY_SYSERR - A system error occurred, check errno.
815
+ */
816
+ int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
817
+
604
818
  #endif
@@ -21,7 +21,10 @@
21
21
  XX(TRILOGY_OPENSSL_ERR, -16) /* check ERR_get_error() */ \
22
22
  XX(TRILOGY_UNSUPPORTED, -17) \
23
23
  XX(TRILOGY_DNS_ERR, -18) \
24
- XX(TRILOGY_AUTH_SWITCH, -19)
24
+ XX(TRILOGY_AUTH_SWITCH, -19) \
25
+ XX(TRILOGY_MAX_PACKET_EXCEEDED, -20) \
26
+ XX(TRILOGY_UNKNOWN_TYPE, -21) \
27
+ XX(TRILOGY_TIMEOUT, -22)
25
28
 
26
29
  enum {
27
30
  #define XX(name, code) name = code,
@@ -124,7 +124,9 @@
124
124
  * sets from a query. \
125
125
  */ \
126
126
  XX(TRILOGY_CAPABILITIES_MULTI_RESULTS, 0x00020000) \
127
- /* From server: the server is capable of sending multiple result sets from \
127
+ /* Not implemented. \
128
+ * \
129
+ * From server: the server is capable of sending multiple result sets from \
128
130
  * a prepared statement. \
129
131
  * \
130
132
  * From client: tells the server it's capable of handling multiple result \
@@ -185,8 +187,7 @@ typedef enum {
185
187
  /* A convenience bitmask with common client capabilities set. */
186
188
  TRILOGY_CAPABILITIES_CLIENT = (TRILOGY_CAPABILITIES_PROTOCOL_41 | TRILOGY_CAPABILITIES_SECURE_CONNECTION |
187
189
  TRILOGY_CAPABILITIES_DEPRECATE_EOF | TRILOGY_CAPABILITIES_SESSION_TRACK |
188
- TRILOGY_CAPABILITIES_PLUGIN_AUTH | TRILOGY_CAPABILITIES_TRANSACTIONS |
189
- TRILOGY_CAPABILITIES_MULTI_RESULTS)
190
+ TRILOGY_CAPABILITIES_PLUGIN_AUTH | TRILOGY_CAPABILITIES_TRANSACTIONS)
190
191
  } TRILOGY_CAPABILITIES_t;
191
192
 
192
193
  #define TRILOGY_SERVER_STATUS(XX) \
@@ -563,6 +564,15 @@ typedef struct {
563
564
  size_t last_gtid_len;
564
565
  } trilogy_ok_packet_t;
565
566
 
567
+ /* trilogy_stmt_ok_packet_t - Represents a MySQL binary protocol prepare response packet.
568
+ */
569
+ typedef struct {
570
+ uint32_t id;
571
+ uint16_t column_count;
572
+ uint16_t parameter_count;
573
+ uint16_t warning_count;
574
+ } trilogy_stmt_ok_packet_t;
575
+
566
576
  typedef struct {
567
577
  uint16_t warning_count;
568
578
  uint16_t status_flags;
@@ -613,6 +623,219 @@ typedef struct {
613
623
  size_t data_len;
614
624
  } trilogy_value_t;
615
625
 
626
+ /* trilogy_binary_value_t - MySQL binary protocol value type
627
+ *
628
+ */
629
+ typedef struct {
630
+ // Flag denoting the value is NULL.
631
+ bool is_null;
632
+
633
+ /* Flag denoting the numeric value is unsigned.
634
+ * If this is true, the unsigned numerical value types should be used
635
+ * from the `as` union below.
636
+ *
637
+ * For example, if the value's MySQL type is TRILOGY_TYPE_LONGLONG and
638
+ * `is_unsigned` is `true`, the caller should use the `.as.uint64` field
639
+ * below to access the properly unsigned value.
640
+ */
641
+ bool is_unsigned;
642
+
643
+ // The MySQL column type of this value.
644
+ TRILOGY_TYPE_t type;
645
+
646
+ /* This union is used for accessing the underlying binary type for the value.
647
+ * Each field member is documented with the MySQL column/value type it maps to.
648
+ */
649
+ union {
650
+ /* MySQL types that use this field:
651
+ *
652
+ * TRILOGY_TYPE_DOUBLE
653
+ */
654
+ double dbl;
655
+
656
+ /* MySQL types that use this field:
657
+ *
658
+ * TRILOGY_TYPE_LONGLONG
659
+ *
660
+ * Refer to the `is_unsigned` field above to see which member below should
661
+ * be used to access the value.
662
+ */
663
+ int64_t int64;
664
+ uint64_t uint64;
665
+
666
+ /* MySQL types that use this field:
667
+ *
668
+ * TRILOGY_TYPE_FLOAT
669
+ */
670
+ float flt;
671
+
672
+ /* MySQL types that use this field:
673
+ *
674
+ * TRILOGY_TYPE_LONG
675
+ * TRILOGY_TYPE_INT24
676
+ *
677
+ * Refer to the `is_unsigned` field above to see which member below should
678
+ * be used to access the value.
679
+ */
680
+ uint32_t uint32;
681
+ int32_t int32;
682
+
683
+ /* MySQL types that use this field:
684
+ *
685
+ * TRILOGY_TYPE_SHORT
686
+ *
687
+ * Refer to the `is_unsigned` field above to see which member below should
688
+ * be used to access the value.
689
+ */
690
+ uint16_t uint16;
691
+ int16_t int16;
692
+
693
+ /* MySQL types that use this field:
694
+ *
695
+ * TRILOGY_TYPE_TINY
696
+ *
697
+ * Refer to the `is_unsigned` field above to see which member below should
698
+ * be used to access the value.
699
+ */
700
+ uint8_t uint8;
701
+ int8_t int8;
702
+
703
+ /* MySQL types that use this field:
704
+ *
705
+ * TRILOGY_TYPE_STRING
706
+ * TRILOGY_TYPE_VARCHAR
707
+ * TRILOGY_TYPE_VAR_STRING
708
+ * TRILOGY_TYPE_ENUM
709
+ * TRILOGY_TYPE_SET
710
+ * TRILOGY_TYPE_LONG_BLOB
711
+ * TRILOGY_TYPE_MEDIUM_BLOB
712
+ * TRILOGY_TYPE_BLOB
713
+ * TRILOGY_TYPE_TINY_BLOB
714
+ * TRILOGY_TYPE_GEOMETRY
715
+ * TRILOGY_TYPE_BIT
716
+ * TRILOGY_TYPE_DECIMAL
717
+ * TRILOGY_TYPE_NEWDECIMAL
718
+ */
719
+ struct {
720
+ const void *data;
721
+ size_t len;
722
+ } str;
723
+
724
+ /* MySQL types that use this field:
725
+ *
726
+ * TRILOGY_TYPE_YEAR
727
+ */
728
+ uint16_t year;
729
+
730
+ /* MySQL types that use this field:
731
+ *
732
+ * TRILOGY_TYPE_DATE
733
+ * TRILOGY_TYPE_DATETIME
734
+ * TRILOGY_TYPE_TIMESTAMP
735
+ */
736
+ struct {
737
+ uint16_t year;
738
+ uint8_t month, day;
739
+ struct {
740
+ uint8_t hour, minute, second;
741
+ uint32_t micro_seconds;
742
+ } datetime;
743
+ } date;
744
+
745
+ /* MySQL types that use this field:
746
+ *
747
+ * TRILOGY_TYPE_TIME
748
+ */
749
+ struct {
750
+ bool is_negative;
751
+ uint32_t days;
752
+ uint8_t hour, minute, second;
753
+ uint32_t micro_seconds;
754
+ } time;
755
+ } as;
756
+ } trilogy_binary_value_t;
757
+
758
+ /* trilogy_build_stmt_prepare_packet - Build a prepared statement prepare command packet.
759
+ *
760
+ * builder - A pointer to a pre-initialized trilogy_builder_t.
761
+ * query - The query string to be used by the prepared statement.
762
+ * query_len - The length of query in bytes.
763
+ *
764
+ * Return values:
765
+ * TRILOGY_OK - The packet was successfully built and written to the
766
+ * builder's internal buffer.
767
+ * TRILOGY_SYSERR - A system error occurred, check errno.
768
+ */
769
+ int trilogy_build_stmt_prepare_packet(trilogy_builder_t *builder, const char *sql, size_t sql_len);
770
+
771
+ // Prepared statement flags
772
+ typedef enum {
773
+ TRILOGY_CURSOR_TYPE_NO_CURSOR = 0x00,
774
+ TRILOGY_CURSOR_TYPE_READ_ONLY = 0x01,
775
+ TRILOGY_CURSOR_TYPE_FOR_UPDATE = 0x02,
776
+ TRILOGY_CURSOR_TYPE_SCROLLABLE = 0x04,
777
+ TRILOGY_CURSOR_TYPE_UNKNOWN
778
+ } TRILOGY_STMT_FLAGS_t;
779
+
780
+ /* trilogy_build_stmt_execute_packet - Build a prepared statement execute command packet.
781
+ *
782
+ * builder - A pointer to a pre-initialized trilogy_builder_t.
783
+ * stmt_id - The statement id for which to build the execute packet with.
784
+ * flags - The flags (TRILOGY_STMT_FLAGS_t) to be used with this execute command packet.
785
+ * binds - Pointer to an array of trilogy_binary_value_t's.
786
+ * num_binds - The number of elements in the binds array above.
787
+ *
788
+ * Return values:
789
+ * TRILOGY_OK - The packet was successfully built and written to the
790
+ * builder's internal buffer.
791
+ * TRILOGY_PROTOCOL_VIOLATION - num_binds is > 0 but binds is NULL.
792
+ * TRILOGY_UNKNOWN_TYPE - An unsupported or unknown MySQL type was used in the list
793
+ * of binds.
794
+ * TRILOGY_SYSERR - A system error occurred, check errno.
795
+ */
796
+ int trilogy_build_stmt_execute_packet(trilogy_builder_t *builder, uint32_t stmt_id, uint8_t flags,
797
+ trilogy_binary_value_t *binds, uint16_t num_binds);
798
+
799
+ /* trilogy_build_stmt_bind_data_packet - Build a prepared statement bind long data command packet.
800
+ *
801
+ * builder - A pointer to a pre-initialized trilogy_builder_t.
802
+ * stmt_id - The statement id for which to build the bind data packet with.
803
+ * param_id - The parameter index for which the supplied data should be bound to.
804
+ * data - A pointer to the buffer containing the data to be bound.
805
+ * data_len - The length of the data buffer.
806
+ *
807
+ * Return values:
808
+ * TRILOGY_OK - The packet was successfully built and written to the
809
+ * builder's internal buffer.
810
+ * TRILOGY_SYSERR - A system error occurred, check errno.
811
+ */
812
+ int trilogy_build_stmt_bind_data_packet(trilogy_builder_t *builder, uint32_t stmt_id, uint16_t param_id, uint8_t *data,
813
+ size_t data_len);
814
+
815
+ /* trilogy_build_stmt_reset_packet - Build a prepared statement reset command packet.
816
+ *
817
+ * builder - A pointer to a pre-initialized trilogy_builder_t.
818
+ * stmt_id - The statement id for which to build the reset packet with.
819
+ *
820
+ * Return values:
821
+ * TRILOGY_OK - The packet was successfully built and written to the
822
+ * builder's internal buffer.
823
+ * TRILOGY_SYSERR - A system error occurred, check errno.
824
+ */
825
+ int trilogy_build_stmt_reset_packet(trilogy_builder_t *builder, uint32_t stmt_id);
826
+
827
+ /* trilogy_build_stmt_close_packet - Build a prepared statement close command packet.
828
+ *
829
+ * builder - A pointer to a pre-initialized trilogy_builder_t.
830
+ * stmt_id - The statement id for which to build the close packet with.
831
+ *
832
+ * Return values:
833
+ * TRILOGY_OK - The packet was successfully built and written to the
834
+ * builder's internal buffer.
835
+ * TRILOGY_SYSERR - A system error occurred, check errno.
836
+ */
837
+ int trilogy_build_stmt_close_packet(trilogy_builder_t *builder, uint32_t stmt_id);
838
+
616
839
  /* The following parsing functions assume the buffer and length passed in point
617
840
  * to one full MySQL-compatible packet. If the buffer contains more than one packet or
618
841
  * has any extra data at the end, these functions will return
@@ -769,4 +992,47 @@ int trilogy_parse_column_packet(const uint8_t *buff, size_t len, bool field_list
769
992
  */
770
993
  int trilogy_parse_row_packet(const uint8_t *buff, size_t len, uint64_t column_count, trilogy_value_t *out_values);
771
994
 
995
+ /* trilogy_parse_stmt_ok_packet - Parse a prepared statement ok packet.
996
+ *
997
+ * buff - A pointer to the buffer containing the result packet data.
998
+ * len - The length of buffer in bytes.
999
+ * out_packet - Out parameter; A pointer to a pre-allocated trilogy_stmt_ok_packet_t.
1000
+ *
1001
+ * Return values:
1002
+ * TRILOGY_OK - The packet was was parsed and the out
1003
+ * parameter has been filled in.
1004
+ * TRILOGY_TRUNCATED_PACKET - There isn't enough data in the buffer
1005
+ * to parse the packet.
1006
+ * TRILOGY_PROTOCOL_VIOLATION - Filler byte was something other than zero.
1007
+ * TRILOGY_EXTRA_DATA_IN_PACKET - There are unparsed bytes left in the
1008
+ * buffer.
1009
+ */
1010
+ int trilogy_parse_stmt_ok_packet(const uint8_t *buff, size_t len, trilogy_stmt_ok_packet_t *out_packet);
1011
+
1012
+ /* trilogy_parse_stmt_row_packet - Parse a prepared statement row packet.
1013
+ *
1014
+ * buff - A pointer to the buffer containing the result packet data.
1015
+ * len - The length of buffer in bytes.
1016
+ * columns - The list of columns from the prepared statement. This parser needs
1017
+ * this in order to match up the value types.
1018
+ * column_count - The number of columns in prepared statement. This parser needs this
1019
+ * in order to know how many values to parse.
1020
+ * out_values - Out parameter; A pointer to a pre-allocated array of
1021
+ * trilogy_binary_value_t's. There must be enough space to fit all of the
1022
+ * values. This can be computed with:
1023
+ * `(sizeof(trilogy_binary_value_t) * column_count)`.
1024
+ *
1025
+ * Return values:
1026
+ * TRILOGY_OK - The packet was was parsed and the out
1027
+ * parameter has been filled in.
1028
+ * TRILOGY_TRUNCATED_PACKET - There isn't enough data in the buffer
1029
+ * to parse the packet.
1030
+ * TRILOGY_PROTOCOL_VIOLATION - Invalid length parsed for a TIME/DATETIME/TIMESTAMP value.
1031
+ * TRILOGY_UNKNOWN_TYPE - An unsupported or unknown MySQL type was seen in the packet.
1032
+ * TRILOGY_EXTRA_DATA_IN_PACKET - There are unparsed bytes left in the
1033
+ * buffer.
1034
+ */
1035
+ int trilogy_parse_stmt_row_packet(const uint8_t *buff, size_t len, trilogy_column_packet_t *columns,
1036
+ uint64_t column_count, trilogy_binary_value_t *out_values);
1037
+
772
1038
  #endif
@@ -90,6 +90,10 @@ int trilogy_reader_get_uint32(trilogy_reader_t *reader, uint32_t *out);
90
90
  */
91
91
  int trilogy_reader_get_uint64(trilogy_reader_t *reader, uint64_t *out);
92
92
 
93
+ int trilogy_reader_get_float(trilogy_reader_t *reader, float *out);
94
+
95
+ int trilogy_reader_get_double(trilogy_reader_t *reader, double *out);
96
+
93
97
  /* trilogy_reader_get_lenenc - Parse an unsigned, length-encoded integer.
94
98
  *
95
99
  * reader - A pointer to a pre-initialized trilogy_reader_t.
@@ -67,6 +67,8 @@ typedef struct {
67
67
  uint16_t keepalive_interval;
68
68
 
69
69
  TRILOGY_CAPABILITIES_t flags;
70
+
71
+ size_t max_allowed_packet;
70
72
  } trilogy_sockopt_t;
71
73
 
72
74
  typedef struct trilogy_sock_t {
@@ -108,6 +110,5 @@ static inline int trilogy_sock_fd(trilogy_sock_t *sock) { return sock->fd_cb(soc
108
110
  trilogy_sock_t *trilogy_sock_new(const trilogy_sockopt_t *opts);
109
111
  int trilogy_sock_resolve(trilogy_sock_t *raw);
110
112
  int trilogy_sock_upgrade_ssl(trilogy_sock_t *raw);
111
- int trilogy_sock_discard(trilogy_sock_t *sock);
112
113
 
113
114
  #endif
@@ -261,4 +261,121 @@ int trilogy_close(trilogy_conn_t *conn)
261
261
  }
262
262
  }
263
263
 
264
+ int trilogy_stmt_prepare(trilogy_conn_t *conn, const char *stmt, size_t stmt_len, trilogy_stmt_t *stmt_out)
265
+ {
266
+ int rc = trilogy_stmt_prepare_send(conn, stmt, stmt_len);
267
+
268
+ if (rc == TRILOGY_AGAIN) {
269
+ rc = flush_full(conn);
270
+ }
271
+
272
+ if (rc < 0) {
273
+ return rc;
274
+ }
275
+
276
+ while (1) {
277
+ rc = trilogy_stmt_prepare_recv(conn, stmt_out);
278
+
279
+ if (rc != TRILOGY_AGAIN) {
280
+ return rc;
281
+ }
282
+
283
+ CHECKED(trilogy_sock_wait_read(conn->socket));
284
+ }
285
+ }
286
+
287
+ int trilogy_stmt_execute(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint8_t flags, trilogy_binary_value_t *binds,
288
+ uint64_t *column_count_out)
289
+ {
290
+ int rc = trilogy_stmt_execute_send(conn, stmt, flags, binds);
291
+
292
+ if (rc == TRILOGY_AGAIN) {
293
+ rc = flush_full(conn);
294
+ }
295
+
296
+ if (rc < 0) {
297
+ return rc;
298
+ }
299
+
300
+ while (1) {
301
+ rc = trilogy_stmt_execute_recv(conn, column_count_out);
302
+
303
+ if (rc != TRILOGY_AGAIN) {
304
+ return rc;
305
+ }
306
+
307
+ CHECKED(trilogy_sock_wait_read(conn->socket));
308
+ }
309
+ }
310
+
311
+ int trilogy_stmt_bind_data(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint16_t param_num, uint8_t *data,
312
+ size_t data_len)
313
+ {
314
+ int rc = trilogy_stmt_bind_data_send(conn, stmt, param_num, data, data_len);
315
+
316
+ if (rc == TRILOGY_AGAIN) {
317
+ rc = flush_full(conn);
318
+ }
319
+
320
+ if (rc < 0) {
321
+ return rc;
322
+ }
323
+
324
+ return TRILOGY_OK;
325
+ }
326
+
327
+ int trilogy_stmt_read_full_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
328
+ trilogy_binary_value_t *values_out)
329
+ {
330
+ int rc;
331
+
332
+ while (1) {
333
+ rc = trilogy_stmt_read_row(conn, stmt, columns, values_out);
334
+
335
+ if (rc != TRILOGY_AGAIN) {
336
+ return rc;
337
+ }
338
+
339
+ CHECKED(trilogy_sock_wait_read(conn->socket));
340
+ }
341
+ }
342
+
343
+ int trilogy_stmt_reset(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
344
+ {
345
+ int rc = trilogy_stmt_reset_send(conn, stmt);
346
+
347
+ if (rc == TRILOGY_AGAIN) {
348
+ rc = flush_full(conn);
349
+ }
350
+
351
+ if (rc < 0) {
352
+ return rc;
353
+ }
354
+
355
+ while (1) {
356
+ rc = trilogy_stmt_reset_recv(conn);
357
+
358
+ if (rc != TRILOGY_AGAIN) {
359
+ return rc;
360
+ }
361
+
362
+ CHECKED(trilogy_sock_wait_read(conn->socket));
363
+ }
364
+ }
365
+
366
+ int trilogy_stmt_close(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
367
+ {
368
+ int rc = trilogy_stmt_close_send(conn, stmt);
369
+
370
+ if (rc == TRILOGY_AGAIN) {
371
+ rc = flush_full(conn);
372
+ }
373
+
374
+ if (rc < 0) {
375
+ return rc;
376
+ }
377
+
378
+ return TRILOGY_OK;
379
+ }
380
+
264
381
  #undef CHECKED