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 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