mysql2 0.5.0 → 0.5.3
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 +5 -5
- data/README.md +49 -28
- data/ext/mysql2/client.c +25 -8
- data/ext/mysql2/extconf.rb +2 -1
- data/ext/mysql2/mysql_enc_name_to_ruby.h +60 -56
- data/ext/mysql2/mysql_enc_to_ruby.h +64 -3
- data/ext/mysql2/result.c +18 -11
- data/ext/mysql2/statement.c +36 -12
- data/lib/mysql2/client.rb +1 -1
- data/lib/mysql2/error.rb +3 -3
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +6 -3
- data/support/5072E1F5.asc +5 -5
- data/support/mysql_enc_to_ruby.rb +6 -1
- data/support/ruby_enc_to_mysql.rb +2 -0
- metadata +4 -55
- data/examples/eventmachine.rb +0 -19
- data/examples/threaded.rb +0 -16
- data/spec/configuration.yml.example +0 -11
- data/spec/em/em_spec.rb +0 -135
- data/spec/my.cnf.example +0 -9
- data/spec/mysql2/client_spec.rb +0 -1072
- data/spec/mysql2/error_spec.rb +0 -78
- data/spec/mysql2/result_spec.rb +0 -485
- data/spec/mysql2/statement_spec.rb +0 -708
- data/spec/rcov.opts +0 -3
- data/spec/spec_helper.rb +0 -112
- data/spec/ssl/ca-cert.pem +0 -17
- data/spec/ssl/ca-key.pem +0 -27
- data/spec/ssl/ca.cnf +0 -22
- data/spec/ssl/cert.cnf +0 -22
- data/spec/ssl/client-cert.pem +0 -17
- data/spec/ssl/client-key.pem +0 -27
- data/spec/ssl/client-req.pem +0 -15
- data/spec/ssl/gen_certs.sh +0 -48
- data/spec/ssl/pkcs8-client-key.pem +0 -28
- data/spec/ssl/pkcs8-server-key.pem +0 -28
- data/spec/ssl/server-cert.pem +0 -17
- data/spec/ssl/server-key.pem +0 -27
- data/spec/ssl/server-req.pem +0 -15
- data/spec/test_data +0 -1
data/ext/mysql2/result.c
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#include <mysql2_ext.h>
|
2
2
|
|
3
3
|
#include "mysql_enc_to_ruby.h"
|
4
|
+
#define MYSQL2_CHARSETNR_SIZE (sizeof(mysql2_mysql_enc_to_rb)/sizeof(mysql2_mysql_enc_to_rb[0]))
|
4
5
|
|
5
6
|
static rb_encoding *binaryEncoding;
|
6
7
|
|
@@ -29,14 +30,15 @@ typedef struct {
|
|
29
30
|
int streaming;
|
30
31
|
ID db_timezone;
|
31
32
|
ID app_timezone;
|
32
|
-
|
33
|
+
int block_given; /* boolean */
|
33
34
|
} result_each_args;
|
34
35
|
|
35
36
|
extern VALUE mMysql2, cMysql2Client, cMysql2Error;
|
36
37
|
static VALUE cMysql2Result, cDateTime, cDate;
|
37
38
|
static VALUE opt_decimal_zero, opt_float_zero, opt_time_year, opt_time_month, opt_utc_offset;
|
38
39
|
static ID intern_new, intern_utc, intern_local, intern_localtime, intern_local_offset,
|
39
|
-
intern_civil, intern_new_offset, intern_merge, intern_BigDecimal
|
40
|
+
intern_civil, intern_new_offset, intern_merge, intern_BigDecimal,
|
41
|
+
intern_query_options;
|
40
42
|
static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone,
|
41
43
|
sym_application_timezone, sym_local, sym_utc, sym_cast_booleans,
|
42
44
|
sym_cache_rows, sym_cast, sym_stream, sym_name;
|
@@ -179,7 +181,8 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
179
181
|
const char *enc_name;
|
180
182
|
int enc_index;
|
181
183
|
|
182
|
-
enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
|
184
|
+
enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
|
185
|
+
|
183
186
|
if (enc_name != NULL) {
|
184
187
|
/* use the field encoding we were able to match */
|
185
188
|
enc_index = rb_enc_find_index(enc_name);
|
@@ -693,7 +696,7 @@ static VALUE rb_mysql_result_fetch_fields(VALUE self) {
|
|
693
696
|
|
694
697
|
GET_RESULT(self);
|
695
698
|
|
696
|
-
defaults =
|
699
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
697
700
|
Check_Type(defaults, T_HASH);
|
698
701
|
if (rb_hash_aref(defaults, sym_symbolize_keys) == Qtrue) {
|
699
702
|
symbolizeKeys = 1;
|
@@ -738,7 +741,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
738
741
|
row = fetch_row_func(self, fields, args);
|
739
742
|
if (row != Qnil) {
|
740
743
|
wrapper->numberOfRows++;
|
741
|
-
if (args->block_given
|
744
|
+
if (args->block_given) {
|
742
745
|
rb_yield(row);
|
743
746
|
}
|
744
747
|
}
|
@@ -788,7 +791,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
788
791
|
return Qnil;
|
789
792
|
}
|
790
793
|
|
791
|
-
if (args->block_given
|
794
|
+
if (args->block_given) {
|
792
795
|
rb_yield(row);
|
793
796
|
}
|
794
797
|
}
|
@@ -806,7 +809,7 @@ static VALUE rb_mysql_result_each_(VALUE self,
|
|
806
809
|
|
807
810
|
static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
808
811
|
result_each_args args;
|
809
|
-
VALUE defaults, opts,
|
812
|
+
VALUE defaults, opts, (*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args);
|
810
813
|
ID db_timezone, app_timezone, dbTz, appTz;
|
811
814
|
int symbolizeKeys, asArray, castBool, cacheRows, cast;
|
812
815
|
|
@@ -816,9 +819,12 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
816
819
|
rb_raise(cMysql2Error, "Statement handle already closed");
|
817
820
|
}
|
818
821
|
|
819
|
-
defaults =
|
822
|
+
defaults = rb_ivar_get(self, intern_query_options);
|
820
823
|
Check_Type(defaults, T_HASH);
|
821
|
-
|
824
|
+
|
825
|
+
// A block can be passed to this method, but since we don't call the block directly from C,
|
826
|
+
// we don't need to capture it into a variable here with the "&" scan arg.
|
827
|
+
if (rb_scan_args(argc, argv, "01", &opts) == 1) {
|
822
828
|
opts = rb_funcall(defaults, intern_merge, 1, opts);
|
823
829
|
} else {
|
824
830
|
opts = defaults;
|
@@ -884,7 +890,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
884
890
|
args.cast = cast;
|
885
891
|
args.db_timezone = db_timezone;
|
886
892
|
args.app_timezone = app_timezone;
|
887
|
-
args.block_given =
|
893
|
+
args.block_given = rb_block_given_p();
|
888
894
|
|
889
895
|
if (wrapper->stmt_wrapper) {
|
890
896
|
fetch_row_func = rb_mysql_result_fetch_row_stmt;
|
@@ -949,7 +955,7 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_
|
|
949
955
|
}
|
950
956
|
|
951
957
|
rb_obj_call_init(obj, 0, NULL);
|
952
|
-
|
958
|
+
rb_ivar_set(obj, intern_query_options, options);
|
953
959
|
|
954
960
|
/* Options that cannot be changed in results.each(...) { |row| }
|
955
961
|
* should be processed here. */
|
@@ -978,6 +984,7 @@ void init_mysql2_result() {
|
|
978
984
|
intern_civil = rb_intern("civil");
|
979
985
|
intern_new_offset = rb_intern("new_offset");
|
980
986
|
intern_BigDecimal = rb_intern("BigDecimal");
|
987
|
+
intern_query_options = rb_intern("@query_options");
|
981
988
|
|
982
989
|
sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
|
983
990
|
sym_as = ID2SYM(rb_intern("as"));
|
data/ext/mysql2/statement.c
CHANGED
@@ -3,7 +3,8 @@
|
|
3
3
|
extern VALUE mMysql2, cMysql2Error;
|
4
4
|
static VALUE cMysql2Statement, cBigDecimal, cDateTime, cDate;
|
5
5
|
static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s, intern_merge_bang;
|
6
|
-
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year
|
6
|
+
static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year,
|
7
|
+
intern_query_options;
|
7
8
|
|
8
9
|
#define GET_STATEMENT(self) \
|
9
10
|
mysql_stmt_wrapper *stmt_wrapper; \
|
@@ -403,6 +404,39 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
|
403
404
|
}
|
404
405
|
}
|
405
406
|
|
407
|
+
// Duplicate the options hash, merge! extra opts, put the copy into the Result object
|
408
|
+
current = rb_hash_dup(rb_ivar_get(stmt_wrapper->client, intern_query_options));
|
409
|
+
(void)RB_GC_GUARD(current);
|
410
|
+
Check_Type(current, T_HASH);
|
411
|
+
|
412
|
+
// Merge in hash opts/keyword arguments
|
413
|
+
if (!NIL_P(opts)) {
|
414
|
+
rb_funcall(current, intern_merge_bang, 1, opts);
|
415
|
+
}
|
416
|
+
|
417
|
+
is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
|
418
|
+
|
419
|
+
// From stmt_execute to mysql_stmt_result_metadata to stmt_store_result, no
|
420
|
+
// Ruby API calls are allowed so that GC is not invoked. If the connection is
|
421
|
+
// in results-streaming-mode for Statement A, and in the middle Statement B
|
422
|
+
// gets garbage collected, a message will be sent to the server notifying it
|
423
|
+
// to release Statement B, resulting in the following error:
|
424
|
+
// Commands out of sync; you can't run this command now
|
425
|
+
//
|
426
|
+
// In streaming mode, statement execute must return a cursor because we
|
427
|
+
// cannot prevent other Statement objects from being garbage collected
|
428
|
+
// between fetches of each row of the result set. The following error
|
429
|
+
// occurs if cursor mode is not set:
|
430
|
+
// Row retrieval was canceled by mysql_stmt_close
|
431
|
+
|
432
|
+
if (is_streaming) {
|
433
|
+
unsigned long type = CURSOR_TYPE_READ_ONLY;
|
434
|
+
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &type)) {
|
435
|
+
FREE_BINDS;
|
436
|
+
rb_raise(cMysql2Error, "Unable to stream prepared statement, could not set CURSOR_TYPE_READ_ONLY");
|
437
|
+
}
|
438
|
+
}
|
439
|
+
|
406
440
|
if ((VALUE)rb_thread_call_without_gvl(nogvl_stmt_execute, stmt, RUBY_UBF_IO, 0) == Qfalse) {
|
407
441
|
FREE_BINDS;
|
408
442
|
rb_raise_mysql2_stmt_error(stmt_wrapper);
|
@@ -421,17 +455,6 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) {
|
|
421
455
|
return Qnil;
|
422
456
|
}
|
423
457
|
|
424
|
-
// Duplicate the options hash, merge! extra opts, put the copy into the Result object
|
425
|
-
current = rb_hash_dup(rb_iv_get(stmt_wrapper->client, "@query_options"));
|
426
|
-
(void)RB_GC_GUARD(current);
|
427
|
-
Check_Type(current, T_HASH);
|
428
|
-
|
429
|
-
// Merge in hash opts/keyword arguments
|
430
|
-
if (!NIL_P(opts)) {
|
431
|
-
rb_funcall(current, intern_merge_bang, 1, opts);
|
432
|
-
}
|
433
|
-
|
434
|
-
is_streaming = (Qtrue == rb_hash_aref(current, sym_stream));
|
435
458
|
if (!is_streaming) {
|
436
459
|
// recieve the whole result set from the server
|
437
460
|
if (mysql_stmt_store_result(stmt)) {
|
@@ -577,4 +600,5 @@ void init_mysql2_statement() {
|
|
577
600
|
|
578
601
|
intern_to_s = rb_intern("to_s");
|
579
602
|
intern_merge_bang = rb_intern("merge!");
|
603
|
+
intern_query_options = rb_intern("@query_options");
|
580
604
|
}
|
data/lib/mysql2/client.rb
CHANGED
@@ -31,7 +31,7 @@ module Mysql2
|
|
31
31
|
opts[:connect_timeout] = 120 unless opts.key?(:connect_timeout)
|
32
32
|
|
33
33
|
# TODO: stricter validation rather than silent massaging
|
34
|
-
%i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin].each do |key|
|
34
|
+
%i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin default_auth].each do |key|
|
35
35
|
next unless opts.key?(key)
|
36
36
|
case key
|
37
37
|
when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin
|
data/lib/mysql2/error.rb
CHANGED
@@ -52,7 +52,7 @@ module Mysql2
|
|
52
52
|
def initialize(msg, server_version = nil, error_number = nil, sql_state = nil)
|
53
53
|
@server_version = server_version
|
54
54
|
@error_number = error_number
|
55
|
-
@sql_state = sql_state ? sql_state.encode(ENCODE_OPTS) : nil
|
55
|
+
@sql_state = sql_state ? sql_state.encode(**ENCODE_OPTS) : nil
|
56
56
|
|
57
57
|
super(clean_message(msg))
|
58
58
|
end
|
@@ -91,9 +91,9 @@ module Mysql2
|
|
91
91
|
# Returns a valid UTF-8 string.
|
92
92
|
def clean_message(message)
|
93
93
|
if @server_version && @server_version > 50500
|
94
|
-
message.encode(ENCODE_OPTS)
|
94
|
+
message.encode(**ENCODE_OPTS)
|
95
95
|
else
|
96
|
-
message.encode(Encoding::UTF_8, ENCODE_OPTS)
|
96
|
+
message.encode(Encoding::UTF_8, **ENCODE_OPTS)
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
data/lib/mysql2/version.rb
CHANGED
data/lib/mysql2.rb
CHANGED
@@ -20,9 +20,12 @@ if RUBY_PLATFORM =~ /mswin|mingw/
|
|
20
20
|
end
|
21
21
|
|
22
22
|
if dll_path
|
23
|
-
require '
|
24
|
-
|
25
|
-
|
23
|
+
require 'fiddle'
|
24
|
+
kernel32 = Fiddle.dlopen 'kernel32'
|
25
|
+
load_library = Fiddle::Function.new(
|
26
|
+
kernel32['LoadLibraryW'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT,
|
27
|
+
)
|
28
|
+
if load_library.call(dll_path.encode('utf-16le')).zero?
|
26
29
|
abort "Failed to load libmysql.dll from #{dll_path}"
|
27
30
|
end
|
28
31
|
end
|
data/support/5072E1F5.asc
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
2
|
-
Version: GnuPG v1
|
2
|
+
Version: GnuPG v1
|
3
3
|
|
4
4
|
mQGiBD4+owwRBAC14GIfUfCyEDSIePvEW3SAFUdJBtoQHH/nJKZyQT7h9bPlUWC3
|
5
5
|
RODjQReyCITRrdwyrKUGku2FmeVGwn2u2WmDMNABLnpprWPkBdCk96+OmSLN9brZ
|
@@ -11,9 +11,9 @@ kYpXBACmWpP8NJTkamEnPCia2ZoOHODANwpUkP43I7jsDmgtobZX9qnrAXw+uNDI
|
|
11
11
|
QJEXM6FSbi0LLtZciNlYsafwAPEOMDKpMqAK6IyisNtPvaLd8lH0bPAnWqcyefep
|
12
12
|
rv0sxxqUEMcM3o7wwgfN83POkDasDbs3pjwPhxvhz6//62zQJ7Q2TXlTUUwgUmVs
|
13
13
|
ZWFzZSBFbmdpbmVlcmluZyA8bXlzcWwtYnVpbGRAb3NzLm9yYWNsZS5jb20+iGwE
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
ExECACwCGyMCHgECF4ACGQEGCwkIBwMCBhUKCQgCAwUWAgMBAAUCXEBY+wUJI87e
|
15
|
+
5AAKCRCMcY07UHLh9RZPAJ9uvm0zlzfCN+DHxHVaoFLFjdVYTQCfborsC9tmEZYa
|
16
|
+
whhogjeBkZkorbyIaQQTEQIAKQIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAhkB
|
17
17
|
BQJTAdRmBQkaZsvLAAoJEIxxjTtQcuH1X4MAoKNLWAbCBUj96637kv6Xa/fJuX5m
|
18
18
|
AJwPtmgDfjUe2iuhXdTrFEPT19SB6ohmBBMRAgAmAhsjBgsJCAcDAgQVAggDBBYC
|
19
19
|
AwECHgECF4AFAk53PioFCRP7AhUACgkQjHGNO1By4fUmzACeJdfqgc9gWTUhgmcM
|
@@ -428,5 +428,5 @@ GoaU9u41oyZTIiXPiFidJoIZCh7fdurP8pn3X+R5HUNXMr7M+ba8lSNxce/F3kmH
|
|
428
428
|
0L7rsKqdh9d/aVxhJINJ+inVDnrXWVoXu9GBjT8Nco1iU9SIVAQYEQIADAUCTnc9
|
429
429
|
7QUJE/sBuAASB2VHUEcAAQEJEIxxjTtQcuH1FJsAmwWK9vmwRJ/y9gTnJ8PWf0BV
|
430
430
|
roUTAKClYAhZuX2nUNwH4vlEJQHDqYa5yQ==
|
431
|
-
=
|
431
|
+
=ghXk
|
432
432
|
-----END PGP PUBLIC KEY BLOCK-----
|
@@ -43,6 +43,8 @@ mysql_to_rb = {
|
|
43
43
|
"geostd8" => "NULL",
|
44
44
|
"cp932" => "Windows-31J",
|
45
45
|
"eucjpms" => "eucJP-ms",
|
46
|
+
"utf16le" => "UTF-16LE",
|
47
|
+
"gb18030" => "GB18030",
|
46
48
|
}
|
47
49
|
|
48
50
|
client = Mysql2::Client.new(username: user, password: pass, host: host, port: port.to_i)
|
@@ -52,7 +54,10 @@ encodings_with_nil = Array.new(encodings.size)
|
|
52
54
|
|
53
55
|
collations.each do |collation|
|
54
56
|
mysql_col_idx = collation[2].to_i
|
55
|
-
rb_enc = mysql_to_rb
|
57
|
+
rb_enc = mysql_to_rb.fetch(collation[1]) do |mysql_enc|
|
58
|
+
$stderr.puts "WARNING: Missing mapping for collation \"#{collation[0]}\" with encoding \"#{mysql_enc}\" and id #{mysql_col_idx}, assuming NULL"
|
59
|
+
"NULL"
|
60
|
+
end
|
56
61
|
encodings[mysql_col_idx - 1] = [mysql_col_idx, rb_enc]
|
57
62
|
end
|
58
63
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Lopez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-11-27 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description:
|
15
15
|
email:
|
@@ -23,8 +23,6 @@ files:
|
|
23
23
|
- CHANGELOG.md
|
24
24
|
- LICENSE
|
25
25
|
- README.md
|
26
|
-
- examples/eventmachine.rb
|
27
|
-
- examples/threaded.rb
|
28
26
|
- ext/mysql2/client.c
|
29
27
|
- ext/mysql2/client.h
|
30
28
|
- ext/mysql2/extconf.rb
|
@@ -48,29 +46,6 @@ files:
|
|
48
46
|
- lib/mysql2/result.rb
|
49
47
|
- lib/mysql2/statement.rb
|
50
48
|
- lib/mysql2/version.rb
|
51
|
-
- spec/configuration.yml.example
|
52
|
-
- spec/em/em_spec.rb
|
53
|
-
- spec/my.cnf.example
|
54
|
-
- spec/mysql2/client_spec.rb
|
55
|
-
- spec/mysql2/error_spec.rb
|
56
|
-
- spec/mysql2/result_spec.rb
|
57
|
-
- spec/mysql2/statement_spec.rb
|
58
|
-
- spec/rcov.opts
|
59
|
-
- spec/spec_helper.rb
|
60
|
-
- spec/ssl/ca-cert.pem
|
61
|
-
- spec/ssl/ca-key.pem
|
62
|
-
- spec/ssl/ca.cnf
|
63
|
-
- spec/ssl/cert.cnf
|
64
|
-
- spec/ssl/client-cert.pem
|
65
|
-
- spec/ssl/client-key.pem
|
66
|
-
- spec/ssl/client-req.pem
|
67
|
-
- spec/ssl/gen_certs.sh
|
68
|
-
- spec/ssl/pkcs8-client-key.pem
|
69
|
-
- spec/ssl/pkcs8-server-key.pem
|
70
|
-
- spec/ssl/server-cert.pem
|
71
|
-
- spec/ssl/server-key.pem
|
72
|
-
- spec/ssl/server-req.pem
|
73
|
-
- spec/test_data
|
74
49
|
- support/5072E1F5.asc
|
75
50
|
- support/libmysql.def
|
76
51
|
- support/mysql_enc_to_ruby.rb
|
@@ -96,34 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
71
|
- !ruby/object:Gem::Version
|
97
72
|
version: '0'
|
98
73
|
requirements: []
|
99
|
-
|
100
|
-
rubygems_version: 2.5.2
|
74
|
+
rubygems_version: 3.0.3
|
101
75
|
signing_key:
|
102
76
|
specification_version: 4
|
103
77
|
summary: A simple, fast Mysql library for Ruby, binding to libmysql
|
104
|
-
test_files:
|
105
|
-
- examples/eventmachine.rb
|
106
|
-
- examples/threaded.rb
|
107
|
-
- spec/configuration.yml.example
|
108
|
-
- spec/em/em_spec.rb
|
109
|
-
- spec/my.cnf.example
|
110
|
-
- spec/mysql2/client_spec.rb
|
111
|
-
- spec/mysql2/error_spec.rb
|
112
|
-
- spec/mysql2/result_spec.rb
|
113
|
-
- spec/mysql2/statement_spec.rb
|
114
|
-
- spec/rcov.opts
|
115
|
-
- spec/spec_helper.rb
|
116
|
-
- spec/ssl/ca-cert.pem
|
117
|
-
- spec/ssl/ca-key.pem
|
118
|
-
- spec/ssl/ca.cnf
|
119
|
-
- spec/ssl/cert.cnf
|
120
|
-
- spec/ssl/client-cert.pem
|
121
|
-
- spec/ssl/client-key.pem
|
122
|
-
- spec/ssl/client-req.pem
|
123
|
-
- spec/ssl/gen_certs.sh
|
124
|
-
- spec/ssl/pkcs8-client-key.pem
|
125
|
-
- spec/ssl/pkcs8-server-key.pem
|
126
|
-
- spec/ssl/server-cert.pem
|
127
|
-
- spec/ssl/server-key.pem
|
128
|
-
- spec/ssl/server-req.pem
|
129
|
-
- spec/test_data
|
78
|
+
test_files: []
|
data/examples/eventmachine.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift 'lib'
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'eventmachine'
|
5
|
-
require 'mysql2/em'
|
6
|
-
|
7
|
-
EM.run do
|
8
|
-
client1 = Mysql2::EM::Client.new
|
9
|
-
defer1 = client1.query "SELECT sleep(3) as first_query"
|
10
|
-
defer1.callback do |result|
|
11
|
-
puts "Result: #{result.to_a.inspect}"
|
12
|
-
end
|
13
|
-
|
14
|
-
client2 = Mysql2::EM::Client.new
|
15
|
-
defer2 = client2.query "SELECT sleep(1) second_query"
|
16
|
-
defer2.callback do |result|
|
17
|
-
puts "Result: #{result.to_a.inspect}"
|
18
|
-
end
|
19
|
-
end
|
data/examples/threaded.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift 'lib'
|
2
|
-
require 'mysql2'
|
3
|
-
require 'timeout'
|
4
|
-
|
5
|
-
# Should never exceed worst case 3.5 secs across all 20 threads
|
6
|
-
Timeout.timeout(3.5) do
|
7
|
-
Array.new(20) do
|
8
|
-
Thread.new do
|
9
|
-
overhead = rand(3)
|
10
|
-
puts ">> thread #{Thread.current.object_id} query, #{overhead} sec overhead"
|
11
|
-
# 3 second overhead per query
|
12
|
-
Mysql2::Client.new(host: "localhost", username: "root").query("SELECT sleep(#{overhead}) as result")
|
13
|
-
puts "<< thread #{Thread.current.object_id} result, #{overhead} sec overhead"
|
14
|
-
end
|
15
|
-
end.each(&:join)
|
16
|
-
end
|
data/spec/em/em_spec.rb
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
begin
|
3
|
-
require 'eventmachine'
|
4
|
-
require 'mysql2/em'
|
5
|
-
|
6
|
-
RSpec.describe Mysql2::EM::Client do
|
7
|
-
it "should support async queries" do
|
8
|
-
results = []
|
9
|
-
EM.run do
|
10
|
-
client1 = Mysql2::EM::Client.new DatabaseCredentials['root']
|
11
|
-
defer1 = client1.query "SELECT sleep(0.1) as first_query"
|
12
|
-
defer1.callback do |result|
|
13
|
-
results << result.first
|
14
|
-
client1.close
|
15
|
-
EM.stop_event_loop
|
16
|
-
end
|
17
|
-
|
18
|
-
client2 = Mysql2::EM::Client.new DatabaseCredentials['root']
|
19
|
-
defer2 = client2.query "SELECT sleep(0.025) second_query"
|
20
|
-
defer2.callback do |result|
|
21
|
-
results << result.first
|
22
|
-
client2.close
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
expect(results[0].keys).to include("second_query")
|
27
|
-
expect(results[1].keys).to include("first_query")
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should support queries in callbacks" do
|
31
|
-
results = []
|
32
|
-
EM.run do
|
33
|
-
client = Mysql2::EM::Client.new DatabaseCredentials['root']
|
34
|
-
defer1 = client.query "SELECT sleep(0.025) as first_query"
|
35
|
-
defer1.callback do |result|
|
36
|
-
results << result.first
|
37
|
-
defer2 = client.query "SELECT sleep(0.025) as second_query"
|
38
|
-
defer2.callback do |r|
|
39
|
-
results << r.first
|
40
|
-
client.close
|
41
|
-
EM.stop_event_loop
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
expect(results[0].keys).to include("first_query")
|
47
|
-
expect(results[1].keys).to include("second_query")
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should not swallow exceptions raised in callbacks" do
|
51
|
-
expect do
|
52
|
-
EM.run do
|
53
|
-
client = Mysql2::EM::Client.new DatabaseCredentials['root']
|
54
|
-
defer = client.query "SELECT sleep(0.1) as first_query"
|
55
|
-
defer.callback do
|
56
|
-
client.close
|
57
|
-
raise 'some error'
|
58
|
-
end
|
59
|
-
defer.errback do
|
60
|
-
# This _shouldn't_ be run, but it needed to prevent the specs from
|
61
|
-
# freezing if this test fails.
|
62
|
-
EM.stop_event_loop
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end.to raise_error('some error')
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'when an exception is raised by the client' do
|
69
|
-
let(:client) { Mysql2::EM::Client.new DatabaseCredentials['root'] }
|
70
|
-
let(:error) { StandardError.new('some error') }
|
71
|
-
before { allow(client).to receive(:async_result).and_raise(error) }
|
72
|
-
after { client.close }
|
73
|
-
|
74
|
-
it "should swallow exceptions raised in by the client" do
|
75
|
-
errors = []
|
76
|
-
EM.run do
|
77
|
-
defer = client.query "SELECT sleep(0.1) as first_query"
|
78
|
-
defer.callback do
|
79
|
-
# This _shouldn't_ be run, but it is needed to prevent the specs from
|
80
|
-
# freezing if this test fails.
|
81
|
-
EM.stop_event_loop
|
82
|
-
end
|
83
|
-
defer.errback do |err|
|
84
|
-
errors << err
|
85
|
-
EM.stop_event_loop
|
86
|
-
end
|
87
|
-
end
|
88
|
-
expect(errors).to eq([error])
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should fail the deferrable" do
|
92
|
-
callbacks_run = []
|
93
|
-
EM.run do
|
94
|
-
defer = client.query "SELECT sleep(0.025) as first_query"
|
95
|
-
EM.add_timer(0.1) do
|
96
|
-
defer.callback do
|
97
|
-
callbacks_run << :callback
|
98
|
-
# This _shouldn't_ be run, but it is needed to prevent the specs from
|
99
|
-
# freezing if this test fails.
|
100
|
-
EM.stop_event_loop
|
101
|
-
end
|
102
|
-
defer.errback do
|
103
|
-
callbacks_run << :errback
|
104
|
-
EM.stop_event_loop
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
expect(callbacks_run).to eq([:errback])
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
it "should not raise error when closing client with no query running" do
|
113
|
-
callbacks_run = []
|
114
|
-
EM.run do
|
115
|
-
client = Mysql2::EM::Client.new DatabaseCredentials['root']
|
116
|
-
defer = client.query("select sleep(0.025)")
|
117
|
-
defer.callback do
|
118
|
-
callbacks_run << :callback
|
119
|
-
end
|
120
|
-
defer.errback do
|
121
|
-
callbacks_run << :errback
|
122
|
-
end
|
123
|
-
EM.add_timer(0.1) do
|
124
|
-
expect(callbacks_run).to eq([:callback])
|
125
|
-
expect do
|
126
|
-
client.close
|
127
|
-
end.not_to raise_error
|
128
|
-
EM.stop_event_loop
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
rescue LoadError
|
134
|
-
puts "EventMachine not installed, skipping the specs that use it"
|
135
|
-
end
|