mysql2 0.3.20 → 0.3.21

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
  SHA1:
3
- metadata.gz: 6261e72195a2e1281c59ad35c44fe9edefc69241
4
- data.tar.gz: 5dd5b66d3bc11fcd978d4a2d491ac47e3a005510
3
+ metadata.gz: 0e3404975106474ef92ef68d239b4c69901a380e
4
+ data.tar.gz: 77464b6c2940d1b8be408918678f4a6abb47c95f
5
5
  SHA512:
6
- metadata.gz: 9a1dc5ee4f77d51c5042b5eb8153a18c2d199506c5514a5064c818fe5f800fcbd32dae5a73c29eec268b8f96e1f31c358f87e9306e50fbee7836f7a3a88c5393
7
- data.tar.gz: fa5d2a4b7815f4b834598e647e0aecb328e8997638ea7c73ad313cfa6b9eba5099a329c402071fb08a8a09b99e5a99784191bf7ff5722f0707a69a9c5d041d62
6
+ metadata.gz: e4e545f707900e4338c9965d068d81260b63cf3d7501926b5d2bce98415a1f589d88a541b256dc81f2e8519869103894303357f44dbc14b132fb3cfeca0d0f1d
7
+ data.tar.gz: 0e3d0943c65f739827fd394e471fa30e04a9c0a9499ed896e944f1b513de4c4c066b0c8e168d4bf66ebbc6905b0df9ffe7fe904094ff49ebff29abdb5c6c6ffc
@@ -642,40 +642,27 @@ static VALUE rb_mysql_client_abandon_results(VALUE self) {
642
642
  * Query the database with +sql+, with optional +options+. For the possible
643
643
  * options, see @@default_query_options on the Mysql2::Client class.
644
644
  */
645
- static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
645
+ static VALUE rb_query(VALUE self, VALUE sql, VALUE current) {
646
646
  #ifndef _WIN32
647
647
  struct async_query_args async_args;
648
648
  #endif
649
649
  struct nogvl_send_query_args args;
650
- int async = 0;
651
- VALUE opts, current;
652
650
  VALUE thread_current = rb_thread_current();
653
- #ifdef HAVE_RUBY_ENCODING_H
654
- rb_encoding *conn_enc;
655
- #endif
656
651
  GET_CLIENT(self);
657
652
 
658
653
  REQUIRE_CONNECTED(wrapper);
659
654
  args.mysql = wrapper->client;
660
655
 
661
- current = rb_hash_dup(rb_iv_get(self, "@query_options"));
662
656
  RB_GC_GUARD(current);
663
657
  Check_Type(current, T_HASH);
664
658
  rb_iv_set(self, "@current_query_options", current);
665
659
 
666
- if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
667
- rb_funcall(current, intern_merge_bang, 1, opts);
668
-
669
- if (rb_hash_aref(current, sym_async) == Qtrue) {
670
- async = 1;
671
- }
672
- }
673
-
674
- Check_Type(args.sql, T_STRING);
660
+ Check_Type(sql, T_STRING);
675
661
  #ifdef HAVE_RUBY_ENCODING_H
676
- conn_enc = rb_to_encoding(wrapper->encoding);
677
662
  /* ensure the string is in the encoding the connection is expecting */
678
- args.sql = rb_str_export_to_enc(args.sql, conn_enc);
663
+ args.sql = rb_str_export_to_enc(sql, rb_to_encoding(wrapper->encoding));
664
+ #else
665
+ args.sql = sql;
679
666
  #endif
680
667
  args.sql_ptr = RSTRING_PTR(args.sql);
681
668
  args.sql_len = RSTRING_LEN(args.sql);
@@ -699,15 +686,15 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
699
686
  #ifndef _WIN32
700
687
  rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
701
688
 
702
- if (!async) {
689
+ if (rb_hash_aref(current, sym_async) == Qtrue) {
690
+ return Qnil;
691
+ } else {
703
692
  async_args.fd = wrapper->client->net.fd;
704
693
  async_args.self = self;
705
694
 
706
695
  rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0);
707
696
 
708
697
  return rb_mysql_client_async_result(self);
709
- } else {
710
- return Qnil;
711
698
  }
712
699
  #else
713
700
  do_send_query(&args);
@@ -1259,7 +1246,6 @@ void init_mysql2_client() {
1259
1246
  rb_define_singleton_method(cMysql2Client, "info", rb_mysql_client_info, 0);
1260
1247
 
1261
1248
  rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
1262
- rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
1263
1249
  rb_define_method(cMysql2Client, "abandon_results!", rb_mysql_client_abandon_results, 0);
1264
1250
  rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
1265
1251
  rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
@@ -1292,6 +1278,7 @@ void init_mysql2_client() {
1292
1278
  rb_define_private_method(cMysql2Client, "ssl_set", set_ssl_options, 5);
1293
1279
  rb_define_private_method(cMysql2Client, "initialize_ext", initialize_ext, 0);
1294
1280
  rb_define_private_method(cMysql2Client, "connect", rb_connect, 7);
1281
+ rb_define_private_method(cMysql2Client, "_query", rb_query, 2);
1295
1282
 
1296
1283
  sym_id = ID2SYM(rb_intern("id"));
1297
1284
  sym_version = ID2SYM(rb_intern("version"));
@@ -531,6 +531,10 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
531
531
  return wrapper->rows;
532
532
  }
533
533
  wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
534
+ } else if (!cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
535
+ mysql_data_seek(wrapper->result, 0);
536
+ wrapper->lastRowProcessed = 0;
537
+ wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
534
538
  }
535
539
 
536
540
  if (cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
@@ -558,7 +562,9 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
558
562
 
559
563
  if (row == Qnil) {
560
564
  /* we don't need the mysql C dataset around anymore, peace it */
561
- rb_mysql_result_free_result(wrapper);
565
+ if (cacheRows) {
566
+ rb_mysql_result_free_result(wrapper);
567
+ }
562
568
  return Qnil;
563
569
  }
564
570
 
@@ -566,7 +572,7 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
566
572
  rb_yield(row);
567
573
  }
568
574
  }
569
- if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
575
+ if (wrapper->lastRowProcessed == wrapper->numberOfRows && cacheRows) {
570
576
  /* we don't need the mysql C dataset around anymore, peace it */
571
577
  rb_mysql_result_free_result(wrapper);
572
578
  }
@@ -61,4 +61,22 @@ module Mysql2::Util
61
61
  Hash[hash.map { |k,v| [k.to_sym, v] }]
62
62
  end
63
63
 
64
+ #
65
+ # In Mysql2::Client#query and Mysql2::Statement#execute,
66
+ # Thread#handle_interrupt is used to prevent Timeout#timeout
67
+ # from interrupting query execution.
68
+ #
69
+ # Timeout::ExitException was removed in Ruby 2.3.0, 2.2.3, and 2.1.8,
70
+ # but is present in earlier 2.1.x and 2.2.x, so we provide a shim.
71
+ #
72
+ if Thread.respond_to?(:handle_interrupt)
73
+ require 'timeout'
74
+ # rubocop:disable Style/ConstantName
75
+ TimeoutError = if defined?(::Timeout::ExitException)
76
+ ::Timeout::ExitException
77
+ else
78
+ ::Timeout::Error
79
+ end
80
+ end
81
+
64
82
  end
@@ -74,6 +74,18 @@ module Mysql2
74
74
  @@default_query_options
75
75
  end
76
76
 
77
+ if Thread.respond_to?(:handle_interrupt)
78
+ def query(sql, options = {})
79
+ Thread.handle_interrupt(::Mysql2::Util::TimeoutError => :never) do
80
+ _query(sql, @query_options.merge(options))
81
+ end
82
+ end
83
+ else
84
+ def query(sql, options = {})
85
+ _query(sql, @query_options.merge(options))
86
+ end
87
+ end
88
+
77
89
  def query_info
78
90
  info = query_info_string
79
91
  return {} unless info
@@ -1,3 +1,3 @@
1
1
  module Mysql2
2
- VERSION = "0.3.20"
2
+ VERSION = "0.3.21"
3
3
  end
@@ -462,59 +462,39 @@ describe Mysql2::Client do
462
462
  }.should raise_error(Mysql2::Error)
463
463
  end
464
464
 
465
- it "should close the connection when an exception is raised" do
466
- begin
467
- Timeout.timeout(1, Timeout::Error) do
468
- @client.query("SELECT sleep(2)")
469
- end
470
- rescue Timeout::Error
471
- end
465
+ it 'should be impervious to connection-corrupting timeouts in #query' do
466
+ pending('`Thread.handle_interrupt` is not defined') unless Thread.respond_to?(:handle_interrupt)
467
+ # attempt to break the connection
468
+ expect { Timeout.timeout(0.1) { @client.query('SELECT SLEEP(1)') } }.to raise_error(Timeout::Error)
472
469
 
473
- lambda {
474
- @client.query("SELECT 1")
475
- }.should raise_error(Mysql2::Error, 'closed MySQL connection')
470
+ # expect the connection to not be broken
471
+ expect { @client.query('SELECT 1') }.to_not raise_error
476
472
  end
477
473
 
478
- it "should handle Timeouts without leaving the connection hanging if reconnect is true" do
479
- client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:reconnect => true))
480
- begin
481
- Timeout.timeout(1, Timeout::Error) do
482
- client.query("SELECT sleep(2)")
483
- end
484
- rescue Timeout::Error
474
+ context 'when a non-standard exception class is raised' do
475
+ it "should close the connection when an exception is raised" do
476
+ expect { Timeout.timeout(0.1, ArgumentError) { @client.query('SELECT SLEEP(1)') } }.to raise_error(ArgumentError)
477
+ expect { @client.query('SELECT 1') }.to raise_error(Mysql2::Error, 'closed MySQL connection')
485
478
  end
486
479
 
487
- lambda {
488
- client.query("SELECT 1")
489
- }.should_not raise_error(Mysql2::Error)
490
- end
480
+ it "should handle Timeouts without leaving the connection hanging if reconnect is true" do
481
+ client = Mysql2::Client.new(DatabaseCredentials['root'].merge(:reconnect => true))
491
482
 
492
- it "should handle Timeouts without leaving the connection hanging if reconnect is set to true after construction true" do
493
- client = Mysql2::Client.new(DatabaseCredentials['root'])
494
- begin
495
- Timeout.timeout(1, Timeout::Error) do
496
- client.query("SELECT sleep(2)")
497
- end
498
- rescue Timeout::Error
483
+ expect { Timeout.timeout(0.1, ArgumentError) { client.query('SELECT SLEEP(1)') } }.to raise_error(ArgumentError)
484
+ expect { client.query('SELECT 1') }.to_not raise_error
499
485
  end
500
486
 
501
- lambda {
502
- client.query("SELECT 1")
503
- }.should raise_error(Mysql2::Error)
487
+ it "should handle Timeouts without leaving the connection hanging if reconnect is set to true after construction true" do
488
+ client = Mysql2::Client.new(DatabaseCredentials['root'])
504
489
 
505
- client.reconnect = true
490
+ expect { Timeout.timeout(0.1, ArgumentError) { client.query('SELECT SLEEP(1)') } }.to raise_error(ArgumentError)
491
+ expect { client.query('SELECT 1') }.to raise_error(Mysql2::Error)
506
492
 
507
- begin
508
- Timeout.timeout(1, Timeout::Error) do
509
- client.query("SELECT sleep(2)")
510
- end
511
- rescue Timeout::Error
512
- end
513
-
514
- lambda {
515
- client.query("SELECT 1")
516
- }.should_not raise_error(Mysql2::Error)
493
+ client.reconnect = true
517
494
 
495
+ expect { Timeout.timeout(0.1, ArgumentError) { client.query('SELECT SLEEP(1)') } }.to raise_error(ArgumentError)
496
+ expect { client.query('SELECT 1') }.to_not raise_error
497
+ end
518
498
  end
519
499
 
520
500
  it "threaded queries should be supported" do
@@ -78,6 +78,11 @@ describe Mysql2::Result do
78
78
  result.first.object_id.should_not eql(result.first.object_id)
79
79
  end
80
80
 
81
+ it "should be able to iterate a second time even if cache_rows is disabled" do
82
+ result = @client.query "SELECT 1 UNION SELECT 2", :cache_rows => false
83
+ result.to_a.should eql(result.to_a)
84
+ end
85
+
81
86
  it "should yield different value for #first if streaming" do
82
87
  result = @client.query "SELECT 1 UNION SELECT 2", :stream => true, :cache_rows => false
83
88
  result.first.should_not eql(result.first)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.20
4
+ version: 0.3.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Lopez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-25 00:00:00.000000000 Z
11
+ date: 2016-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -115,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
115
  version: '0'
116
116
  requirements: []
117
117
  rubyforge_project:
118
- rubygems_version: 2.0.14
118
+ rubygems_version: 2.0.14.1
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: A simple, fast Mysql library for Ruby, binding to libmysql