trilogy 2.4.1 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +110 -33
- 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 +266 -2
- 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 -244
- 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,
|
@@ -26,8 +24,8 @@ static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows,
|
|
26
24
|
id_write_timeout, id_keepalive_enabled, id_keepalive_idle, id_keepalive_interval, id_keepalive_count,
|
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
|
-
id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement,
|
30
|
-
id_from_code, id_from_errno, id_connection_options;
|
27
|
+
id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement, id_multi_result,
|
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,6 +515,10 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
455
515
|
connopt.flags |= TRILOGY_CAPABILITIES_FOUND_ROWS;
|
456
516
|
}
|
457
517
|
|
518
|
+
if (rb_hash_aref(opts, ID2SYM(id_multi_result)) != Qfalse) {
|
519
|
+
connopt.flags |= TRILOGY_CAPABILITIES_MULTI_RESULTS;
|
520
|
+
}
|
521
|
+
|
458
522
|
if (RTEST(rb_hash_aref(opts, ID2SYM(id_multi_statement)))) {
|
459
523
|
connopt.flags |= TRILOGY_CAPABILITIES_MULTI_STATEMENTS;
|
460
524
|
}
|
@@ -510,7 +574,7 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
510
574
|
}
|
511
575
|
|
512
576
|
int rc = try_connect(ctx, &handshake, &connopt);
|
513
|
-
if (rc ==
|
577
|
+
if (rc == TRILOGY_TIMEOUT) {
|
514
578
|
rb_raise(Trilogy_TimeoutError, "trilogy_connect_recv");
|
515
579
|
}
|
516
580
|
if (rc != TRILOGY_OK) {
|
@@ -557,8 +621,9 @@ static VALUE rb_trilogy_change_db(VALUE self, VALUE database)
|
|
557
621
|
handle_trilogy_error(ctx, rc, "trilogy_change_db_recv");
|
558
622
|
}
|
559
623
|
|
560
|
-
|
561
|
-
|
624
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
625
|
+
if (rc != TRILOGY_OK) {
|
626
|
+
handle_trilogy_error(ctx, rc, "trilogy_change_db_recv");
|
562
627
|
}
|
563
628
|
}
|
564
629
|
|
@@ -590,8 +655,9 @@ static VALUE rb_trilogy_set_server_option(VALUE self, VALUE option)
|
|
590
655
|
handle_trilogy_error(ctx, rc, "trilogy_set_option_recv");
|
591
656
|
}
|
592
657
|
|
593
|
-
|
594
|
-
|
658
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
659
|
+
if (rc != TRILOGY_OK) {
|
660
|
+
handle_trilogy_error(ctx, rc, "trilogy_set_option_recv");
|
595
661
|
}
|
596
662
|
}
|
597
663
|
|
@@ -663,8 +729,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
663
729
|
return read_query_error(args, rc, "trilogy_query_recv");
|
664
730
|
}
|
665
731
|
|
666
|
-
|
667
|
-
|
732
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
733
|
+
if (rc != TRILOGY_OK) {
|
734
|
+
handle_trilogy_error(ctx, rc, "trilogy_query_recv");
|
668
735
|
}
|
669
736
|
}
|
670
737
|
|
@@ -712,8 +779,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
712
779
|
return read_query_error(args, rc, "trilogy_read_column");
|
713
780
|
}
|
714
781
|
|
715
|
-
|
716
|
-
|
782
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
783
|
+
if (rc != TRILOGY_OK) {
|
784
|
+
return read_query_error(args, rc, "trilogy_read_column");
|
717
785
|
}
|
718
786
|
}
|
719
787
|
|
@@ -740,8 +808,9 @@ static VALUE read_query_response(VALUE vargs)
|
|
740
808
|
int rc = trilogy_read_row(&ctx->conn, row_values);
|
741
809
|
|
742
810
|
if (rc == TRILOGY_AGAIN) {
|
743
|
-
|
744
|
-
|
811
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
812
|
+
if (rc != TRILOGY_OK) {
|
813
|
+
return read_query_error(args, rc, "trilogy_read_row");
|
745
814
|
}
|
746
815
|
continue;
|
747
816
|
}
|
@@ -867,8 +936,9 @@ static VALUE rb_trilogy_ping(VALUE self)
|
|
867
936
|
handle_trilogy_error(ctx, rc, "trilogy_ping_recv");
|
868
937
|
}
|
869
938
|
|
870
|
-
|
871
|
-
|
939
|
+
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
940
|
+
if (rc != TRILOGY_OK) {
|
941
|
+
handle_trilogy_error(ctx, rc, "trilogy_ping_recv");
|
872
942
|
}
|
873
943
|
}
|
874
944
|
|
@@ -927,6 +997,10 @@ static VALUE rb_trilogy_close(VALUE self)
|
|
927
997
|
}
|
928
998
|
}
|
929
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
|
+
|
930
1004
|
trilogy_free(&ctx->conn);
|
931
1005
|
|
932
1006
|
return Qnil;
|
@@ -1028,6 +1102,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1028
1102
|
|
1029
1103
|
rb_define_private_method(Trilogy, "_initialize", rb_trilogy_initialize, 3);
|
1030
1104
|
rb_define_method(Trilogy, "change_db", rb_trilogy_change_db, 1);
|
1105
|
+
rb_define_alias(Trilogy, "select_db", "change_db");
|
1031
1106
|
rb_define_method(Trilogy, "query", rb_trilogy_query, 1);
|
1032
1107
|
rb_define_method(Trilogy, "ping", rb_trilogy_ping, 0);
|
1033
1108
|
rb_define_method(Trilogy, "escape", rb_trilogy_escape, 1);
|
@@ -1110,6 +1185,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1110
1185
|
id_connect_timeout = rb_intern("connect_timeout");
|
1111
1186
|
id_read_timeout = rb_intern("read_timeout");
|
1112
1187
|
id_write_timeout = rb_intern("write_timeout");
|
1188
|
+
id_max_allowed_packet = rb_intern("max_allowed_packet");
|
1113
1189
|
id_keepalive_enabled = rb_intern("keepalive_enabled");
|
1114
1190
|
id_keepalive_idle = rb_intern("keepalive_idle");
|
1115
1191
|
id_keepalive_count = rb_intern("keepalive_count");
|
@@ -1127,6 +1203,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1127
1203
|
id_tls_min_version = rb_intern("tls_min_version");
|
1128
1204
|
id_tls_max_version = rb_intern("tls_max_version");
|
1129
1205
|
id_multi_statement = rb_intern("multi_statement");
|
1206
|
+
id_multi_result = rb_intern("multi_result");
|
1130
1207
|
id_from_code = rb_intern("from_code");
|
1131
1208
|
id_from_errno = rb_intern("from_errno");
|
1132
1209
|
id_ivar_affected_rows = rb_intern("@affected_rows");
|
@@ -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
|