trilogy 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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