trilogy 2.6.0 → 2.7.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 +1 -2
- data/ext/trilogy-ruby/cext.c +10 -23
- data/ext/trilogy-ruby/extconf.rb +5 -1
- data/ext/trilogy-ruby/src/buffer.c +6 -1
- data/ext/trilogy-ruby/src/socket.c +17 -4
- data/lib/trilogy/error.rb +12 -18
- data/lib/trilogy/version.rb +1 -1
- data/lib/trilogy.rb +3 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f36747c1d61f440a5ff6b5d37981b0a11ad26a1b973ebeb9bab84e832b2841a3
|
4
|
+
data.tar.gz: b654bac6dbc4d3451c5101e9f8574de4aee4044d6aa280c0736e3e18ad09c723
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81aefe81cfe750d70a42915c6a16f6d7211455b255a6588088c8ac6c682240636df5c2269b7090e78ba2ce6f991e3266f1c2b57711130e84fde85a8d38b22a1c
|
7
|
+
data.tar.gz: 3df0441086b141c6c0ebb0d3a216d14205547bd340c06cf0884e1985ac6550023ea8960200c5afe31821160883a3cd96a07a942efb05a9d335153dcdafa83976
|
data/README.md
CHANGED
@@ -27,7 +27,6 @@ $ gem install trilogy
|
|
27
27
|
``` ruby
|
28
28
|
client = Trilogy.new(host: "127.0.0.1", port: 3306, username: "root", read_timeout: 2)
|
29
29
|
if client.ping
|
30
|
-
client.query_options[:database_timezone] = :utc
|
31
30
|
client.change_db "mydb"
|
32
31
|
|
33
32
|
result = client.query("SELECT id, created_at FROM users LIMIT 10")
|
@@ -63,7 +62,7 @@ bundle exec rake build
|
|
63
62
|
|
64
63
|
The official Ruby bindings are inside of the canonical trilogy repository itself.
|
65
64
|
|
66
|
-
1. Fork it ( https://github.com/
|
65
|
+
1. Fork it ( https://github.com/trilogy-libraries/trilogy/fork )
|
67
66
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
68
67
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
69
68
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/ext/trilogy-ruby/cext.c
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
|
18
18
|
VALUE Trilogy_CastError;
|
19
19
|
static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLError, Trilogy_QueryError,
|
20
|
-
Trilogy_ConnectionClosedError,
|
20
|
+
Trilogy_ConnectionClosedError,
|
21
21
|
Trilogy_TimeoutError, Trilogy_SyscallError, Trilogy_Result, Trilogy_EOFError;
|
22
22
|
|
23
23
|
static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows, id_connect_timeout, id_read_timeout,
|
@@ -43,9 +43,7 @@ static void mark_trilogy(void *ptr)
|
|
43
43
|
static void free_trilogy(void *ptr)
|
44
44
|
{
|
45
45
|
struct trilogy_ctx *ctx = ptr;
|
46
|
-
|
47
|
-
trilogy_free(&ctx->conn);
|
48
|
-
}
|
46
|
+
trilogy_free(&ctx->conn);
|
49
47
|
xfree(ptr);
|
50
48
|
}
|
51
49
|
|
@@ -90,12 +88,8 @@ static struct trilogy_ctx *get_open_ctx(VALUE obj)
|
|
90
88
|
NORETURN(static void trilogy_syserr_fail_str(int, VALUE));
|
91
89
|
static void trilogy_syserr_fail_str(int e, VALUE msg)
|
92
90
|
{
|
93
|
-
if (e ==
|
94
|
-
|
95
|
-
} else if (e == ECONNRESET) {
|
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
|
91
|
+
if (e == EPIPE) {
|
92
|
+
// Backwards compatibility: This error message is a bit odd, but includes "TRILOGY_CLOSED_CONNECTION" to match legacy string matching
|
99
93
|
rb_raise(Trilogy_EOFError, "%" PRIsVALUE ": TRILOGY_CLOSED_CONNECTION: EPIPE", msg);
|
100
94
|
} else {
|
101
95
|
VALUE exc = rb_funcall(Trilogy_SyscallError, id_from_errno, 2, INT2NUM(e), msg);
|
@@ -309,6 +303,7 @@ static int try_connect(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake,
|
|
309
303
|
int rc = args.rc;
|
310
304
|
|
311
305
|
if (rc != TRILOGY_OK) {
|
306
|
+
trilogy_sock_close(sock);
|
312
307
|
return rc;
|
313
308
|
}
|
314
309
|
|
@@ -316,8 +311,10 @@ static int try_connect(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake,
|
|
316
311
|
escape the GVL on each wait operation without going through call_without_gvl */
|
317
312
|
sock->wait_cb = _cb_ruby_wait;
|
318
313
|
rc = trilogy_connect_send_socket(&ctx->conn, sock);
|
319
|
-
if (rc < 0)
|
314
|
+
if (rc < 0) {
|
315
|
+
trilogy_sock_close(sock);
|
320
316
|
return rc;
|
317
|
+
}
|
321
318
|
|
322
319
|
while (1) {
|
323
320
|
rc = trilogy_connect_recv(&ctx->conn, handshake);
|
@@ -425,7 +422,7 @@ static void authenticate(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake
|
|
425
422
|
}
|
426
423
|
}
|
427
424
|
|
428
|
-
static VALUE
|
425
|
+
static VALUE rb_trilogy_connect(VALUE self, VALUE encoding, VALUE charset, VALUE opts)
|
429
426
|
{
|
430
427
|
struct trilogy_ctx *ctx = get_ctx(self);
|
431
428
|
trilogy_sockopt_t connopt = {0};
|
@@ -436,7 +433,6 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
436
433
|
connopt.encoding = NUM2INT(charset);
|
437
434
|
|
438
435
|
Check_Type(opts, T_HASH);
|
439
|
-
rb_ivar_set(self, id_connection_options, opts);
|
440
436
|
|
441
437
|
if ((val = rb_hash_lookup(opts, ID2SYM(id_ssl_mode))) != Qnil) {
|
442
438
|
Check_Type(val, T_FIXNUM);
|
@@ -578,9 +574,6 @@ static VALUE rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VA
|
|
578
574
|
}
|
579
575
|
|
580
576
|
int rc = try_connect(ctx, &handshake, &connopt);
|
581
|
-
if (rc == TRILOGY_TIMEOUT) {
|
582
|
-
rb_raise(Trilogy_TimeoutError, "trilogy_connect_recv");
|
583
|
-
}
|
584
577
|
if (rc != TRILOGY_OK) {
|
585
578
|
if (connopt.path) {
|
586
579
|
handle_trilogy_error(ctx, rc, "trilogy_connect - unable to connect to %s", connopt.path);
|
@@ -1104,7 +1097,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1104
1097
|
VALUE Trilogy = rb_const_get(rb_cObject, rb_intern("Trilogy"));
|
1105
1098
|
rb_define_alloc_func(Trilogy, allocate_trilogy);
|
1106
1099
|
|
1107
|
-
rb_define_private_method(Trilogy, "
|
1100
|
+
rb_define_private_method(Trilogy, "_connect", rb_trilogy_connect, 3);
|
1108
1101
|
rb_define_method(Trilogy, "change_db", rb_trilogy_change_db, 1);
|
1109
1102
|
rb_define_alias(Trilogy, "select_db", "change_db");
|
1110
1103
|
rb_define_method(Trilogy, "query", rb_trilogy_query, 1);
|
@@ -1159,12 +1152,6 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1159
1152
|
Trilogy_TimeoutError = rb_const_get(Trilogy, rb_intern("TimeoutError"));
|
1160
1153
|
rb_global_variable(&Trilogy_TimeoutError);
|
1161
1154
|
|
1162
|
-
Trilogy_ConnectionRefusedError = rb_const_get(Trilogy, rb_intern("ConnectionRefusedError"));
|
1163
|
-
rb_global_variable(&Trilogy_ConnectionRefusedError);
|
1164
|
-
|
1165
|
-
Trilogy_ConnectionResetError = rb_const_get(Trilogy, rb_intern("ConnectionResetError"));
|
1166
|
-
rb_global_variable(&Trilogy_ConnectionResetError);
|
1167
|
-
|
1168
1155
|
Trilogy_BaseConnectionError = rb_const_get(Trilogy, rb_intern("BaseConnectionError"));
|
1169
1156
|
rb_global_variable(&Trilogy_BaseConnectionError);
|
1170
1157
|
|
data/ext/trilogy-ruby/extconf.rb
CHANGED
@@ -2,8 +2,12 @@ require "mkmf"
|
|
2
2
|
|
3
3
|
# concatenate trilogy library sources to allow the compiler to optimise across
|
4
4
|
# source files
|
5
|
+
|
6
|
+
trilogy_src_dir = File.realpath("src", __dir__)
|
5
7
|
File.binwrite("trilogy.c",
|
6
|
-
Dir["#{
|
8
|
+
Dir["#{trilogy_src_dir}/**/*.c"].map { |src|
|
9
|
+
%{#line 1 "#{src}"\n} + File.binread(src)
|
10
|
+
}.join)
|
7
11
|
|
8
12
|
$objs = %w[trilogy.o cast.o cext.o]
|
9
13
|
$CFLAGS << " -I #{__dir__}/inc -std=gnu99 -fvisibility=hidden"
|
@@ -57,4 +57,9 @@ int trilogy_buffer_putc(trilogy_buffer_t *buffer, uint8_t c)
|
|
57
57
|
return TRILOGY_OK;
|
58
58
|
}
|
59
59
|
|
60
|
-
void trilogy_buffer_free(trilogy_buffer_t *buffer)
|
60
|
+
void trilogy_buffer_free(trilogy_buffer_t *buffer)
|
61
|
+
{
|
62
|
+
free(buffer->buff);
|
63
|
+
buffer->buff = NULL;
|
64
|
+
buffer->len = buffer->cap = 0;
|
65
|
+
}
|
@@ -100,8 +100,15 @@ static int _cb_raw_close(trilogy_sock_t *_sock)
|
|
100
100
|
if (sock->fd != -1) {
|
101
101
|
rc = close(sock->fd);
|
102
102
|
}
|
103
|
+
|
103
104
|
if (sock->addr) {
|
104
|
-
|
105
|
+
if (sock->base.opts.hostname == NULL && sock->base.opts.path != NULL) {
|
106
|
+
/* We created these with calloc so must free them instead of calling freeaddrinfo */
|
107
|
+
free(sock->addr->ai_addr);
|
108
|
+
free(sock->addr);
|
109
|
+
} else {
|
110
|
+
freeaddrinfo(sock->addr);
|
111
|
+
}
|
105
112
|
}
|
106
113
|
|
107
114
|
free(sock->base.opts.hostname);
|
@@ -189,6 +196,7 @@ static int raw_connect_internal(struct trilogy_sock *sock, const struct addrinfo
|
|
189
196
|
{
|
190
197
|
int sockerr;
|
191
198
|
socklen_t sockerr_len = sizeof(sockerr);
|
199
|
+
int rc = TRILOGY_SYSERR;
|
192
200
|
|
193
201
|
sock->fd = socket(ai->ai_family, SOCK_STREAM, ai->ai_protocol);
|
194
202
|
if (sock->fd < 0) {
|
@@ -244,8 +252,8 @@ static int raw_connect_internal(struct trilogy_sock *sock, const struct addrinfo
|
|
244
252
|
}
|
245
253
|
}
|
246
254
|
|
247
|
-
if (trilogy_sock_wait_write((trilogy_sock_t *)sock) < 0) {
|
248
|
-
goto
|
255
|
+
if ((rc = trilogy_sock_wait_write((trilogy_sock_t *)sock)) < 0) {
|
256
|
+
goto failrc;
|
249
257
|
}
|
250
258
|
|
251
259
|
if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerr_len) < 0) {
|
@@ -263,9 +271,11 @@ static int raw_connect_internal(struct trilogy_sock *sock, const struct addrinfo
|
|
263
271
|
return TRILOGY_OK;
|
264
272
|
|
265
273
|
fail:
|
274
|
+
rc = TRILOGY_SYSERR;
|
275
|
+
failrc:
|
266
276
|
close(sock->fd);
|
267
277
|
sock->fd = -1;
|
268
|
-
return
|
278
|
+
return rc;
|
269
279
|
}
|
270
280
|
|
271
281
|
static int _cb_raw_connect(trilogy_sock_t *_sock)
|
@@ -377,6 +387,9 @@ static ssize_t ssl_io_return(struct trilogy_sock *sock, ssize_t ret)
|
|
377
387
|
int rc = SSL_get_error(sock->ssl, (int)ret);
|
378
388
|
if (rc == SSL_ERROR_WANT_WRITE || rc == SSL_ERROR_WANT_READ) {
|
379
389
|
return (ssize_t)TRILOGY_AGAIN;
|
390
|
+
} else if (rc == SSL_ERROR_ZERO_RETURN) {
|
391
|
+
// Server has closed the connection for writing by sending the close_notify alert
|
392
|
+
return (ssize_t)TRILOGY_CLOSED_CONNECTION;
|
380
393
|
} else if (rc == SSL_ERROR_SYSCALL && !ERR_peek_error()) {
|
381
394
|
if (errno == 0) {
|
382
395
|
// On OpenSSL <= 1.1.1, SSL_ERROR_SYSCALL with an errno value
|
data/lib/trilogy/error.rb
CHANGED
@@ -12,7 +12,7 @@ class Trilogy
|
|
12
12
|
end
|
13
13
|
|
14
14
|
# Trilogy may raise various syscall errors, which we treat as Trilogy::Errors.
|
15
|
-
|
15
|
+
module SyscallError
|
16
16
|
ERRORS = {}
|
17
17
|
|
18
18
|
Errno.constants
|
@@ -20,7 +20,10 @@ class Trilogy
|
|
20
20
|
.select { |c| c.is_a?(Class) && c < SystemCallError }
|
21
21
|
.each do |c|
|
22
22
|
errno_name = c.to_s.split('::').last
|
23
|
-
ERRORS[c::Errno] = const_set(errno_name, Class.new(c) {
|
23
|
+
ERRORS[c::Errno] = const_set(errno_name, Class.new(c) {
|
24
|
+
include Trilogy::ConnectionError
|
25
|
+
singleton_class.define_method(:===, Module.instance_method(:===))
|
26
|
+
})
|
24
27
|
end
|
25
28
|
|
26
29
|
ERRORS.freeze
|
@@ -32,6 +35,11 @@ class Trilogy
|
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
38
|
+
ConnectionRefusedError = SyscallError::ECONNREFUSED
|
39
|
+
deprecate_constant :ConnectionRefusedError
|
40
|
+
ConnectionResetError = SyscallError::ECONNRESET
|
41
|
+
deprecate_constant :ConnectionResetError
|
42
|
+
|
35
43
|
class BaseError < StandardError
|
36
44
|
include Error
|
37
45
|
|
@@ -58,21 +66,7 @@ class Trilogy
|
|
58
66
|
class CastError < ClientError
|
59
67
|
end
|
60
68
|
|
61
|
-
class TimeoutError <
|
62
|
-
include ConnectionError
|
63
|
-
|
64
|
-
def initialize(error_message = nil, error_code = nil)
|
65
|
-
super
|
66
|
-
@error_code = error_code
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
class ConnectionRefusedError < Errno::ECONNREFUSED
|
71
|
-
include ConnectionError
|
72
|
-
end
|
73
|
-
|
74
|
-
class ConnectionResetError < Errno::ECONNRESET
|
75
|
-
include ConnectionError
|
69
|
+
class TimeoutError < BaseConnectionError
|
76
70
|
end
|
77
71
|
|
78
72
|
# DatabaseError was replaced by ProtocolError, but we'll keep it around as an
|
@@ -117,7 +111,7 @@ class Trilogy
|
|
117
111
|
include ConnectionError
|
118
112
|
end
|
119
113
|
|
120
|
-
#
|
114
|
+
# Occurs when a socket read or write returns EOF or when an operation is
|
121
115
|
# attempted on a socket which previously encountered an error.
|
122
116
|
class EOFError < BaseConnectionError
|
123
117
|
end
|
data/lib/trilogy/version.rb
CHANGED
data/lib/trilogy.rb
CHANGED
@@ -12,8 +12,10 @@ class Trilogy
|
|
12
12
|
mysql_encoding = options[:encoding] || "utf8mb4"
|
13
13
|
encoding = Trilogy::Encoding.find(mysql_encoding)
|
14
14
|
charset = Trilogy::Encoding.charset(mysql_encoding)
|
15
|
+
@connection_options = options
|
16
|
+
@connected_host = nil
|
15
17
|
|
16
|
-
|
18
|
+
_connect(encoding, charset, options)
|
17
19
|
end
|
18
20
|
|
19
21
|
def connection_options
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trilogy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
|
-
rubygems_version: 3.4.
|
105
|
+
rubygems_version: 3.4.7
|
106
106
|
signing_key:
|
107
107
|
specification_version: 4
|
108
108
|
summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
|