trilogy 2.6.0 → 2.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a56e3472569e26552e3c8d7a674b70d9f5e15a546187f75e806f4d56ff5f15b2
4
- data.tar.gz: a2c29dc1fcf378be7a26088661401d9d4e7d4253c6823f8e7e84414662947cb1
3
+ metadata.gz: f36747c1d61f440a5ff6b5d37981b0a11ad26a1b973ebeb9bab84e832b2841a3
4
+ data.tar.gz: b654bac6dbc4d3451c5101e9f8574de4aee4044d6aa280c0736e3e18ad09c723
5
5
  SHA512:
6
- metadata.gz: 0f3348ccdf12ae3cef0c34f95e09829528a0bdb09b466774a1a8369fdeae6f4d1fb59df96b1d17e5361aea4656968b5e2149ffbf9fe8337b17d45f0903408122
7
- data.tar.gz: 33711de128dd47aeff4ab618d0c3b6032e966b1b52b7dad6352e1588f5d13e54df2d4709c97c006ec63d1fa603a1f190abd58784cea835d26be6c1f56da5b46c
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/github/trilogy/fork )
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`)
@@ -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, Trilogy_ConnectionRefusedError, Trilogy_ConnectionResetError,
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
- if (ctx->conn.socket != NULL) {
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 == ECONNREFUSED) {
94
- rb_raise(Trilogy_ConnectionRefusedError, "%" PRIsVALUE, msg);
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 rb_trilogy_initialize(VALUE self, VALUE encoding, VALUE charset, VALUE opts)
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, "_initialize", rb_trilogy_initialize, 3);
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
 
@@ -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["#{__dir__}/src/**/*.c"].map { |src| File.binread(src) }.join)
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) { free(buffer->buff); }
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
- freeaddrinfo(sock->addr);
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 fail;
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 TRILOGY_SYSERR;
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
- class SyscallError
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) { include Trilogy::ConnectionError })
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 < Errno::ETIMEDOUT
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
- # Occurrs when a socket read or write returns EOF or when an operation is
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
@@ -1,3 +1,3 @@
1
1
  class Trilogy
2
- VERSION = "2.6.0"
2
+ VERSION = "2.7.0"
3
3
  end
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
- _initialize(encoding, charset, options)
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.6.0
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: 2023-09-18 00:00:00.000000000 Z
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.10
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