trilogy 2.2.0 → 2.4.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 +7 -1
- data/ext/trilogy-ruby/cast.c +12 -7
- data/ext/trilogy-ruby/cext.c +230 -88
- data/ext/trilogy-ruby/extconf.rb +1 -1
- data/ext/trilogy-ruby/inc/trilogy/blocking.h +18 -1
- data/ext/trilogy-ruby/inc/trilogy/client.h +58 -0
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +56 -35
- data/ext/trilogy-ruby/inc/trilogy/socket.h +2 -0
- data/ext/trilogy-ruby/src/blocking.c +23 -0
- data/ext/trilogy-ruby/src/client.c +51 -3
- data/ext/trilogy-ruby/src/protocol.c +21 -6
- data/ext/trilogy-ruby/src/socket.c +25 -0
- data/ext/trilogy-ruby/trilogy-ruby.h +4 -1
- data/lib/trilogy/version.rb +1 -1
- data/lib/trilogy.rb +238 -20
- metadata +3 -3
data/lib/trilogy.rb
CHANGED
@@ -1,7 +1,178 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "trilogy/version"
|
3
4
|
|
4
5
|
class Trilogy
|
6
|
+
# Trilogy::Error is the base error type. All errors raised by Trilogy
|
7
|
+
# should be descendants of Trilogy::Error
|
8
|
+
module Error
|
9
|
+
attr_reader :error_code
|
10
|
+
end
|
11
|
+
|
12
|
+
# Trilogy::ConnectionError is the base error type for all potentially transient
|
13
|
+
# network errors.
|
14
|
+
module ConnectionError
|
15
|
+
include Error
|
16
|
+
end
|
17
|
+
|
18
|
+
# Trilogy may raise various syscall errors, which we treat as Trilogy::Errors.
|
19
|
+
class SyscallError
|
20
|
+
ERRORS = {}
|
21
|
+
|
22
|
+
Errno.constants
|
23
|
+
.map { |c| Errno.const_get(c) }.uniq
|
24
|
+
.select { |c| c.is_a?(Class) && c < SystemCallError }
|
25
|
+
.each do |c|
|
26
|
+
errno_name = c.to_s.split('::').last
|
27
|
+
ERRORS[c::Errno] = const_set(errno_name, Class.new(c) { include Trilogy::Error })
|
28
|
+
end
|
29
|
+
|
30
|
+
ERRORS.freeze
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def from_errno(errno, message)
|
34
|
+
ERRORS[errno].new(message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class BaseError < StandardError
|
40
|
+
include Error
|
41
|
+
|
42
|
+
def initialize(error_message = nil, error_code = nil)
|
43
|
+
message = error_code ? "#{error_code}: #{error_message}" : error_message
|
44
|
+
super(message)
|
45
|
+
@error_code = error_code
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class BaseConnectionError < BaseError
|
50
|
+
include ConnectionError
|
51
|
+
end
|
52
|
+
|
53
|
+
# Trilogy::ClientError is the base error type for invalid queries or parameters
|
54
|
+
# that shouldn't be retried.
|
55
|
+
class ClientError < BaseError
|
56
|
+
include Error
|
57
|
+
end
|
58
|
+
|
59
|
+
class QueryError < ClientError
|
60
|
+
end
|
61
|
+
|
62
|
+
class CastError < ClientError
|
63
|
+
end
|
64
|
+
|
65
|
+
class TimeoutError < Errno::ETIMEDOUT
|
66
|
+
include ConnectionError
|
67
|
+
end
|
68
|
+
|
69
|
+
class ConnectionRefusedError < Errno::ECONNREFUSED
|
70
|
+
include ConnectionError
|
71
|
+
end
|
72
|
+
|
73
|
+
class ConnectionResetError < Errno::ECONNRESET
|
74
|
+
include ConnectionError
|
75
|
+
end
|
76
|
+
|
77
|
+
# DatabaseError was replaced by ProtocolError, but we'll keep it around as an
|
78
|
+
# ancestor of ProtocolError for compatibility reasons (e.g. so `rescue DatabaseError`
|
79
|
+
# still works. We can remove this class in the next major release.
|
80
|
+
module DatabaseError
|
81
|
+
end
|
82
|
+
|
83
|
+
class ProtocolError < BaseError
|
84
|
+
include DatabaseError
|
85
|
+
|
86
|
+
ERROR_CODES = {
|
87
|
+
1205 => TimeoutError, # ER_LOCK_WAIT_TIMEOUT
|
88
|
+
1044 => BaseConnectionError, # ER_DBACCESS_DENIED_ERROR
|
89
|
+
1045 => BaseConnectionError, # ER_ACCESS_DENIED_ERROR
|
90
|
+
1064 => QueryError, # ER_PARSE_ERROR
|
91
|
+
1152 => BaseConnectionError, # ER_ABORTING_CONNECTION
|
92
|
+
1153 => BaseConnectionError, # ER_NET_PACKET_TOO_LARGE
|
93
|
+
1154 => BaseConnectionError, # ER_NET_READ_ERROR_FROM_PIPE
|
94
|
+
1155 => BaseConnectionError, # ER_NET_FCNTL_ERROR
|
95
|
+
1156 => BaseConnectionError, # ER_NET_PACKETS_OUT_OF_ORDER
|
96
|
+
1157 => BaseConnectionError, # ER_NET_UNCOMPRESS_ERROR
|
97
|
+
1158 => BaseConnectionError, # ER_NET_READ_ERROR
|
98
|
+
1159 => BaseConnectionError, # ER_NET_READ_INTERRUPTED
|
99
|
+
1160 => BaseConnectionError, # ER_NET_ERROR_ON_WRITE
|
100
|
+
1161 => BaseConnectionError, # ER_NET_WRITE_INTERRUPTED
|
101
|
+
1927 => BaseConnectionError, # ER_CONNECTION_KILLED
|
102
|
+
}
|
103
|
+
class << self
|
104
|
+
def from_code(message, code)
|
105
|
+
ERROR_CODES.fetch(code, self).new(message, code)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class SSLError < BaseError
|
111
|
+
include ConnectionError
|
112
|
+
end
|
113
|
+
|
114
|
+
class ConnectionClosed < IOError
|
115
|
+
include ConnectionError
|
116
|
+
end
|
117
|
+
|
118
|
+
MYSQL_TO_RUBY_ENCODINGS_MAP = {
|
119
|
+
"big5" => "Big5",
|
120
|
+
"dec8" => nil,
|
121
|
+
"cp850" => "CP850",
|
122
|
+
"hp8" => nil,
|
123
|
+
"koi8r" => "KOI8-R",
|
124
|
+
"latin1" => "ISO-8859-1",
|
125
|
+
"latin2" => "ISO-8859-2",
|
126
|
+
"swe7" => nil,
|
127
|
+
"ascii" => "US-ASCII",
|
128
|
+
"ujis" => "eucJP-ms",
|
129
|
+
"sjis" => "Shift_JIS",
|
130
|
+
"hebrew" => "ISO-8859-8",
|
131
|
+
"tis620" => "TIS-620",
|
132
|
+
"euckr" => "EUC-KR",
|
133
|
+
"koi8u" => "KOI8-R",
|
134
|
+
"gb2312" => "GB2312",
|
135
|
+
"greek" => "ISO-8859-7",
|
136
|
+
"cp1250" => "Windows-1250",
|
137
|
+
"gbk" => "GBK",
|
138
|
+
"latin5" => "ISO-8859-9",
|
139
|
+
"armscii8" => nil,
|
140
|
+
"utf8" => "UTF-8",
|
141
|
+
"ucs2" => "UTF-16BE",
|
142
|
+
"cp866" => "IBM866",
|
143
|
+
"keybcs2" => nil,
|
144
|
+
"macce" => "macCentEuro",
|
145
|
+
"macroman" => "macRoman",
|
146
|
+
"cp852" => "CP852",
|
147
|
+
"latin7" => "ISO-8859-13",
|
148
|
+
"utf8mb4" => "UTF-8",
|
149
|
+
"cp1251" => "Windows-1251",
|
150
|
+
"utf16" => "UTF-16",
|
151
|
+
"cp1256" => "Windows-1256",
|
152
|
+
"cp1257" => "Windows-1257",
|
153
|
+
"utf32" => "UTF-32",
|
154
|
+
"binary" => "ASCII-8BIT",
|
155
|
+
"geostd8" => nil,
|
156
|
+
"cp932" => "Windows-31J",
|
157
|
+
"eucjpms" => "eucJP-ms",
|
158
|
+
"utf16le" => "UTF-16LE",
|
159
|
+
"gb18030" => "GB18030",
|
160
|
+
}.freeze
|
161
|
+
|
162
|
+
def initialize(options = {})
|
163
|
+
mysql_encoding = options[:encoding] || "utf8mb4"
|
164
|
+
unless rb_encoding = MYSQL_TO_RUBY_ENCODINGS_MAP[mysql_encoding]
|
165
|
+
raise ArgumentError, "Unknown or unsupported encoding: #{mysql_encoding}"
|
166
|
+
end
|
167
|
+
encoding = Encoding.find(rb_encoding)
|
168
|
+
charset = charset_for_mysql_encoding(mysql_encoding)
|
169
|
+
_initialize(encoding, charset, **options)
|
170
|
+
end
|
171
|
+
|
172
|
+
def connection_options
|
173
|
+
@connection_options.dup.freeze
|
174
|
+
end
|
175
|
+
|
5
176
|
def in_transaction?
|
6
177
|
(server_status & SERVER_STATUS_IN_TRANS) != 0
|
7
178
|
end
|
@@ -28,34 +199,81 @@ class Trilogy
|
|
28
199
|
ensure
|
29
200
|
self.query_flags = old_flags
|
30
201
|
end
|
31
|
-
end
|
32
202
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
203
|
+
class Result
|
204
|
+
attr_reader :fields, :rows, :query_time, :affected_rows, :last_insert_id
|
205
|
+
|
206
|
+
def count
|
207
|
+
rows.count
|
208
|
+
end
|
37
209
|
|
38
|
-
|
39
|
-
|
210
|
+
def each_hash
|
211
|
+
return enum_for(:each_hash) unless block_given?
|
40
212
|
|
41
|
-
|
42
|
-
|
213
|
+
rows.each do |row|
|
214
|
+
this_row = {}
|
43
215
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
216
|
+
idx = 0
|
217
|
+
row.each do |col|
|
218
|
+
this_row[fields[idx]] = col
|
219
|
+
idx += 1
|
220
|
+
end
|
221
|
+
|
222
|
+
yield this_row
|
48
223
|
end
|
49
224
|
|
50
|
-
|
225
|
+
self
|
51
226
|
end
|
52
227
|
|
53
|
-
|
54
|
-
|
228
|
+
def each(&bk)
|
229
|
+
rows.each(&bk)
|
230
|
+
end
|
55
231
|
|
56
|
-
|
57
|
-
rows.each(&bk)
|
232
|
+
include Enumerable
|
58
233
|
end
|
59
234
|
|
60
|
-
|
235
|
+
private
|
236
|
+
|
237
|
+
def charset_for_mysql_encoding(mysql_encoding)
|
238
|
+
@mysql_encodings_map ||= {
|
239
|
+
"big5" => CHARSET_BIG5_CHINESE_CI,
|
240
|
+
"cp850" => CHARSET_CP850_GENERAL_CI,
|
241
|
+
"koi8r" => CHARSET_KOI8R_GENERAL_CI,
|
242
|
+
"latin1" => CHARSET_LATIN1_GENERAL_CI,
|
243
|
+
"latin2" => CHARSET_LATIN2_GENERAL_CI,
|
244
|
+
"ascii" => CHARSET_ASCII_GENERAL_CI,
|
245
|
+
"ujis" => CHARSET_UJIS_JAPANESE_CI,
|
246
|
+
"sjis" => CHARSET_SJIS_JAPANESE_CI,
|
247
|
+
"hebrew" => CHARSET_HEBREW_GENERAL_CI,
|
248
|
+
"tis620" => CHARSET_TIS620_THAI_CI,
|
249
|
+
"euckr" => CHARSET_EUCKR_KOREAN_CI,
|
250
|
+
"koi8u" => CHARSET_KOI8U_GENERAL_CI,
|
251
|
+
"gb2312" => CHARSET_GB2312_CHINESE_CI,
|
252
|
+
"greek" => CHARSET_GREEK_GENERAL_CI,
|
253
|
+
"cp1250" => CHARSET_CP1250_GENERAL_CI,
|
254
|
+
"gbk" => CHARSET_GBK_CHINESE_CI,
|
255
|
+
"latin5" => CHARSET_LATIN5_TURKISH_CI,
|
256
|
+
"utf8" => CHARSET_UTF8_GENERAL_CI,
|
257
|
+
"ucs2" => CHARSET_UCS2_GENERAL_CI,
|
258
|
+
"cp866" => CHARSET_CP866_GENERAL_CI,
|
259
|
+
"cp932" => CHARSET_CP932_JAPANESE_CI,
|
260
|
+
"eucjpms" => CHARSET_EUCJPMS_JAPANESE_CI,
|
261
|
+
"utf16le" => CHARSET_UTF16_GENERAL_CI,
|
262
|
+
"gb18030" => CHARSET_GB18030_CHINESE_CI,
|
263
|
+
"macce" => CHARSET_MACCE_GENERAL_CI,
|
264
|
+
"macroman" => CHARSET_MACROMAN_GENERAL_CI,
|
265
|
+
"cp852" => CHARSET_CP852_GENERAL_CI,
|
266
|
+
"latin7" => CHARSET_LATIN7_GENERAL_CI,
|
267
|
+
"utf8mb4" => CHARSET_UTF8MB4_GENERAL_CI,
|
268
|
+
"cp1251" => CHARSET_CP1251_GENERAL_CI,
|
269
|
+
"utf16" => CHARSET_UTF16_GENERAL_CI,
|
270
|
+
"cp1256" => CHARSET_CP1256_GENERAL_CI,
|
271
|
+
"cp1257" => CHARSET_CP1257_GENERAL_CI,
|
272
|
+
"utf32" => CHARSET_UTF32_GENERAL_CI,
|
273
|
+
"binary" => CHARSET_BINARY,
|
274
|
+
}.freeze
|
275
|
+
@mysql_encodings_map[mysql_encoding]
|
276
|
+
end
|
61
277
|
end
|
278
|
+
|
279
|
+
require "trilogy/cext"
|
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.4.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: 2023-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -99,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
99
|
- !ruby/object:Gem::Version
|
100
100
|
version: '0'
|
101
101
|
requirements: []
|
102
|
-
rubygems_version: 3.
|
102
|
+
rubygems_version: 3.4.7
|
103
103
|
signing_key:
|
104
104
|
specification_version: 4
|
105
105
|
summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
|