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.
- checksums.yaml +4 -4
- data/README.md +14 -5
- data/Rakefile +6 -0
- data/ext/trilogy-ruby/cast.c +0 -4
- data/ext/trilogy-ruby/cext.c +106 -34
- data/ext/trilogy-ruby/inc/trilogy/blocking.h +118 -0
- data/ext/trilogy-ruby/inc/trilogy/builder.h +60 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +214 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +4 -1
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +269 -3
- data/ext/trilogy-ruby/inc/trilogy/reader.h +4 -0
- data/ext/trilogy-ruby/inc/trilogy/socket.h +2 -1
- data/ext/trilogy-ruby/src/blocking.c +117 -0
- data/ext/trilogy-ruby/src/builder.c +63 -0
- data/ext/trilogy-ruby/src/client.c +180 -17
- data/ext/trilogy-ruby/src/protocol.c +503 -0
- data/ext/trilogy-ruby/src/reader.c +38 -0
- data/ext/trilogy-ruby/src/socket.c +96 -39
- data/lib/trilogy/encoding.rb +97 -0
- data/lib/trilogy/error.rb +118 -0
- data/lib/trilogy/result.rb +33 -0
- data/lib/trilogy/version.rb +1 -1
- data/lib/trilogy.rb +9 -239
- data/trilogy.gemspec +1 -1
- metadata +6 -3
@@ -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
|
-
/*
|
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
|