trilogy 2.9.0 → 2.10.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 +1 -1
- data/ext/trilogy-ruby/cext.c +195 -3
- data/ext/trilogy-ruby/extconf.rb +2 -2
- data/ext/trilogy-ruby/inc/trilogy/buffer.h +13 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +9 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +2 -1
- data/ext/trilogy-ruby/src/buffer.c +22 -3
- data/ext/trilogy-ruby/src/client.c +59 -39
- data/lib/trilogy/encoding.rb +2 -0
- data/lib/trilogy/result.rb +2 -0
- data/lib/trilogy/version.rb +1 -1
- data/trilogy.gemspec +4 -0
- metadata +18 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e84050730e47a4bd826b9c15b226d0f825a46df8849c3c4a89c01011e27fb6c
|
|
4
|
+
data.tar.gz: eddfedb0481b09220bb95f1de423b473aa78f2ad8058de692b85c52bba1c0480
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a1fa8ecb46aa1b1595c6d6f1a20b5dd4267452d5c59b0571fe31c4cc854907aeb8f8ad1496099e53ba83b29c0594f88dc6f4f45586ede8b1ad53d70b0ff2a774
|
|
7
|
+
data.tar.gz: a18b393f8b035c8ee3315d42b23d8a46e1597f4ccbac0347acab0161a8c041572eeb8a13d4d323c97a63040f9f18baa04e0742c73e65df33d5763fdd27b6c581
|
data/README.md
CHANGED
data/ext/trilogy-ruby/cext.c
CHANGED
|
@@ -15,6 +15,149 @@
|
|
|
15
15
|
|
|
16
16
|
#include "trilogy-ruby.h"
|
|
17
17
|
|
|
18
|
+
typedef struct _buffer_pool_entry_struct {
|
|
19
|
+
size_t cap;
|
|
20
|
+
uint8_t *buff;
|
|
21
|
+
} buffer_pool_entry;
|
|
22
|
+
|
|
23
|
+
typedef struct _buffer_pool_struct {
|
|
24
|
+
size_t capa;
|
|
25
|
+
size_t len;
|
|
26
|
+
buffer_pool_entry *entries;
|
|
27
|
+
} buffer_pool;
|
|
28
|
+
|
|
29
|
+
#ifndef HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY
|
|
30
|
+
static VALUE _global_buffer_pool = Qnil;
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#define BUFFER_POOL_MAX_SIZE 8
|
|
34
|
+
|
|
35
|
+
static void buffer_pool_free(void *data)
|
|
36
|
+
{
|
|
37
|
+
#ifndef HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY
|
|
38
|
+
_global_buffer_pool = Qnil;
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
buffer_pool *pool = (buffer_pool *)data;
|
|
42
|
+
if (pool->capa) {
|
|
43
|
+
for (size_t index = 0; index < pool->len; index++) {
|
|
44
|
+
// NB: buff was allocated by trilogy/buffer.h using raw `malloc`
|
|
45
|
+
// hence we must use raw `free`.
|
|
46
|
+
free(pool->entries[index].buff);
|
|
47
|
+
}
|
|
48
|
+
xfree(pool->entries);
|
|
49
|
+
}
|
|
50
|
+
xfree(pool);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static size_t buffer_pool_memsize(const void *data)
|
|
54
|
+
{
|
|
55
|
+
const buffer_pool *pool = (const buffer_pool *)data;
|
|
56
|
+
|
|
57
|
+
size_t memsize = sizeof(buffer_pool) + sizeof(buffer_pool_entry) * pool->capa;
|
|
58
|
+
|
|
59
|
+
if (pool->capa) {
|
|
60
|
+
for (size_t index = 0; index < pool->len; index++) {
|
|
61
|
+
memsize += pool->entries[index].cap;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return memsize;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static const rb_data_type_t buffer_pool_type = {
|
|
69
|
+
.wrap_struct_name = "trilogy/buffer_pool",
|
|
70
|
+
.function = {
|
|
71
|
+
.dmark = NULL,
|
|
72
|
+
.dfree = buffer_pool_free,
|
|
73
|
+
.dsize = buffer_pool_memsize,
|
|
74
|
+
},
|
|
75
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
static VALUE create_rb_buffer_pool(void)
|
|
79
|
+
{
|
|
80
|
+
buffer_pool *pool;
|
|
81
|
+
return TypedData_Make_Struct(Qfalse, buffer_pool, &buffer_pool_type, pool);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#ifdef HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY
|
|
85
|
+
#include <ruby/ractor.h>
|
|
86
|
+
static rb_ractor_local_key_t buffer_pool_key;
|
|
87
|
+
|
|
88
|
+
static VALUE get_rb_buffer_pool(void)
|
|
89
|
+
{
|
|
90
|
+
VALUE pool;
|
|
91
|
+
if (!rb_ractor_local_storage_value_lookup(buffer_pool_key, &pool)) {
|
|
92
|
+
pool = create_rb_buffer_pool();
|
|
93
|
+
rb_ractor_local_storage_value_set(buffer_pool_key, pool);
|
|
94
|
+
}
|
|
95
|
+
return pool;
|
|
96
|
+
}
|
|
97
|
+
#else
|
|
98
|
+
static VALUE get_rb_buffer_pool(void)
|
|
99
|
+
{
|
|
100
|
+
if (NIL_P(_global_buffer_pool)) {
|
|
101
|
+
_global_buffer_pool = create_rb_buffer_pool();
|
|
102
|
+
}
|
|
103
|
+
return _global_buffer_pool;
|
|
104
|
+
}
|
|
105
|
+
#endif
|
|
106
|
+
|
|
107
|
+
static inline buffer_pool *get_buffer_pool(void)
|
|
108
|
+
{
|
|
109
|
+
buffer_pool *pool;
|
|
110
|
+
VALUE rb_pool = get_rb_buffer_pool();
|
|
111
|
+
if (NIL_P(rb_pool)) {
|
|
112
|
+
return NULL;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
TypedData_Get_Struct(rb_pool, buffer_pool, &buffer_pool_type, pool);
|
|
116
|
+
return pool;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static void buffer_checkout(trilogy_buffer_t *buffer, size_t initial_capacity)
|
|
120
|
+
{
|
|
121
|
+
buffer_pool * pool = get_buffer_pool();
|
|
122
|
+
if (pool->len) {
|
|
123
|
+
pool->len--;
|
|
124
|
+
buffer->buff = pool->entries[pool->len].buff;
|
|
125
|
+
buffer->cap = pool->entries[pool->len].cap;
|
|
126
|
+
} else {
|
|
127
|
+
buffer->buff = RB_ALLOC_N(uint8_t, initial_capacity);
|
|
128
|
+
buffer->cap = initial_capacity;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static bool buffer_checkin(trilogy_buffer_t *buffer)
|
|
133
|
+
{
|
|
134
|
+
buffer_pool * pool = get_buffer_pool();
|
|
135
|
+
|
|
136
|
+
if (pool->len >= BUFFER_POOL_MAX_SIZE) {
|
|
137
|
+
xfree(buffer->buff);
|
|
138
|
+
buffer->buff = NULL;
|
|
139
|
+
buffer->cap = 0;
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!pool->capa) {
|
|
144
|
+
pool->entries = RB_ALLOC_N(buffer_pool_entry, 16);
|
|
145
|
+
pool->capa = 16;
|
|
146
|
+
} else if (pool->len >= pool->capa) {
|
|
147
|
+
pool->capa *= 2;
|
|
148
|
+
RB_REALLOC_N(pool->entries, buffer_pool_entry, pool->capa);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
pool->entries[pool->len].buff = buffer->buff;
|
|
152
|
+
pool->entries[pool->len].cap = buffer->cap;
|
|
153
|
+
pool->len++;
|
|
154
|
+
|
|
155
|
+
buffer->buff = NULL;
|
|
156
|
+
buffer->cap = 0;
|
|
157
|
+
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
|
|
18
161
|
VALUE Trilogy_CastError;
|
|
19
162
|
static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLError, Trilogy_QueryError,
|
|
20
163
|
Trilogy_ConnectionClosedError,
|
|
@@ -34,6 +177,20 @@ struct trilogy_ctx {
|
|
|
34
177
|
VALUE encoding;
|
|
35
178
|
};
|
|
36
179
|
|
|
180
|
+
static void rb_trilogy_acquire_buffer(struct trilogy_ctx *ctx)
|
|
181
|
+
{
|
|
182
|
+
if (!ctx->conn.packet_buffer.buff) {
|
|
183
|
+
buffer_checkout(&ctx->conn.packet_buffer, TRILOGY_DEFAULT_BUF_SIZE);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
static void rb_trilogy_release_buffer(struct trilogy_ctx *ctx)
|
|
188
|
+
{
|
|
189
|
+
if (ctx->conn.packet_buffer.buff) {
|
|
190
|
+
buffer_checkin(&ctx->conn.packet_buffer);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
37
194
|
static void mark_trilogy(void *ptr)
|
|
38
195
|
{
|
|
39
196
|
struct trilogy_ctx *ctx = ptr;
|
|
@@ -43,6 +200,7 @@ static void mark_trilogy(void *ptr)
|
|
|
43
200
|
static void free_trilogy(void *ptr)
|
|
44
201
|
{
|
|
45
202
|
struct trilogy_ctx *ctx = ptr;
|
|
203
|
+
|
|
46
204
|
trilogy_free(&ctx->conn);
|
|
47
205
|
xfree(ptr);
|
|
48
206
|
}
|
|
@@ -116,6 +274,8 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms
|
|
|
116
274
|
VALUE rbmsg = rb_vsprintf(msg, args);
|
|
117
275
|
va_end(args);
|
|
118
276
|
|
|
277
|
+
rb_trilogy_release_buffer(ctx);
|
|
278
|
+
|
|
119
279
|
if (!trilogy_error_recoverable_p(rc)) {
|
|
120
280
|
if (ctx->conn.socket != NULL) {
|
|
121
281
|
// trilogy_sock_shutdown may affect errno
|
|
@@ -178,7 +338,7 @@ static VALUE allocate_trilogy(VALUE klass)
|
|
|
178
338
|
|
|
179
339
|
ctx->query_flags = TRILOGY_FLAGS_DEFAULT;
|
|
180
340
|
|
|
181
|
-
if (
|
|
341
|
+
if (trilogy_init_no_buffer(&ctx->conn) < 0) {
|
|
182
342
|
VALUE rbmsg = rb_str_new("trilogy_init", 13);
|
|
183
343
|
trilogy_syserr_fail_str(errno, rbmsg);
|
|
184
344
|
}
|
|
@@ -602,6 +762,8 @@ static VALUE rb_trilogy_connect(VALUE self, VALUE encoding, VALUE charset, VALUE
|
|
|
602
762
|
connopt.tls_max_version = NUM2INT(val);
|
|
603
763
|
}
|
|
604
764
|
|
|
765
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
766
|
+
|
|
605
767
|
int rc = try_connect(ctx, &handshake, &connopt);
|
|
606
768
|
if (rc != TRILOGY_OK) {
|
|
607
769
|
if (connopt.path) {
|
|
@@ -617,6 +779,8 @@ static VALUE rb_trilogy_connect(VALUE self, VALUE encoding, VALUE charset, VALUE
|
|
|
617
779
|
|
|
618
780
|
authenticate(ctx, &handshake, connopt.ssl_mode);
|
|
619
781
|
|
|
782
|
+
rb_trilogy_release_buffer(ctx);
|
|
783
|
+
|
|
620
784
|
return Qnil;
|
|
621
785
|
}
|
|
622
786
|
|
|
@@ -626,6 +790,8 @@ static VALUE rb_trilogy_change_db(VALUE self, VALUE database)
|
|
|
626
790
|
|
|
627
791
|
StringValue(database);
|
|
628
792
|
|
|
793
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
794
|
+
|
|
629
795
|
int rc = trilogy_change_db_send(&ctx->conn, RSTRING_PTR(database), RSTRING_LEN(database));
|
|
630
796
|
|
|
631
797
|
if (rc == TRILOGY_AGAIN) {
|
|
@@ -653,6 +819,8 @@ static VALUE rb_trilogy_change_db(VALUE self, VALUE database)
|
|
|
653
819
|
}
|
|
654
820
|
}
|
|
655
821
|
|
|
822
|
+
rb_trilogy_release_buffer(ctx);
|
|
823
|
+
|
|
656
824
|
return Qtrue;
|
|
657
825
|
}
|
|
658
826
|
|
|
@@ -660,6 +828,8 @@ static VALUE rb_trilogy_set_server_option(VALUE self, VALUE option)
|
|
|
660
828
|
{
|
|
661
829
|
struct trilogy_ctx *ctx = get_open_ctx(self);
|
|
662
830
|
|
|
831
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
832
|
+
|
|
663
833
|
int rc = trilogy_set_option_send(&ctx->conn, NUM2INT(option));
|
|
664
834
|
|
|
665
835
|
if (rc == TRILOGY_AGAIN) {
|
|
@@ -687,6 +857,8 @@ static VALUE rb_trilogy_set_server_option(VALUE self, VALUE option)
|
|
|
687
857
|
}
|
|
688
858
|
}
|
|
689
859
|
|
|
860
|
+
rb_trilogy_release_buffer(ctx);
|
|
861
|
+
|
|
690
862
|
return Qtrue;
|
|
691
863
|
}
|
|
692
864
|
|
|
@@ -892,6 +1064,10 @@ static VALUE execute_read_query_response(struct trilogy_ctx *ctx)
|
|
|
892
1064
|
handle_trilogy_error(ctx, args.rc, args.msg);
|
|
893
1065
|
}
|
|
894
1066
|
|
|
1067
|
+
if (!(ctx->conn.server_status & TRILOGY_SERVER_STATUS_MORE_RESULTS_EXISTS)) {
|
|
1068
|
+
rb_trilogy_release_buffer(ctx);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
895
1071
|
return result;
|
|
896
1072
|
}
|
|
897
1073
|
|
|
@@ -924,6 +1100,8 @@ static VALUE rb_trilogy_query(VALUE self, VALUE query)
|
|
|
924
1100
|
StringValue(query);
|
|
925
1101
|
query = rb_str_export_to_enc(query, rb_to_encoding(ctx->encoding));
|
|
926
1102
|
|
|
1103
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
1104
|
+
|
|
927
1105
|
int rc = trilogy_query_send(&ctx->conn, RSTRING_PTR(query), RSTRING_LEN(query));
|
|
928
1106
|
|
|
929
1107
|
if (rc == TRILOGY_AGAIN) {
|
|
@@ -941,6 +1119,8 @@ static VALUE rb_trilogy_ping(VALUE self)
|
|
|
941
1119
|
{
|
|
942
1120
|
struct trilogy_ctx *ctx = get_open_ctx(self);
|
|
943
1121
|
|
|
1122
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
1123
|
+
|
|
944
1124
|
int rc = trilogy_ping_send(&ctx->conn);
|
|
945
1125
|
|
|
946
1126
|
if (rc == TRILOGY_AGAIN) {
|
|
@@ -968,6 +1148,7 @@ static VALUE rb_trilogy_ping(VALUE self)
|
|
|
968
1148
|
}
|
|
969
1149
|
}
|
|
970
1150
|
|
|
1151
|
+
rb_trilogy_release_buffer(ctx);
|
|
971
1152
|
return Qtrue;
|
|
972
1153
|
}
|
|
973
1154
|
|
|
@@ -985,13 +1166,19 @@ static VALUE rb_trilogy_escape(VALUE self, VALUE str)
|
|
|
985
1166
|
const char *escaped_str;
|
|
986
1167
|
size_t escaped_len;
|
|
987
1168
|
|
|
1169
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
1170
|
+
|
|
988
1171
|
int rc = trilogy_escape(&ctx->conn, RSTRING_PTR(str), RSTRING_LEN(str), &escaped_str, &escaped_len);
|
|
989
1172
|
|
|
990
1173
|
if (rc < 0) {
|
|
991
1174
|
handle_trilogy_error(ctx, rc, "trilogy_escape");
|
|
992
1175
|
}
|
|
993
1176
|
|
|
994
|
-
|
|
1177
|
+
VALUE escaped_string = rb_enc_str_new(escaped_str, escaped_len, str_enc);
|
|
1178
|
+
|
|
1179
|
+
rb_trilogy_release_buffer(ctx);
|
|
1180
|
+
|
|
1181
|
+
return escaped_string;
|
|
995
1182
|
}
|
|
996
1183
|
|
|
997
1184
|
static VALUE rb_trilogy_close(VALUE self)
|
|
@@ -1002,6 +1189,8 @@ static VALUE rb_trilogy_close(VALUE self)
|
|
|
1002
1189
|
return Qnil;
|
|
1003
1190
|
}
|
|
1004
1191
|
|
|
1192
|
+
rb_trilogy_acquire_buffer(ctx);
|
|
1193
|
+
|
|
1005
1194
|
int rc = trilogy_close_send(&ctx->conn);
|
|
1006
1195
|
|
|
1007
1196
|
if (rc == TRILOGY_AGAIN) {
|
|
@@ -1027,6 +1216,8 @@ static VALUE rb_trilogy_close(VALUE self)
|
|
|
1027
1216
|
// we must clear any SSL errors left in the queue from a read/write.
|
|
1028
1217
|
ERR_clear_error();
|
|
1029
1218
|
|
|
1219
|
+
rb_trilogy_release_buffer(ctx);
|
|
1220
|
+
|
|
1030
1221
|
trilogy_free(&ctx->conn);
|
|
1031
1222
|
|
|
1032
1223
|
return Qnil;
|
|
@@ -1134,8 +1325,9 @@ static VALUE rb_trilogy_server_version(VALUE self) { return rb_str_new_cstr(get_
|
|
|
1134
1325
|
|
|
1135
1326
|
RUBY_FUNC_EXPORTED void Init_cext(void)
|
|
1136
1327
|
{
|
|
1137
|
-
#ifdef
|
|
1328
|
+
#ifdef HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY
|
|
1138
1329
|
rb_ext_ractor_safe(true);
|
|
1330
|
+
buffer_pool_key = rb_ractor_local_storage_value_newkey();
|
|
1139
1331
|
#endif
|
|
1140
1332
|
|
|
1141
1333
|
VALUE Trilogy = rb_const_get(rb_cObject, rb_intern("Trilogy"));
|
data/ext/trilogy-ruby/extconf.rb
CHANGED
|
@@ -10,12 +10,12 @@ File.binwrite("trilogy.c",
|
|
|
10
10
|
}.join)
|
|
11
11
|
|
|
12
12
|
$objs = %w[trilogy.o cast.o cext.o]
|
|
13
|
-
|
|
13
|
+
append_cflags(["-I #{__dir__}/inc", "-std=gnu99", "-fvisibility=hidden"])
|
|
14
14
|
|
|
15
15
|
dir_config("openssl")
|
|
16
16
|
|
|
17
17
|
have_library("crypto", "CRYPTO_malloc")
|
|
18
18
|
have_library("ssl", "SSL_new")
|
|
19
19
|
have_func("rb_interned_str", "ruby.h")
|
|
20
|
-
|
|
20
|
+
have_func("rb_ractor_local_storage_value_newkey", "ruby.h")
|
|
21
21
|
create_makefile "trilogy/cext"
|
|
@@ -53,6 +53,19 @@ int trilogy_buffer_expand(trilogy_buffer_t *buffer, size_t needed);
|
|
|
53
53
|
*/
|
|
54
54
|
int trilogy_buffer_putc(trilogy_buffer_t *buffer, uint8_t c);
|
|
55
55
|
|
|
56
|
+
/* trilogy_buffer_write - Appends multiple bytes to the buffer, resizing the underlying
|
|
57
|
+
* allocation if necessary.
|
|
58
|
+
*
|
|
59
|
+
* buffer - A pointer to a pre-initialized trilogy_buffer_t.
|
|
60
|
+
* ptr - The pointer to the byte array.
|
|
61
|
+
* len - How many bytes to append.
|
|
62
|
+
*
|
|
63
|
+
* Return values:
|
|
64
|
+
* TRILOGY_OK - The character was appended to the buffer
|
|
65
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
|
66
|
+
*/
|
|
67
|
+
int trilogy_buffer_write(trilogy_buffer_t *buffer, const uint8_t *ptr, size_t len);
|
|
68
|
+
|
|
56
69
|
/* trilogy_buffer_free - Free an trilogy_buffer_t's underlying storage. The buffer
|
|
57
70
|
* must be re-initialized with trilogy_buffer_init if it is to be reused. Any
|
|
58
71
|
* operations performed on an unintialized or freed buffer are undefined.
|
|
@@ -106,6 +106,15 @@ typedef struct {
|
|
|
106
106
|
*/
|
|
107
107
|
int trilogy_init(trilogy_conn_t *conn);
|
|
108
108
|
|
|
109
|
+
/* trilogy_init_no_buffer - Same as trilogy_init but doesn't allocate the packet buffer
|
|
110
|
+
*
|
|
111
|
+
* conn - A pre-allocated trilogy_conn_t pointer.
|
|
112
|
+
*
|
|
113
|
+
* Return values:
|
|
114
|
+
* TRILOGY_OK - The trilogy_conn_t pointer was properly initialized
|
|
115
|
+
*/
|
|
116
|
+
int trilogy_init_no_buffer(trilogy_conn_t *conn);
|
|
117
|
+
|
|
109
118
|
/* trilogy_flush_writes - Attempt to flush the internal packet buffer to the
|
|
110
119
|
* network. This must be used if a `_send` function returns TRILOGY_AGAIN, and
|
|
111
120
|
* should continue to be called until it returns a value other than
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
XX(TRILOGY_MAX_PACKET_EXCEEDED, -20) \
|
|
26
26
|
XX(TRILOGY_UNKNOWN_TYPE, -21) \
|
|
27
27
|
XX(TRILOGY_TIMEOUT, -22) \
|
|
28
|
-
XX(TRILOGY_AUTH_PLUGIN_ERROR, -23)
|
|
28
|
+
XX(TRILOGY_AUTH_PLUGIN_ERROR, -23) \
|
|
29
|
+
XX(TRILOGY_MEM_ERROR, -24)
|
|
29
30
|
|
|
30
31
|
enum {
|
|
31
32
|
#define XX(name, code) name = code,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <stdint.h>
|
|
2
2
|
#include <stdlib.h>
|
|
3
|
+
#include <string.h>
|
|
3
4
|
|
|
4
5
|
#include "trilogy/buffer.h"
|
|
5
6
|
#include "trilogy/error.h"
|
|
@@ -23,6 +24,9 @@ int trilogy_buffer_expand(trilogy_buffer_t *buffer, size_t needed)
|
|
|
23
24
|
{
|
|
24
25
|
// expand buffer if necessary
|
|
25
26
|
if (buffer->len + needed > buffer->cap) {
|
|
27
|
+
if (buffer->buff == NULL)
|
|
28
|
+
return TRILOGY_MEM_ERROR;
|
|
29
|
+
|
|
26
30
|
size_t new_cap = buffer->cap;
|
|
27
31
|
|
|
28
32
|
while (buffer->len + needed > new_cap) {
|
|
@@ -57,9 +61,24 @@ int trilogy_buffer_putc(trilogy_buffer_t *buffer, uint8_t c)
|
|
|
57
61
|
return TRILOGY_OK;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
int trilogy_buffer_write(trilogy_buffer_t *buffer, const uint8_t *ptr, size_t len)
|
|
65
|
+
{
|
|
66
|
+
int rc = trilogy_buffer_expand(buffer, len);
|
|
67
|
+
if (rc) {
|
|
68
|
+
return rc;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
memcpy(buffer->buff + buffer->len, ptr, len);
|
|
72
|
+
buffer->len += len;
|
|
73
|
+
|
|
74
|
+
return TRILOGY_OK;
|
|
75
|
+
}
|
|
76
|
+
|
|
60
77
|
void trilogy_buffer_free(trilogy_buffer_t *buffer)
|
|
61
78
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
if (buffer->buff) {
|
|
80
|
+
free(buffer->buff);
|
|
81
|
+
buffer->buff = NULL;
|
|
82
|
+
buffer->len = buffer->cap = 0;
|
|
83
|
+
}
|
|
65
84
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#include <fcntl.h>
|
|
2
|
+
#include <string.h>
|
|
2
3
|
|
|
3
4
|
#include "trilogy/client.h"
|
|
4
5
|
#include "trilogy/error.h"
|
|
@@ -117,10 +118,8 @@ static int begin_write(trilogy_conn_t *conn)
|
|
|
117
118
|
return trilogy_flush_writes(conn);
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
int
|
|
121
|
+
int trilogy_init_no_buffer(trilogy_conn_t *conn)
|
|
121
122
|
{
|
|
122
|
-
int rc;
|
|
123
|
-
|
|
124
123
|
conn->affected_rows = 0;
|
|
125
124
|
conn->last_insert_id = 0;
|
|
126
125
|
conn->warning_count = 0;
|
|
@@ -142,8 +141,14 @@ int trilogy_init(trilogy_conn_t *conn)
|
|
|
142
141
|
trilogy_packet_parser_init(&conn->packet_parser, &packet_parser_callbacks);
|
|
143
142
|
conn->packet_parser.user_data = &conn->packet_buffer;
|
|
144
143
|
|
|
145
|
-
|
|
144
|
+
return TRILOGY_OK;
|
|
145
|
+
}
|
|
146
146
|
|
|
147
|
+
int trilogy_init(trilogy_conn_t *conn)
|
|
148
|
+
{
|
|
149
|
+
int rc;
|
|
150
|
+
trilogy_init_no_buffer(conn);
|
|
151
|
+
CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
|
|
147
152
|
return TRILOGY_OK;
|
|
148
153
|
}
|
|
149
154
|
|
|
@@ -217,7 +222,7 @@ static int read_err_packet(trilogy_conn_t *conn)
|
|
|
217
222
|
return TRILOGY_ERR;
|
|
218
223
|
}
|
|
219
224
|
|
|
220
|
-
static int
|
|
225
|
+
static int read_deprecated_eof_packet(trilogy_conn_t *conn)
|
|
221
226
|
{
|
|
222
227
|
trilogy_eof_packet_t eof_packet;
|
|
223
228
|
|
|
@@ -236,6 +241,21 @@ static int read_eof_packet(trilogy_conn_t *conn)
|
|
|
236
241
|
return TRILOGY_EOF;
|
|
237
242
|
}
|
|
238
243
|
|
|
244
|
+
static int read_eof_packet(trilogy_conn_t *conn)
|
|
245
|
+
{
|
|
246
|
+
int rc;
|
|
247
|
+
|
|
248
|
+
if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
|
|
249
|
+
return read_ok_packet(conn);
|
|
250
|
+
} else {
|
|
251
|
+
if ((rc = read_deprecated_eof_packet(conn)) != TRILOGY_EOF) {
|
|
252
|
+
return rc;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return TRILOGY_OK;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
239
259
|
static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
240
260
|
{
|
|
241
261
|
trilogy_auth_switch_request_packet_t auth_switch_packet;
|
|
@@ -646,15 +666,7 @@ static int read_eof(trilogy_conn_t *conn)
|
|
|
646
666
|
return rc;
|
|
647
667
|
}
|
|
648
668
|
|
|
649
|
-
|
|
650
|
-
return read_ok_packet(conn);
|
|
651
|
-
} else {
|
|
652
|
-
if ((rc = read_eof_packet(conn)) != TRILOGY_EOF) {
|
|
653
|
-
return rc;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
return TRILOGY_OK;
|
|
657
|
-
}
|
|
669
|
+
return read_eof_packet(conn);
|
|
658
670
|
}
|
|
659
671
|
|
|
660
672
|
int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
@@ -679,14 +691,12 @@ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
|
679
691
|
return rc;
|
|
680
692
|
}
|
|
681
693
|
|
|
682
|
-
if (conn
|
|
683
|
-
if ((rc =
|
|
694
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
695
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
684
696
|
return rc;
|
|
685
697
|
}
|
|
686
698
|
|
|
687
699
|
return TRILOGY_EOF;
|
|
688
|
-
} else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
689
|
-
return read_eof_packet(conn);
|
|
690
700
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
691
701
|
return read_err_packet(conn);
|
|
692
702
|
} else {
|
|
@@ -722,7 +732,7 @@ int trilogy_drain_results(trilogy_conn_t *conn)
|
|
|
722
732
|
}
|
|
723
733
|
}
|
|
724
734
|
|
|
725
|
-
static uint8_t escape_lookup_table[256] = {
|
|
735
|
+
static const uint8_t escape_lookup_table[256] = {
|
|
726
736
|
['"'] = '"', ['\0'] = '0', ['\''] = '\'', ['\\'] = '\\', ['\n'] = 'n', ['\r'] = 'r', [26] = 'Z',
|
|
727
737
|
};
|
|
728
738
|
|
|
@@ -735,28 +745,40 @@ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char
|
|
|
735
745
|
|
|
736
746
|
b->len = 0;
|
|
737
747
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
748
|
+
// Escaped string will be at least as large as the source string,
|
|
749
|
+
// so might as well pre-expand the buffer.
|
|
750
|
+
CHECKED(trilogy_buffer_expand(b, len));
|
|
751
|
+
|
|
752
|
+
const uint8_t *cursor = (const uint8_t *)str;
|
|
753
|
+
const uint8_t *end = cursor + len;
|
|
741
754
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
755
|
+
if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
|
|
756
|
+
while (cursor < end) {
|
|
757
|
+
uint8_t *next_escape = memchr(cursor, '\'', (size_t)(end - cursor));
|
|
758
|
+
if (next_escape) {
|
|
759
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(next_escape - cursor)));
|
|
760
|
+
CHECKED(trilogy_buffer_write(b, (uint8_t *)"\'\'", 2));
|
|
761
|
+
cursor = next_escape + 1;
|
|
745
762
|
} else {
|
|
746
|
-
CHECKED(
|
|
763
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(end - cursor)));
|
|
764
|
+
break;
|
|
747
765
|
}
|
|
748
766
|
}
|
|
749
767
|
} else {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
768
|
+
while (cursor < end) {
|
|
769
|
+
uint8_t escaped = 0;
|
|
770
|
+
const uint8_t *start = cursor;
|
|
771
|
+
while (cursor < end && !(escaped = escape_lookup_table[*cursor])) {
|
|
772
|
+
cursor++;
|
|
773
|
+
}
|
|
754
774
|
|
|
775
|
+
CHECKED(trilogy_buffer_write(b, start, (size_t)(cursor - start)));
|
|
755
776
|
if (escaped) {
|
|
756
777
|
CHECKED(trilogy_buffer_putc(b, '\\'));
|
|
757
778
|
CHECKED(trilogy_buffer_putc(b, escaped));
|
|
779
|
+
cursor++;
|
|
758
780
|
} else {
|
|
759
|
-
|
|
781
|
+
break;
|
|
760
782
|
}
|
|
761
783
|
}
|
|
762
784
|
}
|
|
@@ -940,20 +962,18 @@ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint
|
|
|
940
962
|
int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
|
|
941
963
|
trilogy_binary_value_t *values_out)
|
|
942
964
|
{
|
|
943
|
-
int
|
|
965
|
+
int rc = read_packet(conn);
|
|
944
966
|
|
|
945
|
-
if (
|
|
946
|
-
return
|
|
967
|
+
if (rc < 0) {
|
|
968
|
+
return rc;
|
|
947
969
|
}
|
|
948
970
|
|
|
949
|
-
if (conn
|
|
950
|
-
if ((
|
|
951
|
-
return
|
|
971
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
972
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
973
|
+
return rc;
|
|
952
974
|
}
|
|
953
975
|
|
|
954
976
|
return TRILOGY_EOF;
|
|
955
|
-
} else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
956
|
-
return read_eof_packet(conn);
|
|
957
977
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
958
978
|
return read_err_packet(conn);
|
|
959
979
|
} else {
|
data/lib/trilogy/encoding.rb
CHANGED
data/lib/trilogy/result.rb
CHANGED
data/lib/trilogy/version.rb
CHANGED
data/trilogy.gemspec
CHANGED
|
@@ -22,6 +22,10 @@ Gem::Specification.new do |s|
|
|
|
22
22
|
|
|
23
23
|
s.require_paths = ["lib"]
|
|
24
24
|
|
|
25
|
+
s.required_ruby_version = ">= 3.0"
|
|
26
|
+
|
|
27
|
+
s.add_dependency "bigdecimal"
|
|
28
|
+
|
|
25
29
|
s.add_development_dependency "rake-compiler", "~> 1.0"
|
|
26
30
|
s.add_development_dependency "minitest", "~> 5.5"
|
|
27
31
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trilogy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- GitHub Engineering
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: bigdecimal
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
13
26
|
- !ruby/object:Gem::Dependency
|
|
14
27
|
name: rake-compiler
|
|
15
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,7 +51,6 @@ dependencies:
|
|
|
38
51
|
- - "~>"
|
|
39
52
|
- !ruby/object:Gem::Version
|
|
40
53
|
version: '5.5'
|
|
41
|
-
description:
|
|
42
54
|
email: opensource+trilogy@github.com
|
|
43
55
|
executables: []
|
|
44
56
|
extensions:
|
|
@@ -87,7 +99,6 @@ homepage: https://github.com/trilogy-libraries/trilogy
|
|
|
87
99
|
licenses:
|
|
88
100
|
- MIT
|
|
89
101
|
metadata: {}
|
|
90
|
-
post_install_message:
|
|
91
102
|
rdoc_options: []
|
|
92
103
|
require_paths:
|
|
93
104
|
- lib
|
|
@@ -95,15 +106,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
95
106
|
requirements:
|
|
96
107
|
- - ">="
|
|
97
108
|
- !ruby/object:Gem::Version
|
|
98
|
-
version: '0'
|
|
109
|
+
version: '3.0'
|
|
99
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
111
|
requirements:
|
|
101
112
|
- - ">="
|
|
102
113
|
- !ruby/object:Gem::Version
|
|
103
114
|
version: '0'
|
|
104
115
|
requirements: []
|
|
105
|
-
rubygems_version: 3.
|
|
106
|
-
signing_key:
|
|
116
|
+
rubygems_version: 3.6.9
|
|
107
117
|
specification_version: 4
|
|
108
118
|
summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
|
|
109
119
|
test_files: []
|