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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0730bbbdae7e8eab195c4ad745e223bcd55fe6299f98cb324c88beea15ebdc5e
|
4
|
+
data.tar.gz: 7779f268cbfae85bf5575f680ebff9fee6d22b78bb5d3d315ba664969ab9618a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42c81e496210cfc0538ef1dd9f4f7c34e2ce94de45e5bcfe4c5815839c463a6b3ae78af529b88c63a670b3cd2035a6b931ef76fdfe1ec508f6b7851858b664d2
|
7
|
+
data.tar.gz: ad05962a8a47cea68ab66188badf405fe96342587bd86d91faf43dd028dc641949ea58d9a6d25547e820c4700c6cd9548d70a2494f0a215b08bb8a61c9c920c8
|
data/README.md
CHANGED
@@ -34,13 +34,22 @@ if client.ping
|
|
34
34
|
result.each_hash do |user|
|
35
35
|
p user
|
36
36
|
end
|
37
|
+
end
|
38
|
+
```
|
37
39
|
|
38
|
-
|
40
|
+
### Processing multiple result sets
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
In order to send and receive multiple result sets, pass the `multi_statement` option when connecting.
|
43
|
+
`Trilogy#more_results_exist?` will return true if more results exist, false if no more results exist, or raise
|
44
|
+
an error if the respective query errored. `Trilogy#next_result` will retrieve the next result set, or return nil
|
45
|
+
if no more results exist.
|
46
|
+
|
47
|
+
``` ruby
|
48
|
+
client = Trilogy.new(host: "127.0.0.1", port: 3306, username: "root", read_timeout: 2, multi_statement: true)
|
49
|
+
|
50
|
+
results = []
|
51
|
+
results << client.query("SELECT name FROM users WHERE id = 1; SELECT name FROM users WHERE id = 2")
|
52
|
+
results << client.next_result while client.more_results_exist?
|
44
53
|
```
|
45
54
|
|
46
55
|
## Building
|
data/Rakefile
CHANGED
@@ -8,6 +8,12 @@ Rake::ExtensionTask.new do |ext|
|
|
8
8
|
ext.lib_dir = "lib/trilogy"
|
9
9
|
end
|
10
10
|
|
11
|
+
# When any of the parent library's files change, we need to re-run extconf
|
12
|
+
vendored_c_lib = FileList["ext/trilogy-ruby/src/**/*.c", "ext/trilogy-ruby/inc/**/*.h"]
|
13
|
+
if extconf_task = Rake.application.tasks.find { |t| t.name =~ /Makefile/ }
|
14
|
+
task extconf_task => vendored_c_lib
|
15
|
+
end
|
16
|
+
|
11
17
|
Rake::TestTask.new do |t|
|
12
18
|
t.libs << "test"
|
13
19
|
t.test_files = FileList['test/*_test.rb']
|
data/ext/trilogy-ruby/cast.c
CHANGED
@@ -233,10 +233,6 @@ rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *co
|
|
233
233
|
return Qnil;
|
234
234
|
}
|
235
235
|
|
236
|
-
if (hour == 0 && min == 0 && sec == 0) {
|
237
|
-
return Qnil;
|
238
|
-
}
|
239
|
-
|
240
236
|
// pad out msec_char with zeroes at the end as it could be at any
|
241
237
|
// level of precision
|
242
238
|
for (size_t i = strlen(msec_char); i < sizeof(msec_char) - 1; i++) {
|
data/ext/trilogy-ruby/cext.c
CHANGED
@@ -15,8 +15,6 @@
|
|
15
15
|
|
16
16
|
#include "trilogy-ruby.h"
|
17
17
|
|
18
|
-
#define TRILOGY_RB_TIMEOUT 1
|
19
|
-
|
20
18
|
VALUE Trilogy_CastError;
|
21
19
|
static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLError, Trilogy_QueryError,
|
22
20
|
Trilogy_ConnectionClosedError, Trilogy_ConnectionRefusedError, Trilogy_ConnectionResetError,
|
@@ -27,7 +25,7 @@ static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows,
|
|
27
25
|
id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, id_ivar_query_time, id_password,
|
28
26
|
id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key,
|
29
27
|
id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement, id_multi_result,
|
30
|
-
id_from_code, id_from_errno, id_connection_options;
|
28
|
+
id_from_code, id_from_errno, id_connection_options, id_max_allowed_packet;
|
31
29
|
|
32
30
|
struct trilogy_ctx {
|
33
31
|
trilogy_conn_t conn;
|
@@ -96,12 +94,26 @@ static void trilogy_syserr_fail_str(int e, VALUE msg)
|
|
96
94
|
rb_raise(Trilogy_ConnectionRefusedError, "%" PRIsVALUE, msg);
|
97
95
|
} else if (e == ECONNRESET) {
|
98
96
|
rb_raise(Trilogy_ConnectionResetError, "%" PRIsVALUE, msg);
|
97
|
+
} else if (e == EPIPE) {
|
98
|
+
// Backwards compatibility: This error class makes no sense, but matches legacy behavior
|
99
|
+
rb_raise(Trilogy_QueryError, "%" PRIsVALUE ": TRILOGY_CLOSED_CONNECTION", msg);
|
99
100
|
} else {
|
100
101
|
VALUE exc = rb_funcall(Trilogy_SyscallError, id_from_errno, 2, INT2NUM(e), msg);
|
101
102
|
rb_exc_raise(exc);
|
102
103
|
}
|
103
104
|
}
|
104
105
|
|
106
|
+
static int trilogy_error_recoverable_p(int rc)
|
107
|
+
{
|
108
|
+
// TRILOGY_OPENSSL_ERR and TRILOGY_SYSERR (which can result from an SSL error) must shut down the socket, as further
|
109
|
+
// SSL calls would be invalid.
|
110
|
+
// TRILOGY_ERR, which represents an error message sent to us from the server, is recoverable.
|
111
|
+
// TRILOGY_MAX_PACKET_EXCEEDED is also recoverable as we do not send data when it occurs.
|
112
|
+
// For other exceptions we will also close the socket to prevent further use, as the connection is probably in an
|
113
|
+
// invalid state.
|
114
|
+
return rc == TRILOGY_ERR || rc == TRILOGY_MAX_PACKET_EXCEEDED;
|
115
|
+
}
|
116
|
+
|
105
117
|
NORETURN(static void handle_trilogy_error(struct trilogy_ctx *, int, const char *, ...));
|
106
118
|
static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *msg, ...)
|
107
119
|
{
|
@@ -110,10 +122,22 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms
|
|
110
122
|
VALUE rbmsg = rb_vsprintf(msg, args);
|
111
123
|
va_end(args);
|
112
124
|
|
125
|
+
if (!trilogy_error_recoverable_p(rc)) {
|
126
|
+
if (ctx->conn.socket != NULL) {
|
127
|
+
// trilogy_sock_shutdown may affect errno
|
128
|
+
int errno_was = errno;
|
129
|
+
trilogy_sock_shutdown(ctx->conn.socket);
|
130
|
+
errno = errno_was;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
113
134
|
switch (rc) {
|
114
135
|
case TRILOGY_SYSERR:
|
115
136
|
trilogy_syserr_fail_str(errno, rbmsg);
|
116
137
|
|
138
|
+
case TRILOGY_TIMEOUT:
|
139
|
+
rb_raise(Trilogy_TimeoutError, "%" PRIsVALUE, rbmsg);
|
140
|
+
|
117
141
|
case TRILOGY_ERR: {
|
118
142
|
VALUE message = rb_str_new(ctx->conn.error_message, ctx->conn.error_message_len);
|
119
143
|
VALUE exc = rb_funcall(Trilogy_ProtocolError, id_from_code, 2, message, INT2NUM(ctx->conn.error_code));
|
@@ -127,11 +151,6 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms
|
|
127
151
|
int err_reason = ERR_GET_REASON(ossl_error);
|
128
152
|
trilogy_syserr_fail_str(err_reason, rbmsg);
|
129
153
|
}
|
130
|
-
// We can't recover from OpenSSL level errors if there's
|
131
|
-
// an active connection.
|
132
|
-
if (ctx->conn.socket != NULL) {
|
133
|
-
trilogy_sock_shutdown(ctx->conn.socket);
|
134
|
-
}
|
135
154
|
rb_raise(Trilogy_SSLError, "%" PRIsVALUE ": SSL Error: %s", rbmsg, ERR_reason_error_string(ossl_error));
|
136
155
|
}
|
137
156
|
|
@@ -169,8 +188,9 @@ static int flush_writes(struct trilogy_ctx *ctx)
|
|
169
188
|
return rc;
|
170
189
|
}
|
171
190
|
|
172
|
-
|
173
|
-
|
191
|
+
rc = trilogy_sock_wait_write(ctx->conn.socket);
|
192
|
+
if (rc != TRILOGY_OK) {
|
193
|
+
return rc;
|
174
194
|
}
|
175
195
|
}
|
176
196
|
}
|
@@ -190,6 +210,21 @@ static double timeval_to_double(struct timeval tv)
|
|
190
210
|
return (double)tv.tv_sec + ((double)tv.tv_usec) / 1000000.0;
|
191
211
|
}
|
192
212
|
|
213
|
+
struct rb_trilogy_wait_args {
|
214
|
+
struct timeval *timeout;
|
215
|
+
int wait_flag;
|
216
|
+
int fd;
|
217
|
+
int rc;
|
218
|
+
};
|
219
|
+
|
220
|
+
static VALUE rb_trilogy_wait_protected(VALUE vargs) {
|
221
|
+
struct rb_trilogy_wait_args *args = (void *)vargs;
|
222
|
+
|
223
|
+
args->rc = rb_wait_for_single_fd(args->fd, args->wait_flag, args->timeout);
|
224
|
+
|
225
|
+
return Qnil;
|
226
|
+
}
|
227
|
+
|
193
228
|
static int _cb_ruby_wait(trilogy_sock_t *sock, trilogy_wait_t wait)
|
194
229
|
{
|
195
230
|
struct timeval *timeout = NULL;
|
@@ -219,11 +254,27 @@ static int _cb_ruby_wait(trilogy_sock_t *sock, trilogy_wait_t wait)
|
|
219
254
|
timeout = NULL;
|
220
255
|
}
|
221
256
|
|
222
|
-
|
223
|
-
|
257
|
+
struct rb_trilogy_wait_args args;
|
258
|
+
args.fd = trilogy_sock_fd(sock);
|
259
|
+
args.wait_flag = wait_flag;
|
260
|
+
args.timeout = timeout;
|
261
|
+
args.rc = 0;
|
262
|
+
|
263
|
+
int state = 0;
|
264
|
+
rb_protect(rb_trilogy_wait_protected, (VALUE)&args, &state);
|
265
|
+
if (state) {
|
266
|
+
trilogy_sock_shutdown(sock);
|
267
|
+
rb_jump_tag(state);
|
268
|
+
}
|
269
|
+
|
270
|
+
// rc here comes from rb_wait_for_single_fd which (similar to poll(3)) returns 0 to indicate that the call timed out
|
271
|
+
// or -1 to indicate a system error with errno set.
|
272
|
+
if (args.rc < 0)
|
224
273
|
return TRILOGY_SYSERR;
|
274
|
+
if (args.rc == 0)
|
275
|
+
return TRILOGY_TIMEOUT;
|
225
276
|
|
226
|
-
return
|
277
|
+
return TRILOGY_OK;
|
227
278
|
}
|
228
279
|
|
229
280
|
struct nogvl_sock_args {
|
@@ -275,8 +326,10 @@ escape the GVL on each wait operation without going through call_without_gvl */
|
|
275
326
|
return rc;
|
276
327
|
}
|
277
328
|
|
278
|
-
|
279
|
-
|
329
|
+
rc = trilogy_sock_wait(ctx->conn.socket, TRILOGY_WAIT_HANDSHAKE);
|
330
|
+
if (rc != TRILOGY_OK) {
|
331
|
+
return rc;
|
332
|
+
}
|
280
333
|
}
|
281
334
|
}
|
282
335
|
|
@@ -303,8 +356,9 @@ static void auth_switch(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake)
|
|
303
356
|
handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
|
304
357
|
}
|
305
358
|
|
306
|
-
|
307
|
-
|
359
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
360
|
+
if (rc != TRILOGY_OK) {
|
361
|
+
handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
|
308
362
|
}
|
309
363
|
}
|
310
364
|
}
|
@@ -356,8 +410,9 @@ static void authenticate(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake
|
|
356
410
|
handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
|
357
411
|
}
|
358
412
|
|
359
|
-
|
360
|
-
|
413
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
414
|
+
if (rc != TRILOGY_OK) {
|
415
|
+
handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
|
361
416
|
}
|
362
417
|
}
|
363
418
|
|
@@ -415,6 +470,11 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
415
470
|
connopt.keepalive_interval = NUM2USHORT(val);
|
416
471
|
}
|
417
472
|
|
473
|
+
if ((val = rb_hash_lookup(opts, ID2SYM(id_max_allowed_packet))) != Qnil) {
|
474
|
+
Check_Type(val, T_FIXNUM);
|
475
|
+
connopt.max_allowed_packet = NUM2SIZET(val);
|
476
|
+
}
|
477
|
+
|
418
478
|
if ((val = rb_hash_lookup(opts, ID2SYM(id_host))) != Qnil) {
|
419
479
|
Check_Type(val, T_STRING);
|
420
480
|
|
@@ -455,12 +515,12 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
455
515
|
connopt.flags |= TRILOGY_CAPABILITIES_FOUND_ROWS;
|
456
516
|
}
|
457
517
|
|
458
|
-
if (
|
518
|
+
if (rb_hash_aref(opts, ID2SYM(id_multi_result)) != Qfalse) {
|
459
519
|
connopt.flags |= TRILOGY_CAPABILITIES_MULTI_RESULTS;
|
460
520
|
}
|
461
521
|
|
462
522
|
if (RTEST(rb_hash_aref(opts, ID2SYM(id_multi_statement)))) {
|
463
|
-
connopt.flags |= TRILOGY_CAPABILITIES_MULTI_STATEMENTS
|
523
|
+
connopt.flags |= TRILOGY_CAPABILITIES_MULTI_STATEMENTS;
|
464
524
|
}
|
465
525
|
|
466
526
|
if ((val = rb_hash_aref(opts, ID2SYM(id_ssl_ca))) != Qnil) {
|
@@ -514,7 +574,7 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
514
574
|
}
|
515
575
|
|
516
576
|
int rc = try_connect(ctx, &handshake, &connopt);
|
517
|
-
if (rc ==
|
577
|
+
if (rc == TRILOGY_TIMEOUT) {
|
518
578
|
rb_raise(Trilogy_TimeoutError, "trilogy_connect_recv");
|
519
579
|
}
|
520
580
|
if (rc != TRILOGY_OK) {
|
@@ -561,8 +621,9 @@ static VALUE rb_trilogy_change_db(VALUE self, VALUE database)
|
|
561
621
|
handle_trilogy_error(ctx, rc, "trilogy_change_db_recv");
|
562
622
|
}
|
563
623
|
|
564
|
-
|
565
|
-
|
624
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
625
|
+
if (rc != TRILOGY_OK) {
|
626
|
+
handle_trilogy_error(ctx, rc, "trilogy_change_db_recv");
|
566
627
|
}
|
567
628
|
}
|
568
629
|
|
@@ -594,8 +655,9 @@ static VALUE rb_trilogy_set_server_option(VALUE self, VALUE option)
|
|
594
655
|
handle_trilogy_error(ctx, rc, "trilogy_set_option_recv");
|
595
656
|
}
|
596
657
|
|
597
|
-
|
598
|
-
|
658
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
659
|
+
if (rc != TRILOGY_OK) {
|
660
|
+
handle_trilogy_error(ctx, rc, "trilogy_set_option_recv");
|
599
661
|
}
|
600
662
|
}
|
601
663
|
|
@@ -667,8 +729,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
667
729
|
return read_query_error(args, rc, "trilogy_query_recv");
|
668
730
|
}
|
669
731
|
|
670
|
-
|
671
|
-
|
732
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
733
|
+
if (rc != TRILOGY_OK) {
|
734
|
+
handle_trilogy_error(ctx, rc, "trilogy_query_recv");
|
672
735
|
}
|
673
736
|
}
|
674
737
|
|
@@ -716,8 +779,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
716
779
|
return read_query_error(args, rc, "trilogy_read_column");
|
717
780
|
}
|
718
781
|
|
719
|
-
|
720
|
-
|
782
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
783
|
+
if (rc != TRILOGY_OK) {
|
784
|
+
return read_query_error(args, rc, "trilogy_read_column");
|
721
785
|
}
|
722
786
|
}
|
723
787
|
|
@@ -744,8 +808,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
744
808
|
int rc = trilogy_read_row(&ctx->conn, row_values);
|
745
809
|
|
746
810
|
if (rc == TRILOGY_AGAIN) {
|
747
|
-
|
748
|
-
|
811
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
812
|
+
if (rc != TRILOGY_OK) {
|
813
|
+
return read_query_error(args, rc, "trilogy_read_row");
|
749
814
|
}
|
750
815
|
continue;
|
751
816
|
}
|
@@ -871,8 +936,9 @@ static VALUE rb_trilogy_ping(VALUE self)
|
|
871
936
|
handle_trilogy_error(ctx, rc, "trilogy_ping_recv");
|
872
937
|
}
|
873
938
|
|
874
|
-
|
875
|
-
|
939
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
940
|
+
if (rc != TRILOGY_OK) {
|
941
|
+
handle_trilogy_error(ctx, rc, "trilogy_ping_recv");
|
876
942
|
}
|
877
943
|
}
|
878
944
|
|
@@ -931,6 +997,10 @@ static VALUE rb_trilogy_close(VALUE self)
|
|
931
997
|
}
|
932
998
|
}
|
933
999
|
|
1000
|
+
// We aren't checking or raising errors here (we need close to always close the socket and free the connection), so
|
1001
|
+
// we must clear any SSL errors left in the queue from a read/write.
|
1002
|
+
ERR_clear_error();
|
1003
|
+
|
934
1004
|
trilogy_free(&ctx->conn);
|
935
1005
|
|
936
1006
|
return Qnil;
|
@@ -1032,6 +1102,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1032
1102
|
|
1033
1103
|
rb_define_private_method(Trilogy, "_initialize", rb_trilogy_initialize, 3);
|
1034
1104
|
rb_define_method(Trilogy, "change_db", rb_trilogy_change_db, 1);
|
1105
|
+
rb_define_alias(Trilogy, "select_db", "change_db");
|
1035
1106
|
rb_define_method(Trilogy, "query", rb_trilogy_query, 1);
|
1036
1107
|
rb_define_method(Trilogy, "ping", rb_trilogy_ping, 0);
|
1037
1108
|
rb_define_method(Trilogy, "escape", rb_trilogy_escape, 1);
|
@@ -1114,6 +1185,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1114
1185
|
id_connect_timeout = rb_intern("connect_timeout");
|
1115
1186
|
id_read_timeout = rb_intern("read_timeout");
|
1116
1187
|
id_write_timeout = rb_intern("write_timeout");
|
1188
|
+
id_max_allowed_packet = rb_intern("max_allowed_packet");
|
1117
1189
|
id_keepalive_enabled = rb_intern("keepalive_enabled");
|
1118
1190
|
id_keepalive_idle = rb_intern("keepalive_idle");
|
1119
1191
|
id_keepalive_count = rb_intern("keepalive_count");
|
@@ -177,4 +177,122 @@ int trilogy_ping(trilogy_conn_t *conn);
|
|
177
177
|
*/
|
178
178
|
int trilogy_close(trilogy_conn_t *conn);
|
179
179
|
|
180
|
+
/* trilogy_stmt_prepare - Send a prepared statement prepare command to the server.
|
181
|
+
*
|
182
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
183
|
+
* undefined.
|
184
|
+
* stmt - A pointer to the buffer containing the statement to prepare.
|
185
|
+
* stmt_len - The length of the data buffer.
|
186
|
+
* stmt_out - A pointer to a pre-allocated trilogy_stmt_t.
|
187
|
+
*
|
188
|
+
* Return values:
|
189
|
+
* TRILOGY_OK - The prepare command was successfully sent to the server.
|
190
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
191
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
192
|
+
* packet.
|
193
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
194
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
195
|
+
*/
|
196
|
+
int trilogy_stmt_prepare(trilogy_conn_t *conn, const char *stmt, size_t stmt_len, trilogy_stmt_t *stmt_out);
|
197
|
+
|
198
|
+
/* trilogy_stmt_execute - Send a prepared statement execute command to the server.
|
199
|
+
*
|
200
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
201
|
+
* undefined.
|
202
|
+
* stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
|
203
|
+
* requesting to execute.
|
204
|
+
* flags - The flags (TRILOGY_STMT_FLAGS_t) to be used with this execute command packet.
|
205
|
+
* binds - Pointer to an array of trilogy_binary_value_t's. The array size should
|
206
|
+
* match that of `trilogy_stmt_t.column_count`.
|
207
|
+
* column_count_out - Out parameter; A pointer to a pre-allocated uint64_t. Represents the
|
208
|
+
* number of columns in the response.
|
209
|
+
*
|
210
|
+
* Return values:
|
211
|
+
* TRILOGY_OK - The execute command was successfully sent to the server.
|
212
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
213
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
214
|
+
* packet.
|
215
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
216
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
217
|
+
*/
|
218
|
+
int trilogy_stmt_execute(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint8_t flags, trilogy_binary_value_t *binds,
|
219
|
+
uint64_t *column_count_out);
|
220
|
+
|
221
|
+
/* trilogy_stmt_bind_data - Send a prepared statement bind long data command to the server.
|
222
|
+
*
|
223
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
224
|
+
* undefined.
|
225
|
+
* stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement for which
|
226
|
+
* to bind the supplied parameter data to.
|
227
|
+
* param_num - The parameter index for which the supplied data should be bound to.
|
228
|
+
* data - A pointer to the buffer containing the data to be bound.
|
229
|
+
* data_len - The length of the data buffer.
|
230
|
+
*
|
231
|
+
* Return values:
|
232
|
+
* TRILOGY_OK - The bind data command was successfully sent to the server.
|
233
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
234
|
+
*/
|
235
|
+
int trilogy_stmt_bind_data(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint16_t param_num, uint8_t *data,
|
236
|
+
size_t data_len);
|
237
|
+
|
238
|
+
/* trilogy_stmt_read_full_row - Read a row from the prepared statement execute response.
|
239
|
+
*
|
240
|
+
* This should only be called after a sucessful call to trilogy_stmt_execute.
|
241
|
+
* You should continue calling this until TRILOGY_EOF is returned. Denoting the end
|
242
|
+
* of the result set.
|
243
|
+
*
|
244
|
+
* conn - A pre-initialized trilogy_conn_t pointer. It can also be connected but
|
245
|
+
* a disconnected trilogy_conn_t will also return TRILOGY_OK.
|
246
|
+
* stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
|
247
|
+
* requesting to execute.
|
248
|
+
* columns - The list of columns from the prepared statement.
|
249
|
+
* column_count - The number of columns in prepared statement.
|
250
|
+
* values_out - Out parameter; A pointer to a pre-allocated array of
|
251
|
+
* trilogy_binary_value_t's. There must be enough space to fit all of the
|
252
|
+
* values. This can be computed with:
|
253
|
+
* `(sizeof(trilogy_binary_value_t) * column_count)`.
|
254
|
+
*
|
255
|
+
* Return values:
|
256
|
+
* TRILOGY_OK - The prepare command response successfully read from
|
257
|
+
* the server.
|
258
|
+
* TRILOGY_EOF - There are no more rows to read from the result set.
|
259
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
260
|
+
* TRILOGY_PROTOCOL_VIOLATION - Invalid length parsed for a TIME/DATETIME/TIMESTAMP value.
|
261
|
+
* TRILOGY_UNKNOWN_TYPE - An unsupported or unknown MySQL type was seen.
|
262
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
263
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
264
|
+
*/
|
265
|
+
int trilogy_stmt_read_full_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
|
266
|
+
trilogy_binary_value_t *values_out);
|
267
|
+
|
268
|
+
/* trilogy_stmt_reset - Send a prepared statement reset command to the server.
|
269
|
+
*
|
270
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
271
|
+
* undefined.
|
272
|
+
* stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
|
273
|
+
* requesting to reset.
|
274
|
+
*
|
275
|
+
* Return values:
|
276
|
+
* TRILOGY_OK - The reset command was successfully sent to the server.
|
277
|
+
* TRILOGY_UNEXPECTED_PACKET - The response packet wasn't what was expected.
|
278
|
+
* TRILOGY_PROTOCOL_VIOLATION - An error occurred while processing a network
|
279
|
+
* packet.
|
280
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
281
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
282
|
+
*/
|
283
|
+
int trilogy_stmt_reset(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
|
284
|
+
|
285
|
+
/* trilogy_stmt_close_send - Send a prepared statement close command to the server.
|
286
|
+
*
|
287
|
+
* conn - A connected trilogy_conn_t pointer. Using a disconnected trilogy_conn_t is
|
288
|
+
* undefined.
|
289
|
+
* stmt - Pointer to a valid trilogy_stmt_t, representing the prepared statement you're
|
290
|
+
* requesting to close.
|
291
|
+
*
|
292
|
+
* Return values:
|
293
|
+
* TRILOGY_OK - The close command was successfully sent to the server.
|
294
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
295
|
+
*/
|
296
|
+
int trilogy_stmt_close(trilogy_conn_t *conn, trilogy_stmt_t *stmt);
|
297
|
+
|
180
298
|
#endif
|
@@ -16,6 +16,8 @@
|
|
16
16
|
typedef struct {
|
17
17
|
trilogy_buffer_t *buffer;
|
18
18
|
size_t header_offset;
|
19
|
+
size_t packet_length;
|
20
|
+
size_t packet_max_length;
|
19
21
|
uint32_t fragment_length;
|
20
22
|
uint8_t seq;
|
21
23
|
} trilogy_builder_t;
|
@@ -54,6 +56,8 @@ void trilogy_builder_finalize(trilogy_builder_t *builder);
|
|
54
56
|
* Return values:
|
55
57
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
56
58
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
59
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
60
|
+
* packet size.
|
57
61
|
*/
|
58
62
|
int trilogy_builder_write_uint8(trilogy_builder_t *builder, uint8_t val);
|
59
63
|
|
@@ -66,6 +70,8 @@ int trilogy_builder_write_uint8(trilogy_builder_t *builder, uint8_t val);
|
|
66
70
|
* Return values:
|
67
71
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
68
72
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
73
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
74
|
+
* packet size.
|
69
75
|
*/
|
70
76
|
int trilogy_builder_write_uint16(trilogy_builder_t *builder, uint16_t val);
|
71
77
|
|
@@ -78,6 +84,8 @@ int trilogy_builder_write_uint16(trilogy_builder_t *builder, uint16_t val);
|
|
78
84
|
* Return values:
|
79
85
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
80
86
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
87
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
88
|
+
* packet size.
|
81
89
|
*/
|
82
90
|
int trilogy_builder_write_uint24(trilogy_builder_t *builder, uint32_t val);
|
83
91
|
|
@@ -90,6 +98,8 @@ int trilogy_builder_write_uint24(trilogy_builder_t *builder, uint32_t val);
|
|
90
98
|
* Return values:
|
91
99
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
92
100
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
101
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
102
|
+
* packet size.
|
93
103
|
*/
|
94
104
|
int trilogy_builder_write_uint32(trilogy_builder_t *builder, uint32_t val);
|
95
105
|
|
@@ -102,9 +112,37 @@ int trilogy_builder_write_uint32(trilogy_builder_t *builder, uint32_t val);
|
|
102
112
|
* Return values:
|
103
113
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
104
114
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
115
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
116
|
+
* packet size.
|
105
117
|
*/
|
106
118
|
int trilogy_builder_write_uint64(trilogy_builder_t *builder, uint64_t val);
|
107
119
|
|
120
|
+
/* trilogy_builder_write_float - Append a float to the packet buffer.
|
121
|
+
*
|
122
|
+
* builder - A pre-initialized trilogy_builder_t pointer
|
123
|
+
* val - The value to append to the buffer
|
124
|
+
*
|
125
|
+
* Return values:
|
126
|
+
* TRILOGY_OK - The value was appended to the packet buffer.
|
127
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
128
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
129
|
+
* packet size.
|
130
|
+
*/
|
131
|
+
int trilogy_builder_write_float(trilogy_builder_t *builder, float val);
|
132
|
+
|
133
|
+
/* trilogy_builder_write_double - Append a double to the packet buffer.
|
134
|
+
*
|
135
|
+
* builder - A pre-initialized trilogy_builder_t pointer
|
136
|
+
* val - The value to append to the buffer
|
137
|
+
*
|
138
|
+
* Return values:
|
139
|
+
* TRILOGY_OK - The value was appended to the packet buffer.
|
140
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
141
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
142
|
+
* packet size.
|
143
|
+
*/
|
144
|
+
int trilogy_builder_write_double(trilogy_builder_t *builder, double val);
|
145
|
+
|
108
146
|
/* trilogy_builder_write_lenenc - Append a length-encoded integer to the packet
|
109
147
|
* buffer.
|
110
148
|
*
|
@@ -117,6 +155,8 @@ int trilogy_builder_write_uint64(trilogy_builder_t *builder, uint64_t val);
|
|
117
155
|
* Return values:
|
118
156
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
119
157
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
158
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
159
|
+
* packet size.
|
120
160
|
*/
|
121
161
|
int trilogy_builder_write_lenenc(trilogy_builder_t *builder, uint64_t val);
|
122
162
|
|
@@ -130,6 +170,8 @@ int trilogy_builder_write_lenenc(trilogy_builder_t *builder, uint64_t val);
|
|
130
170
|
* Return values:
|
131
171
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
132
172
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
173
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
174
|
+
* packet size.
|
133
175
|
*/
|
134
176
|
int trilogy_builder_write_buffer(trilogy_builder_t *builder, const void *data, size_t len);
|
135
177
|
|
@@ -144,6 +186,8 @@ int trilogy_builder_write_buffer(trilogy_builder_t *builder, const void *data, s
|
|
144
186
|
* Return values:
|
145
187
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
146
188
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
189
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
190
|
+
* packet size.
|
147
191
|
*/
|
148
192
|
int trilogy_builder_write_lenenc_buffer(trilogy_builder_t *builder, const void *data, size_t len);
|
149
193
|
|
@@ -155,7 +199,23 @@ int trilogy_builder_write_lenenc_buffer(trilogy_builder_t *builder, const void *
|
|
155
199
|
* Return values:
|
156
200
|
* TRILOGY_OK - The value was appended to the packet buffer.
|
157
201
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
202
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - Appending this value would exceed the maximum
|
203
|
+
* packet size.
|
158
204
|
*/
|
159
205
|
int trilogy_builder_write_string(trilogy_builder_t *builder, const char *data);
|
160
206
|
|
207
|
+
/* trilogy_builder_set_max_packet_length - Set the maximum packet length for
|
208
|
+
* the builder. Writing data to the builder that would cause the packet length
|
209
|
+
* to exceed this value will cause the builder to error.
|
210
|
+
*
|
211
|
+
* builder - A pre-initialized trilogy_builder_t pointer
|
212
|
+
* max_length - The new maximum packet length to set
|
213
|
+
*
|
214
|
+
* Return values:
|
215
|
+
* TRILOGY_OK - The maximum packet length was set.
|
216
|
+
* TRILOGY_MAX_PACKET_EXCEEDED - The current packet length is already
|
217
|
+
* larger than the requested maximum.
|
218
|
+
*/
|
219
|
+
int trilogy_builder_set_max_packet_length(trilogy_builder_t *builder, size_t max_length);
|
220
|
+
|
161
221
|
#endif
|