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.
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
- VALUE block_given;
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 = rb_iv_get(self, "@query_options");
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 != Qnil) {
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 != Qnil) {
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, block, (*fetch_row_func)(VALUE, MYSQL_FIELD *fields, const result_each_args *args);
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 = rb_iv_get(self, "@query_options");
822
+ defaults = rb_ivar_get(self, intern_query_options);
820
823
  Check_Type(defaults, T_HASH);
821
- if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
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 = block;
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
- rb_iv_set(obj, "@query_options", options);
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"));
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.5.0".freeze
2
+ VERSION = "0.5.3".freeze
3
3
  end
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 'Win32API'
24
- LoadLibrary = Win32API.new('Kernel32', 'LoadLibrary', ['P'], 'I')
25
- if LoadLibrary.call(dll_path).zero?
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.4.5 (GNU/Linux)
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
- ExECACwCGyMCHgECF4ACGQEGCwkIBwMCBhUKCQgCAwUWAgMBAAUCWKcFIAUJHirJ
15
- FAAKCRCMcY07UHLh9VcFAJ46pUyVd8BZ2r5CppMC1tmyQ3ceRgCfVPwuVsiS0VER
16
- 5WUqtAQDt+DoetCIaQQTEQIAKQIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAhkB
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
- =HfUN
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[collation[1]]
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
 
@@ -38,6 +38,8 @@ mysql_to_rb = {
38
38
  "geostd8" => nil,
39
39
  "cp932" => "Windows-31J",
40
40
  "eucjpms" => "eucJP-ms",
41
+ "utf16le" => "UTF-16LE",
42
+ "gb18030" => "GB18030",
41
43
  }
42
44
 
43
45
  puts <<-HEADER
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.0
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: 2018-03-20 00:00:00.000000000 Z
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
- rubyforge_project:
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: []
@@ -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
@@ -1,11 +0,0 @@
1
- root:
2
- host: localhost
3
- username: root
4
- password:
5
- database: test
6
-
7
- user:
8
- host: localhost
9
- username: LOCALUSERNAME
10
- password:
11
- database: mysql2_test
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
data/spec/my.cnf.example DELETED
@@ -1,9 +0,0 @@
1
- [root]
2
- host=localhost
3
- user=LOCALUSERNAME
4
- password=
5
-
6
- [client]
7
- host=localhost
8
- user=LOCALUSERNAME
9
- password=