mysql2 0.2.6-x86-mswin32-60 → 0.2.15-x86-mswin32-60
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/.rspec +1 -0
 - data/.rvmrc +1 -0
 - data/CHANGELOG.md +60 -1
 - data/Gemfile +3 -0
 - data/MIT-LICENSE +1 -1
 - data/README.md +326 -0
 - data/benchmark/active_record.rb +2 -4
 - data/benchmark/active_record_threaded.rb +42 -0
 - data/benchmark/escape.rb +3 -6
 - data/benchmark/query_with_mysql_casting.rb +3 -6
 - data/benchmark/query_without_mysql_casting.rb +13 -7
 - data/benchmark/sequel.rb +4 -6
 - data/benchmark/setup_db.rb +17 -13
 - data/benchmark/threaded.rb +44 -0
 - data/ext/mysql2/client.c +314 -80
 - data/ext/mysql2/client.h +3 -2
 - data/ext/mysql2/extconf.rb +9 -1
 - data/ext/mysql2/mysql2_ext.h +10 -0
 - data/ext/mysql2/result.c +128 -37
 - data/ext/mysql2/result.h +2 -2
 - data/ext/mysql2/wait_for_single_fd.h +36 -0
 - data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +10 -9
 - data/lib/active_record/connection_adapters/mysql2_adapter.rb +9 -58
 - data/lib/active_record/fiber_patches.rb +37 -9
 - data/lib/mysql2.rb +7 -2
 - data/lib/mysql2/client.rb +9 -2
 - data/lib/mysql2/em.rb +10 -6
 - data/lib/mysql2/em_fiber.rb +31 -0
 - data/lib/mysql2/version.rb +3 -0
 - data/mysql2.gemspec +18 -78
 - data/spec/em/em_fiber_spec.rb +22 -0
 - data/spec/mysql2/client_spec.rb +179 -62
 - data/spec/mysql2/error_spec.rb +47 -3
 - data/spec/mysql2/result_spec.rb +78 -8
 - data/spec/spec_helper.rb +2 -2
 - data/tasks/benchmarks.rake +15 -3
 - data/tasks/compile.rake +23 -6
 - data/tasks/vendor_mysql.rake +6 -7
 - metadata +145 -48
 - data/README.rdoc +0 -240
 - data/VERSION +0 -1
 - data/tasks/jeweler.rake +0 -17
 
    
        data/benchmark/escape.rb
    CHANGED
    
    | 
         @@ -10,24 +10,21 @@ require 'do_mysql' 
     | 
|
| 
       10 
10 
     | 
    
         
             
            def run_escape_benchmarks(str, number_of = 1000)
         
     | 
| 
       11 
11 
     | 
    
         
             
              Benchmark.bmbm do |x|
         
     | 
| 
       12 
12 
     | 
    
         
             
                mysql = Mysql.new("localhost", "root")
         
     | 
| 
       13 
     | 
    
         
            -
                x.report do
         
     | 
| 
       14 
     | 
    
         
            -
                  puts "Mysql #{str.inspect}"
         
     | 
| 
      
 13 
     | 
    
         
            +
                x.report "Mysql #{str.inspect}" do
         
     | 
| 
       15 
14 
     | 
    
         
             
                  number_of.times do
         
     | 
| 
       16 
15 
     | 
    
         
             
                    mysql.quote str
         
     | 
| 
       17 
16 
     | 
    
         
             
                  end
         
     | 
| 
       18 
17 
     | 
    
         
             
                end
         
     | 
| 
       19 
18 
     | 
    
         | 
| 
       20 
19 
     | 
    
         
             
                mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
         
     | 
| 
       21 
     | 
    
         
            -
                x.report do
         
     | 
| 
       22 
     | 
    
         
            -
                  puts "Mysql2 #{str.inspect}"
         
     | 
| 
      
 20 
     | 
    
         
            +
                x.report "Mysql2 #{str.inspect}" do
         
     | 
| 
       23 
21 
     | 
    
         
             
                  number_of.times do
         
     | 
| 
       24 
22 
     | 
    
         
             
                    mysql2.escape str
         
     | 
| 
       25 
23 
     | 
    
         
             
                  end
         
     | 
| 
       26 
24 
     | 
    
         
             
                end
         
     | 
| 
       27 
25 
     | 
    
         | 
| 
       28 
26 
     | 
    
         
             
                do_mysql = DataObjects::Connection.new("mysql://localhost/test")
         
     | 
| 
       29 
     | 
    
         
            -
                x.report do
         
     | 
| 
       30 
     | 
    
         
            -
                  puts "do_mysql #{str.inspect}"
         
     | 
| 
      
 27 
     | 
    
         
            +
                x.report "do_mysql #{str.inspect}" do
         
     | 
| 
       31 
28 
     | 
    
         
             
                  number_of.times do
         
     | 
| 
       32 
29 
     | 
    
         
             
                    do_mysql.quote_string str
         
     | 
| 
       33 
30 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -42,8 +42,7 @@ end 
     | 
|
| 
       42 
42 
     | 
    
         
             
            Benchmark.bmbm do |x|
         
     | 
| 
       43 
43 
     | 
    
         
             
              mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
         
     | 
| 
       44 
44 
     | 
    
         
             
              mysql2.query "USE #{database}"
         
     | 
| 
       45 
     | 
    
         
            -
              x.report do
         
     | 
| 
       46 
     | 
    
         
            -
                puts "Mysql2"
         
     | 
| 
      
 45 
     | 
    
         
            +
              x.report "Mysql2" do
         
     | 
| 
       47 
46 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       48 
47 
     | 
    
         
             
                  mysql2_result = mysql2.query sql, :symbolize_keys => true
         
     | 
| 
       49 
48 
     | 
    
         
             
                  mysql2_result.each do |res|
         
     | 
| 
         @@ -54,8 +53,7 @@ Benchmark.bmbm do |x| 
     | 
|
| 
       54 
53 
     | 
    
         | 
| 
       55 
54 
     | 
    
         
             
              mysql = Mysql.new("localhost", "root")
         
     | 
| 
       56 
55 
     | 
    
         
             
              mysql.query "USE #{database}"
         
     | 
| 
       57 
     | 
    
         
            -
              x.report do
         
     | 
| 
       58 
     | 
    
         
            -
                puts "Mysql"
         
     | 
| 
      
 56 
     | 
    
         
            +
              x.report "Mysql" do
         
     | 
| 
       59 
57 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       60 
58 
     | 
    
         
             
                  mysql_result = mysql.query sql
         
     | 
| 
       61 
59 
     | 
    
         
             
                  fields = mysql_result.fetch_fields
         
     | 
| 
         @@ -71,8 +69,7 @@ Benchmark.bmbm do |x| 
     | 
|
| 
       71 
69 
     | 
    
         | 
| 
       72 
70 
     | 
    
         
             
              do_mysql = DataObjects::Connection.new("mysql://localhost/#{database}")
         
     | 
| 
       73 
71 
     | 
    
         
             
              command = do_mysql.create_command sql
         
     | 
| 
       74 
     | 
    
         
            -
              x.report do
         
     | 
| 
       75 
     | 
    
         
            -
                puts "do_mysql"
         
     | 
| 
      
 72 
     | 
    
         
            +
              x.report "do_mysql" do
         
     | 
| 
       76 
73 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       77 
74 
     | 
    
         
             
                  do_result = command.execute_reader
         
     | 
| 
       78 
75 
     | 
    
         
             
                  do_result.each do |res|
         
     | 
| 
         @@ -14,10 +14,18 @@ sql = "SELECT * FROM mysql2_test LIMIT 100" 
     | 
|
| 
       14 
14 
     | 
    
         
             
            Benchmark.bmbm do |x|
         
     | 
| 
       15 
15 
     | 
    
         
             
              mysql2 = Mysql2::Client.new(:host => "localhost", :username => "root")
         
     | 
| 
       16 
16 
     | 
    
         
             
              mysql2.query "USE #{database}"
         
     | 
| 
       17 
     | 
    
         
            -
              x.report do
         
     | 
| 
       18 
     | 
    
         
            -
                puts "Mysql2"
         
     | 
| 
      
 17 
     | 
    
         
            +
              x.report "Mysql2 (cast: true)" do
         
     | 
| 
       19 
18 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       20 
     | 
    
         
            -
                  mysql2_result = mysql2.query sql, :symbolize_keys => true
         
     | 
| 
      
 19 
     | 
    
         
            +
                  mysql2_result = mysql2.query sql, :symbolize_keys => true, :cast => true
         
     | 
| 
      
 20 
     | 
    
         
            +
                  mysql2_result.each do |res|
         
     | 
| 
      
 21 
     | 
    
         
            +
                    # puts res.inspect
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              x.report "Mysql2 (cast: false)" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                number_of.times do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  mysql2_result = mysql2.query sql, :symbolize_keys => true, :cast => false
         
     | 
| 
       21 
29 
     | 
    
         
             
                  mysql2_result.each do |res|
         
     | 
| 
       22 
30 
     | 
    
         
             
                    # puts res.inspect
         
     | 
| 
       23 
31 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -26,8 +34,7 @@ Benchmark.bmbm do |x| 
     | 
|
| 
       26 
34 
     | 
    
         | 
| 
       27 
35 
     | 
    
         
             
              mysql = Mysql.new("localhost", "root")
         
     | 
| 
       28 
36 
     | 
    
         
             
              mysql.query "USE #{database}"
         
     | 
| 
       29 
     | 
    
         
            -
              x.report do
         
     | 
| 
       30 
     | 
    
         
            -
                puts "Mysql"
         
     | 
| 
      
 37 
     | 
    
         
            +
              x.report "Mysql" do
         
     | 
| 
       31 
38 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       32 
39 
     | 
    
         
             
                  mysql_result = mysql.query sql
         
     | 
| 
       33 
40 
     | 
    
         
             
                  mysql_result.each_hash do |res|
         
     | 
| 
         @@ -38,8 +45,7 @@ Benchmark.bmbm do |x| 
     | 
|
| 
       38 
45 
     | 
    
         | 
| 
       39 
46 
     | 
    
         
             
              do_mysql = DataObjects::Connection.new("mysql://localhost/#{database}")
         
     | 
| 
       40 
47 
     | 
    
         
             
              command = DataObjects::Mysql::Command.new do_mysql, sql
         
     | 
| 
       41 
     | 
    
         
            -
              x.report do
         
     | 
| 
       42 
     | 
    
         
            -
                puts "do_mysql"
         
     | 
| 
      
 48 
     | 
    
         
            +
              x.report "do_mysql" do
         
     | 
| 
       43 
49 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       44 
50 
     | 
    
         
             
                  do_result = command.execute_reader
         
     | 
| 
       45 
51 
     | 
    
         
             
                  do_result.each do |res|
         
     | 
    
        data/benchmark/sequel.rb
    CHANGED
    
    | 
         @@ -3,6 +3,7 @@ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') 
     | 
|
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            require 'rubygems'
         
     | 
| 
       5 
5 
     | 
    
         
             
            require 'benchmark'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'mysql2'
         
     | 
| 
       6 
7 
     | 
    
         
             
            require 'sequel'
         
     | 
| 
       7 
8 
     | 
    
         
             
            require 'sequel/adapters/do'
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
         @@ -16,22 +17,19 @@ class MysqlModel < Sequel::Model(Sequel.connect(mysql_opts)[:mysql2_test]); end 
     | 
|
| 
       16 
17 
     | 
    
         
             
            class DOMysqlModel < Sequel::Model(Sequel.connect(do_mysql_opts)[:mysql2_test]); end
         
     | 
| 
       17 
18 
     | 
    
         | 
| 
       18 
19 
     | 
    
         
             
            Benchmark.bmbm do |x|
         
     | 
| 
       19 
     | 
    
         
            -
              x.report do
         
     | 
| 
       20 
     | 
    
         
            -
                puts "Mysql2"
         
     | 
| 
      
 20 
     | 
    
         
            +
              x.report "Mysql2" do
         
     | 
| 
       21 
21 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       22 
22 
     | 
    
         
             
                  Mysql2Model.limit(1000).all
         
     | 
| 
       23 
23 
     | 
    
         
             
                end
         
     | 
| 
       24 
24 
     | 
    
         
             
              end
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
              x.report do
         
     | 
| 
       27 
     | 
    
         
            -
                puts "do:mysql"
         
     | 
| 
      
 26 
     | 
    
         
            +
              x.report "do:mysql" do
         
     | 
| 
       28 
27 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       29 
28 
     | 
    
         
             
                  DOMysqlModel.limit(1000).all
         
     | 
| 
       30 
29 
     | 
    
         
             
                end
         
     | 
| 
       31 
30 
     | 
    
         
             
              end
         
     | 
| 
       32 
31 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
              x.report do
         
     | 
| 
       34 
     | 
    
         
            -
                puts "Mysql"
         
     | 
| 
      
 32 
     | 
    
         
            +
              x.report "Mysql" do
         
     | 
| 
       35 
33 
     | 
    
         
             
                number_of.times do
         
     | 
| 
       36 
34 
     | 
    
         
             
                  MysqlModel.limit(1000).all
         
     | 
| 
       37 
35 
     | 
    
         
             
                end
         
     | 
    
        data/benchmark/setup_db.rb
    CHANGED
    
    | 
         @@ -76,6 +76,8 @@ end 
     | 
|
| 
       76 
76 
     | 
    
         | 
| 
       77 
77 
     | 
    
         
             
            puts "Creating #{num} records"
         
     | 
| 
       78 
78 
     | 
    
         
             
            num.times do |n|
         
     | 
| 
      
 79 
     | 
    
         
            +
              five_words = Faker::Lorem.words(rand(5))
         
     | 
| 
      
 80 
     | 
    
         
            +
              twenty5_paragraphs = Faker::Lorem.paragraphs(rand(25))
         
     | 
| 
       79 
81 
     | 
    
         
             
              insert_record(
         
     | 
| 
       80 
82 
     | 
    
         
             
                :bit_test => 1,
         
     | 
| 
       81 
83 
     | 
    
         
             
                :tiny_int_test => rand(128),
         
     | 
| 
         @@ -93,23 +95,25 @@ num.times do |n| 
     | 
|
| 
       93 
95 
     | 
    
         
             
                :timestamp_test => '2010-4-4 11:44:00',
         
     | 
| 
       94 
96 
     | 
    
         
             
                :time_test => '11:44:00',
         
     | 
| 
       95 
97 
     | 
    
         
             
                :year_test => Time.now.year,
         
     | 
| 
       96 
     | 
    
         
            -
                :char_test =>  
     | 
| 
       97 
     | 
    
         
            -
                :varchar_test =>  
     | 
| 
       98 
     | 
    
         
            -
                :binary_test =>  
     | 
| 
       99 
     | 
    
         
            -
                :varbinary_test =>  
     | 
| 
       100 
     | 
    
         
            -
                :tiny_blob_test =>  
     | 
| 
      
 98 
     | 
    
         
            +
                :char_test => five_words,
         
     | 
| 
      
 99 
     | 
    
         
            +
                :varchar_test => five_words,
         
     | 
| 
      
 100 
     | 
    
         
            +
                :binary_test => five_words,
         
     | 
| 
      
 101 
     | 
    
         
            +
                :varbinary_test => five_words,
         
     | 
| 
      
 102 
     | 
    
         
            +
                :tiny_blob_test => five_words,
         
     | 
| 
       101 
103 
     | 
    
         
             
                :tiny_text_test => Faker::Lorem.paragraph(rand(5)),
         
     | 
| 
       102 
     | 
    
         
            -
                :blob_test =>  
     | 
| 
       103 
     | 
    
         
            -
                :text_test =>  
     | 
| 
       104 
     | 
    
         
            -
                :medium_blob_test =>  
     | 
| 
       105 
     | 
    
         
            -
                :medium_text_test =>  
     | 
| 
       106 
     | 
    
         
            -
                :long_blob_test =>  
     | 
| 
       107 
     | 
    
         
            -
                :long_text_test =>  
     | 
| 
      
 104 
     | 
    
         
            +
                :blob_test => twenty5_paragraphs,
         
     | 
| 
      
 105 
     | 
    
         
            +
                :text_test => twenty5_paragraphs,
         
     | 
| 
      
 106 
     | 
    
         
            +
                :medium_blob_test => twenty5_paragraphs,
         
     | 
| 
      
 107 
     | 
    
         
            +
                :medium_text_test => twenty5_paragraphs,
         
     | 
| 
      
 108 
     | 
    
         
            +
                :long_blob_test => twenty5_paragraphs,
         
     | 
| 
      
 109 
     | 
    
         
            +
                :long_text_test => twenty5_paragraphs,
         
     | 
| 
       108 
110 
     | 
    
         
             
                :enum_test => ['val1', 'val2'].rand,
         
     | 
| 
       109 
111 
     | 
    
         
             
                :set_test => ['val1', 'val2', 'val1,val2'].rand
         
     | 
| 
       110 
112 
     | 
    
         
             
              )
         
     | 
| 
       111 
     | 
    
         
            -
               
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
      
 113 
     | 
    
         
            +
              if n % 100 == 0
         
     | 
| 
      
 114 
     | 
    
         
            +
                $stdout.putc '.'
         
     | 
| 
      
 115 
     | 
    
         
            +
                $stdout.flush
         
     | 
| 
      
 116 
     | 
    
         
            +
              end
         
     | 
| 
       113 
117 
     | 
    
         
             
            end
         
     | 
| 
       114 
118 
     | 
    
         
             
            puts
         
     | 
| 
       115 
119 
     | 
    
         
             
            puts "Done"
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: UTF-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'benchmark'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'active_record'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            mysql2_opts = {
         
     | 
| 
      
 9 
     | 
    
         
            +
              :adapter => 'mysql2',
         
     | 
| 
      
 10 
     | 
    
         
            +
              :database => 'test',
         
     | 
| 
      
 11 
     | 
    
         
            +
              :pool => 25
         
     | 
| 
      
 12 
     | 
    
         
            +
            }
         
     | 
| 
      
 13 
     | 
    
         
            +
            ActiveRecord::Base.establish_connection(mysql2_opts)
         
     | 
| 
      
 14 
     | 
    
         
            +
            x = Benchmark.realtime do
         
     | 
| 
      
 15 
     | 
    
         
            +
              threads = []
         
     | 
| 
      
 16 
     | 
    
         
            +
              25.times do
         
     | 
| 
      
 17 
     | 
    
         
            +
                threads << Thread.new { ActiveRecord::Base.connection.execute("select sleep(1)") }
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
              threads.each {|t| t.join }
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
      
 21 
     | 
    
         
            +
            puts x
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            mysql2_opts = {
         
     | 
| 
      
 24 
     | 
    
         
            +
              :adapter => 'mysql',
         
     | 
| 
      
 25 
     | 
    
         
            +
              :database => 'test',
         
     | 
| 
      
 26 
     | 
    
         
            +
              :pool => 25
         
     | 
| 
      
 27 
     | 
    
         
            +
            }
         
     | 
| 
      
 28 
     | 
    
         
            +
            ActiveRecord::Base.establish_connection(mysql2_opts)
         
     | 
| 
      
 29 
     | 
    
         
            +
            x = Benchmark.realtime do
         
     | 
| 
      
 30 
     | 
    
         
            +
              threads = []
         
     | 
| 
      
 31 
     | 
    
         
            +
              25.times do
         
     | 
| 
      
 32 
     | 
    
         
            +
                threads << Thread.new { ActiveRecord::Base.connection.execute("select sleep(1)") }
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
              threads.each {|t| t.join }
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
      
 36 
     | 
    
         
            +
            puts x
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            # these results are similar on 1.8.7, 1.9.2 and rbx-head
         
     | 
| 
      
 39 
     | 
    
         
            +
            #
         
     | 
| 
      
 40 
     | 
    
         
            +
            # $ bundle exec ruby benchmarks/threaded.rb
         
     | 
| 
      
 41 
     | 
    
         
            +
            # 1.0774750709533691
         
     | 
| 
      
 42 
     | 
    
         
            +
            #
         
     | 
| 
      
 43 
     | 
    
         
            +
            # and using the mysql gem
         
     | 
| 
      
 44 
     | 
    
         
            +
            # 25.099437952041626
         
     | 
    
        data/ext/mysql2/client.c
    CHANGED
    
    | 
         @@ -1,17 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            #include <mysql2_ext.h>
         
     | 
| 
       2 
2 
     | 
    
         
             
            #include <client.h>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #include <errno.h>
         
     | 
| 
      
 4 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 5 
     | 
    
         
            +
            #include <sys/socket.h>
         
     | 
| 
      
 6 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 7 
     | 
    
         
            +
            #include "wait_for_single_fd.h"
         
     | 
| 
       4 
8 
     | 
    
         | 
| 
       5 
9 
     | 
    
         
             
            VALUE cMysql2Client;
         
     | 
| 
       6 
10 
     | 
    
         
             
            extern VALUE mMysql2, cMysql2Error;
         
     | 
| 
       7 
11 
     | 
    
         
             
            static VALUE intern_encoding_from_charset;
         
     | 
| 
       8 
     | 
    
         
            -
            static  
     | 
| 
      
 12 
     | 
    
         
            +
            static VALUE sym_id, sym_version, sym_async, sym_symbolize_keys, sym_as, sym_array;
         
     | 
| 
       9 
13 
     | 
    
         
             
            static ID intern_merge, intern_error_number_eql, intern_sql_state_eql;
         
     | 
| 
       10 
14 
     | 
    
         | 
| 
       11 
15 
     | 
    
         
             
            #define REQUIRE_OPEN_DB(wrapper) \
         
     | 
| 
       12 
     | 
    
         
            -
              if(wrapper->closed) { \
         
     | 
| 
      
 16 
     | 
    
         
            +
              if(!wrapper->reconnect_enabled && wrapper->closed) { \
         
     | 
| 
       13 
17 
     | 
    
         
             
                rb_raise(cMysql2Error, "closed MySQL connection"); \
         
     | 
| 
       14 
     | 
    
         
            -
                return Qnil; \
         
     | 
| 
       15 
18 
     | 
    
         
             
              }
         
     | 
| 
       16 
19 
     | 
    
         | 
| 
       17 
20 
     | 
    
         
             
            #define MARK_CONN_INACTIVE(conn) \
         
     | 
| 
         @@ -43,6 +46,7 @@ struct nogvl_connect_args { 
     | 
|
| 
       43 
46 
     | 
    
         
             
            struct nogvl_send_query_args {
         
     | 
| 
       44 
47 
     | 
    
         
             
              MYSQL *mysql;
         
     | 
| 
       45 
48 
     | 
    
         
             
              VALUE sql;
         
     | 
| 
      
 49 
     | 
    
         
            +
              mysql_client_wrapper *wrapper;
         
     | 
| 
       46 
50 
     | 
    
         
             
            };
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
       48 
52 
     | 
    
         
             
            /*
         
     | 
| 
         @@ -74,10 +78,24 @@ static void rb_mysql_client_mark(void * wrapper) { 
     | 
|
| 
       74 
78 
     | 
    
         
             
              }
         
     | 
| 
       75 
79 
     | 
    
         
             
            }
         
     | 
| 
       76 
80 
     | 
    
         | 
| 
       77 
     | 
    
         
            -
            static VALUE rb_raise_mysql2_error( 
     | 
| 
       78 
     | 
    
         
            -
              VALUE  
     | 
| 
       79 
     | 
    
         
            -
               
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
      
 81 
     | 
    
         
            +
            static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
         
     | 
| 
      
 82 
     | 
    
         
            +
              VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client));
         
     | 
| 
      
 83 
     | 
    
         
            +
              VALUE rb_sql_state = rb_tainted_str_new2(mysql_sqlstate(wrapper->client));
         
     | 
| 
      
 84 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 85 
     | 
    
         
            +
              rb_encoding *default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
      
 86 
     | 
    
         
            +
              rb_encoding *conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
              rb_enc_associate(rb_error_msg, conn_enc);
         
     | 
| 
      
 89 
     | 
    
         
            +
              rb_enc_associate(rb_sql_state, conn_enc);
         
     | 
| 
      
 90 
     | 
    
         
            +
              if (default_internal_enc) {
         
     | 
| 
      
 91 
     | 
    
         
            +
                rb_error_msg = rb_str_export_to_enc(rb_error_msg, default_internal_enc);
         
     | 
| 
      
 92 
     | 
    
         
            +
                rb_sql_state = rb_str_export_to_enc(rb_sql_state, default_internal_enc);
         
     | 
| 
      
 93 
     | 
    
         
            +
              }
         
     | 
| 
      
 94 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
              VALUE e = rb_exc_new3(cMysql2Error, rb_error_msg);
         
     | 
| 
      
 97 
     | 
    
         
            +
              rb_funcall(e, intern_error_number_eql, 1, UINT2NUM(mysql_errno(wrapper->client)));
         
     | 
| 
      
 98 
     | 
    
         
            +
              rb_funcall(e, intern_sql_state_eql, 1, rb_sql_state);
         
     | 
| 
       81 
99 
     | 
    
         
             
              rb_exc_raise(e);
         
     | 
| 
       82 
100 
     | 
    
         
             
              return Qnil;
         
     | 
| 
       83 
101 
     | 
    
         
             
            }
         
     | 
| 
         @@ -105,10 +123,14 @@ static VALUE nogvl_connect(void *ptr) { 
     | 
|
| 
       105 
123 
     | 
    
         
             
            }
         
     | 
| 
       106 
124 
     | 
    
         | 
| 
       107 
125 
     | 
    
         
             
            static VALUE nogvl_close(void *ptr) {
         
     | 
| 
       108 
     | 
    
         
            -
              mysql_client_wrapper *wrapper 
     | 
| 
      
 126 
     | 
    
         
            +
              mysql_client_wrapper *wrapper;
         
     | 
| 
      
 127 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 128 
     | 
    
         
            +
              int flags;
         
     | 
| 
      
 129 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 130 
     | 
    
         
            +
              wrapper = ptr;
         
     | 
| 
       109 
131 
     | 
    
         
             
              if (!wrapper->closed) {
         
     | 
| 
       110 
132 
     | 
    
         
             
                wrapper->closed = 1;
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
      
 133 
     | 
    
         
            +
                wrapper->active = 0;
         
     | 
| 
       112 
134 
     | 
    
         
             
                /*
         
     | 
| 
       113 
135 
     | 
    
         
             
                 * we'll send a QUIT message to the server, but that message is more of a
         
     | 
| 
       114 
136 
     | 
    
         
             
                 * formality than a hard requirement since the socket is getting shutdown
         
     | 
| 
         @@ -119,12 +141,9 @@ static VALUE nogvl_close(void *ptr) { 
     | 
|
| 
       119 
141 
     | 
    
         
             
                 * so ignore any potential fcntl errors since they don't matter
         
     | 
| 
       120 
142 
     | 
    
         
             
                 */
         
     | 
| 
       121 
143 
     | 
    
         
             
            #ifndef _WIN32
         
     | 
| 
       122 
     | 
    
         
            -
                 
     | 
| 
      
 144 
     | 
    
         
            +
                flags = fcntl(wrapper->client->net.fd, F_GETFL);
         
     | 
| 
       123 
145 
     | 
    
         
             
                if (flags > 0 && !(flags & O_NONBLOCK))
         
     | 
| 
       124 
146 
     | 
    
         
             
                  fcntl(wrapper->client->net.fd, F_SETFL, flags | O_NONBLOCK);
         
     | 
| 
       125 
     | 
    
         
            -
            #else
         
     | 
| 
       126 
     | 
    
         
            -
                u_long iMode = 1;
         
     | 
| 
       127 
     | 
    
         
            -
                ioctlsocket(wrapper->client->net.fd, FIONBIO, &iMode);
         
     | 
| 
       128 
147 
     | 
    
         
             
            #endif
         
     | 
| 
       129 
148 
     | 
    
         | 
| 
       130 
149 
     | 
    
         
             
                mysql_close(wrapper->client);
         
     | 
| 
         @@ -139,7 +158,7 @@ static void rb_mysql_client_free(void * ptr) { 
     | 
|
| 
       139 
158 
     | 
    
         | 
| 
       140 
159 
     | 
    
         
             
              nogvl_close(wrapper);
         
     | 
| 
       141 
160 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
               
     | 
| 
      
 161 
     | 
    
         
            +
              free(ptr);
         
     | 
| 
       143 
162 
     | 
    
         
             
            }
         
     | 
| 
       144 
163 
     | 
    
         | 
| 
       145 
164 
     | 
    
         
             
            static VALUE allocate(VALUE klass) {
         
     | 
| 
         @@ -148,11 +167,37 @@ static VALUE allocate(VALUE klass) { 
     | 
|
| 
       148 
167 
     | 
    
         
             
              obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
         
     | 
| 
       149 
168 
     | 
    
         
             
              wrapper->encoding = Qnil;
         
     | 
| 
       150 
169 
     | 
    
         
             
              wrapper->active = 0;
         
     | 
| 
      
 170 
     | 
    
         
            +
              wrapper->reconnect_enabled = 0;
         
     | 
| 
       151 
171 
     | 
    
         
             
              wrapper->closed = 1;
         
     | 
| 
       152 
172 
     | 
    
         
             
              wrapper->client = (MYSQL*)malloc(sizeof(MYSQL));
         
     | 
| 
       153 
173 
     | 
    
         
             
              return obj;
         
     | 
| 
       154 
174 
     | 
    
         
             
            }
         
     | 
| 
       155 
175 
     | 
    
         | 
| 
      
 176 
     | 
    
         
            +
            static VALUE rb_mysql_client_escape(RB_MYSQL_UNUSED VALUE klass, VALUE str) {
         
     | 
| 
      
 177 
     | 
    
         
            +
              unsigned char *newStr;
         
     | 
| 
      
 178 
     | 
    
         
            +
              VALUE rb_str;
         
     | 
| 
      
 179 
     | 
    
         
            +
              unsigned long newLen, oldLen;
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
              Check_Type(str, T_STRING);
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
              oldLen = RSTRING_LEN(str);
         
     | 
| 
      
 184 
     | 
    
         
            +
              newStr = malloc(oldLen*2+1);
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              newLen = mysql_escape_string((char *)newStr, StringValuePtr(str), oldLen);
         
     | 
| 
      
 187 
     | 
    
         
            +
              if (newLen == oldLen) {
         
     | 
| 
      
 188 
     | 
    
         
            +
                // no need to return a new ruby string if nothing changed
         
     | 
| 
      
 189 
     | 
    
         
            +
                free(newStr);
         
     | 
| 
      
 190 
     | 
    
         
            +
                return str;
         
     | 
| 
      
 191 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 192 
     | 
    
         
            +
                rb_str = rb_str_new((const char*)newStr, newLen);
         
     | 
| 
      
 193 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 194 
     | 
    
         
            +
                rb_enc_copy(rb_str, str);
         
     | 
| 
      
 195 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 196 
     | 
    
         
            +
                free(newStr);
         
     | 
| 
      
 197 
     | 
    
         
            +
                return rb_str;
         
     | 
| 
      
 198 
     | 
    
         
            +
              }
         
     | 
| 
      
 199 
     | 
    
         
            +
            }
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
       156 
201 
     | 
    
         
             
            static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE port, VALUE database, VALUE socket, VALUE flags) {
         
     | 
| 
       157 
202 
     | 
    
         
             
              struct nogvl_connect_args args;
         
     | 
| 
       158 
203 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
         @@ -168,7 +213,7 @@ static VALUE rb_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VALUE po 
     | 
|
| 
       168 
213 
     | 
    
         | 
| 
       169 
214 
     | 
    
         
             
              if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       170 
215 
     | 
    
         
             
                // unable to connect
         
     | 
| 
       171 
     | 
    
         
            -
                return rb_raise_mysql2_error(wrapper 
     | 
| 
      
 216 
     | 
    
         
            +
                return rb_raise_mysql2_error(wrapper);
         
     | 
| 
       172 
217 
     | 
    
         
             
              }
         
     | 
| 
       173 
218 
     | 
    
         | 
| 
       174 
219 
     | 
    
         
             
              return self;
         
     | 
| 
         @@ -206,6 +251,17 @@ static VALUE nogvl_send_query(void *ptr) { 
     | 
|
| 
       206 
251 
     | 
    
         
             
              return rv == 0 ? Qtrue : Qfalse;
         
     | 
| 
       207 
252 
     | 
    
         
             
            }
         
     | 
| 
       208 
253 
     | 
    
         | 
| 
      
 254 
     | 
    
         
            +
            static VALUE do_send_query(void *args) {
         
     | 
| 
      
 255 
     | 
    
         
            +
              struct nogvl_send_query_args *query_args = args;
         
     | 
| 
      
 256 
     | 
    
         
            +
              mysql_client_wrapper *wrapper = query_args->wrapper;
         
     | 
| 
      
 257 
     | 
    
         
            +
              if (rb_thread_blocking_region(nogvl_send_query, args, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
      
 258 
     | 
    
         
            +
                // an error occurred, we're not active anymore
         
     | 
| 
      
 259 
     | 
    
         
            +
                MARK_CONN_INACTIVE(self);
         
     | 
| 
      
 260 
     | 
    
         
            +
                return rb_raise_mysql2_error(wrapper);
         
     | 
| 
      
 261 
     | 
    
         
            +
              }
         
     | 
| 
      
 262 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 263 
     | 
    
         
            +
            }
         
     | 
| 
      
 264 
     | 
    
         
            +
             
     | 
| 
       209 
265 
     | 
    
         
             
            /*
         
     | 
| 
       210 
266 
     | 
    
         
             
             * even though we did rb_thread_select before calling this, a large
         
     | 
| 
       211 
267 
     | 
    
         
             
             * response can overflow the socket buffers and cause us to eventually
         
     | 
| 
         @@ -220,63 +276,161 @@ static VALUE nogvl_read_query_result(void *ptr) { 
     | 
|
| 
       220 
276 
     | 
    
         | 
| 
       221 
277 
     | 
    
         
             
            /* mysql_store_result may (unlikely) read rows off the socket */
         
     | 
| 
       222 
278 
     | 
    
         
             
            static VALUE nogvl_store_result(void *ptr) {
         
     | 
| 
       223 
     | 
    
         
            -
               
     | 
| 
       224 
     | 
    
         
            -
               
     | 
| 
      
 279 
     | 
    
         
            +
              mysql_client_wrapper *wrapper;
         
     | 
| 
      
 280 
     | 
    
         
            +
              MYSQL_RES *result;
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
              wrapper = (mysql_client_wrapper *)ptr;
         
     | 
| 
      
 283 
     | 
    
         
            +
              result = mysql_store_result(wrapper->client);
         
     | 
| 
      
 284 
     | 
    
         
            +
             
     | 
| 
      
 285 
     | 
    
         
            +
              // once our result is stored off, this connection is
         
     | 
| 
      
 286 
     | 
    
         
            +
              // ready for another command to be issued
         
     | 
| 
      
 287 
     | 
    
         
            +
              wrapper->active = 0;
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
              return (VALUE)result;
         
     | 
| 
       225 
290 
     | 
    
         
             
            }
         
     | 
| 
       226 
291 
     | 
    
         | 
| 
       227 
292 
     | 
    
         
             
            static VALUE rb_mysql_client_async_result(VALUE self) {
         
     | 
| 
       228 
293 
     | 
    
         
             
              MYSQL_RES * result;
         
     | 
| 
      
 294 
     | 
    
         
            +
              VALUE resultObj;
         
     | 
| 
      
 295 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 296 
     | 
    
         
            +
              mysql2_result_wrapper * result_wrapper;
         
     | 
| 
      
 297 
     | 
    
         
            +
            #endif
         
     | 
| 
       229 
298 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       230 
299 
     | 
    
         | 
| 
      
 300 
     | 
    
         
            +
              // if we're not waiting on a result, do nothing
         
     | 
| 
      
 301 
     | 
    
         
            +
              if (!wrapper->active)
         
     | 
| 
      
 302 
     | 
    
         
            +
                return Qnil;
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
       231 
304 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       232 
305 
     | 
    
         
             
              if (rb_thread_blocking_region(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       233 
306 
     | 
    
         
             
                // an error occurred, mark this connection inactive
         
     | 
| 
       234 
307 
     | 
    
         
             
                MARK_CONN_INACTIVE(self);
         
     | 
| 
       235 
     | 
    
         
            -
                return rb_raise_mysql2_error(wrapper 
     | 
| 
      
 308 
     | 
    
         
            +
                return rb_raise_mysql2_error(wrapper);
         
     | 
| 
       236 
309 
     | 
    
         
             
              }
         
     | 
| 
       237 
310 
     | 
    
         | 
| 
       238 
     | 
    
         
            -
              result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper 
     | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
       240 
     | 
    
         
            -
              // we have our result, mark this connection inactive
         
     | 
| 
       241 
     | 
    
         
            -
              MARK_CONN_INACTIVE(self);
         
     | 
| 
      
 311 
     | 
    
         
            +
              result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
         
     | 
| 
       242 
312 
     | 
    
         | 
| 
       243 
313 
     | 
    
         
             
              if (result == NULL) {
         
     | 
| 
       244 
314 
     | 
    
         
             
                if (mysql_field_count(wrapper->client) != 0) {
         
     | 
| 
       245 
     | 
    
         
            -
                  rb_raise_mysql2_error(wrapper 
     | 
| 
      
 315 
     | 
    
         
            +
                  rb_raise_mysql2_error(wrapper);
         
     | 
| 
       246 
316 
     | 
    
         
             
                }
         
     | 
| 
       247 
317 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       248 
318 
     | 
    
         
             
              }
         
     | 
| 
       249 
319 
     | 
    
         | 
| 
       250 
     | 
    
         
            -
               
     | 
| 
      
 320 
     | 
    
         
            +
              resultObj = rb_mysql_result_to_obj(result);
         
     | 
| 
       251 
321 
     | 
    
         
             
              // pass-through query options for result construction later
         
     | 
| 
       252 
322 
     | 
    
         
             
              rb_iv_set(resultObj, "@query_options", rb_funcall(rb_iv_get(self, "@query_options"), rb_intern("dup"), 0));
         
     | 
| 
       253 
323 
     | 
    
         | 
| 
       254 
324 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       255 
     | 
    
         
            -
              mysql2_result_wrapper * result_wrapper;
         
     | 
| 
       256 
325 
     | 
    
         
             
              GetMysql2Result(resultObj, result_wrapper);
         
     | 
| 
       257 
326 
     | 
    
         
             
              result_wrapper->encoding = wrapper->encoding;
         
     | 
| 
       258 
327 
     | 
    
         
             
            #endif
         
     | 
| 
       259 
328 
     | 
    
         
             
              return resultObj;
         
     | 
| 
       260 
329 
     | 
    
         
             
            }
         
     | 
| 
       261 
330 
     | 
    
         | 
| 
      
 331 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 332 
     | 
    
         
            +
            struct async_query_args {
         
     | 
| 
      
 333 
     | 
    
         
            +
              int fd;
         
     | 
| 
      
 334 
     | 
    
         
            +
              VALUE self;
         
     | 
| 
      
 335 
     | 
    
         
            +
            };
         
     | 
| 
      
 336 
     | 
    
         
            +
             
     | 
| 
      
 337 
     | 
    
         
            +
            static VALUE disconnect_and_raise(VALUE self, VALUE error) {
         
     | 
| 
      
 338 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
              wrapper->closed = 1;
         
     | 
| 
      
 341 
     | 
    
         
            +
              wrapper->active = 0;
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
              // manually close the socket for read/write
         
     | 
| 
      
 344 
     | 
    
         
            +
              // this feels dirty, but is there another way?
         
     | 
| 
      
 345 
     | 
    
         
            +
              shutdown(wrapper->client->net.fd, 2);
         
     | 
| 
      
 346 
     | 
    
         
            +
             
     | 
| 
      
 347 
     | 
    
         
            +
              rb_exc_raise(error);
         
     | 
| 
      
 348 
     | 
    
         
            +
             
     | 
| 
      
 349 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 350 
     | 
    
         
            +
            }
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
      
 352 
     | 
    
         
            +
            static VALUE do_query(void *args) {
         
     | 
| 
      
 353 
     | 
    
         
            +
              struct async_query_args *async_args;
         
     | 
| 
      
 354 
     | 
    
         
            +
              struct timeval tv;
         
     | 
| 
      
 355 
     | 
    
         
            +
              struct timeval* tvp;
         
     | 
| 
      
 356 
     | 
    
         
            +
              long int sec;
         
     | 
| 
      
 357 
     | 
    
         
            +
              int retval;
         
     | 
| 
      
 358 
     | 
    
         
            +
              VALUE read_timeout;
         
     | 
| 
      
 359 
     | 
    
         
            +
             
     | 
| 
      
 360 
     | 
    
         
            +
              async_args = (struct async_query_args *)args;
         
     | 
| 
      
 361 
     | 
    
         
            +
              read_timeout = rb_iv_get(async_args->self, "@read_timeout");
         
     | 
| 
      
 362 
     | 
    
         
            +
             
     | 
| 
      
 363 
     | 
    
         
            +
              tvp = NULL;
         
     | 
| 
      
 364 
     | 
    
         
            +
              if (!NIL_P(read_timeout)) {
         
     | 
| 
      
 365 
     | 
    
         
            +
                Check_Type(read_timeout, T_FIXNUM);
         
     | 
| 
      
 366 
     | 
    
         
            +
                tvp = &tv;
         
     | 
| 
      
 367 
     | 
    
         
            +
                sec = FIX2INT(read_timeout);
         
     | 
| 
      
 368 
     | 
    
         
            +
                // TODO: support partial seconds?
         
     | 
| 
      
 369 
     | 
    
         
            +
                // also, this check is here for sanity, we also check up in Ruby
         
     | 
| 
      
 370 
     | 
    
         
            +
                if (sec >= 0) {
         
     | 
| 
      
 371 
     | 
    
         
            +
                  tvp->tv_sec = sec;
         
     | 
| 
      
 372 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 373 
     | 
    
         
            +
                  rb_raise(cMysql2Error, "read_timeout must be a positive integer, you passed %ld", sec);
         
     | 
| 
      
 374 
     | 
    
         
            +
                }
         
     | 
| 
      
 375 
     | 
    
         
            +
                tvp->tv_usec = 0;
         
     | 
| 
      
 376 
     | 
    
         
            +
              }
         
     | 
| 
      
 377 
     | 
    
         
            +
             
     | 
| 
      
 378 
     | 
    
         
            +
              for(;;) {
         
     | 
| 
      
 379 
     | 
    
         
            +
                retval = rb_wait_for_single_fd(async_args->fd, RB_WAITFD_IN, tvp);
         
     | 
| 
      
 380 
     | 
    
         
            +
             
     | 
| 
      
 381 
     | 
    
         
            +
                if (retval == 0) {
         
     | 
| 
      
 382 
     | 
    
         
            +
                  rb_raise(cMysql2Error, "Timeout waiting for a response from the last query. (waited %d seconds)", FIX2INT(read_timeout));
         
     | 
| 
      
 383 
     | 
    
         
            +
                }
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                if (retval < 0) {
         
     | 
| 
      
 386 
     | 
    
         
            +
                  rb_sys_fail(0);
         
     | 
| 
      
 387 
     | 
    
         
            +
                }
         
     | 
| 
      
 388 
     | 
    
         
            +
             
     | 
| 
      
 389 
     | 
    
         
            +
                if (retval > 0) {
         
     | 
| 
      
 390 
     | 
    
         
            +
                  break;
         
     | 
| 
      
 391 
     | 
    
         
            +
                }
         
     | 
| 
      
 392 
     | 
    
         
            +
              }
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 395 
     | 
    
         
            +
            }
         
     | 
| 
      
 396 
     | 
    
         
            +
            #else
         
     | 
| 
      
 397 
     | 
    
         
            +
            static VALUE finish_and_mark_inactive(void *args) {
         
     | 
| 
      
 398 
     | 
    
         
            +
              VALUE self;
         
     | 
| 
      
 399 
     | 
    
         
            +
              MYSQL_RES *result;
         
     | 
| 
      
 400 
     | 
    
         
            +
             
     | 
| 
      
 401 
     | 
    
         
            +
              self = (VALUE)args;
         
     | 
| 
      
 402 
     | 
    
         
            +
             
     | 
| 
      
 403 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
              if (wrapper->active) {
         
     | 
| 
      
 406 
     | 
    
         
            +
                // if we got here, the result hasn't been read off the wire yet
         
     | 
| 
      
 407 
     | 
    
         
            +
                // so lets do that and then throw it away because we have no way
         
     | 
| 
      
 408 
     | 
    
         
            +
                // of getting it back up to the caller from here
         
     | 
| 
      
 409 
     | 
    
         
            +
                result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, wrapper, RUBY_UBF_IO, 0);
         
     | 
| 
      
 410 
     | 
    
         
            +
                mysql_free_result(result);
         
     | 
| 
      
 411 
     | 
    
         
            +
             
     | 
| 
      
 412 
     | 
    
         
            +
                wrapper->active = 0;
         
     | 
| 
      
 413 
     | 
    
         
            +
              }
         
     | 
| 
      
 414 
     | 
    
         
            +
             
     | 
| 
      
 415 
     | 
    
         
            +
              return Qnil;
         
     | 
| 
      
 416 
     | 
    
         
            +
            }
         
     | 
| 
      
 417 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
       262 
419 
     | 
    
         
             
            static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
         
     | 
| 
      
 420 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 421 
     | 
    
         
            +
              struct async_query_args async_args;
         
     | 
| 
      
 422 
     | 
    
         
            +
            #endif
         
     | 
| 
       263 
423 
     | 
    
         
             
              struct nogvl_send_query_args args;
         
     | 
| 
       264 
     | 
    
         
            -
              fd_set fdset;
         
     | 
| 
       265 
     | 
    
         
            -
              int fd, retval;
         
     | 
| 
       266 
424 
     | 
    
         
             
              int async = 0;
         
     | 
| 
       267 
425 
     | 
    
         
             
              VALUE opts, defaults;
         
     | 
| 
      
 426 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 427 
     | 
    
         
            +
              rb_encoding *conn_enc;
         
     | 
| 
      
 428 
     | 
    
         
            +
            #endif
         
     | 
| 
       268 
429 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       269 
430 
     | 
    
         | 
| 
       270 
431 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       271 
432 
     | 
    
         
             
              args.mysql = wrapper->client;
         
     | 
| 
       272 
433 
     | 
    
         | 
| 
       273 
     | 
    
         
            -
              // see if this connection is still waiting on a result from a previous query
         
     | 
| 
       274 
     | 
    
         
            -
              if (wrapper->active == 0) {
         
     | 
| 
       275 
     | 
    
         
            -
                // mark this connection active
         
     | 
| 
       276 
     | 
    
         
            -
                wrapper->active = 1;
         
     | 
| 
       277 
     | 
    
         
            -
              } else {
         
     | 
| 
       278 
     | 
    
         
            -
                rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
         
     | 
| 
       279 
     | 
    
         
            -
              }
         
     | 
| 
       280 
434 
     | 
    
         | 
| 
       281 
435 
     | 
    
         
             
              defaults = rb_iv_get(self, "@query_options");
         
     | 
| 
       282 
436 
     | 
    
         
             
              if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
         
     | 
| 
         @@ -290,85 +444,96 @@ static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) { 
     | 
|
| 
       290 
444 
     | 
    
         
             
                opts = defaults;
         
     | 
| 
       291 
445 
     | 
    
         
             
              }
         
     | 
| 
       292 
446 
     | 
    
         | 
| 
      
 447 
     | 
    
         
            +
              Check_Type(args.sql, T_STRING);
         
     | 
| 
       293 
448 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       294 
     | 
    
         
            -
               
     | 
| 
      
 449 
     | 
    
         
            +
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       295 
450 
     | 
    
         
             
              // ensure the string is in the encoding the connection is expecting
         
     | 
| 
       296 
451 
     | 
    
         
             
              args.sql = rb_str_export_to_enc(args.sql, conn_enc);
         
     | 
| 
       297 
452 
     | 
    
         
             
            #endif
         
     | 
| 
       298 
453 
     | 
    
         | 
| 
       299 
     | 
    
         
            -
              if  
     | 
| 
       300 
     | 
    
         
            -
             
     | 
| 
       301 
     | 
    
         
            -
                 
     | 
| 
       302 
     | 
    
         
            -
                 
     | 
| 
      
 454 
     | 
    
         
            +
              // see if this connection is still waiting on a result from a previous query
         
     | 
| 
      
 455 
     | 
    
         
            +
              if (wrapper->active == 0) {
         
     | 
| 
      
 456 
     | 
    
         
            +
                // mark this connection active
         
     | 
| 
      
 457 
     | 
    
         
            +
                wrapper->active = 1;
         
     | 
| 
      
 458 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 459 
     | 
    
         
            +
                rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
         
     | 
| 
       303 
460 
     | 
    
         
             
              }
         
     | 
| 
       304 
461 
     | 
    
         | 
| 
      
 462 
     | 
    
         
            +
              args.wrapper = wrapper;
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
      
 465 
     | 
    
         
            +
              rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
         
     | 
| 
      
 466 
     | 
    
         
            +
             
     | 
| 
       305 
467 
     | 
    
         
             
              if (!async) {
         
     | 
| 
       306 
     | 
    
         
            -
                 
     | 
| 
       307 
     | 
    
         
            -
                 
     | 
| 
       308 
     | 
    
         
            -
                fd = wrapper->client->net.fd;
         
     | 
| 
       309 
     | 
    
         
            -
                for(;;) {
         
     | 
| 
       310 
     | 
    
         
            -
                  FD_ZERO(&fdset);
         
     | 
| 
       311 
     | 
    
         
            -
                  FD_SET(fd, &fdset);
         
     | 
| 
       312 
     | 
    
         
            -
             
     | 
| 
       313 
     | 
    
         
            -
                  retval = rb_thread_select(fd + 1, &fdset, NULL, NULL, NULL);
         
     | 
| 
       314 
     | 
    
         
            -
             
     | 
| 
       315 
     | 
    
         
            -
                  if (retval < 0) {
         
     | 
| 
       316 
     | 
    
         
            -
                    rb_sys_fail(0);
         
     | 
| 
       317 
     | 
    
         
            -
                  }
         
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
       319 
     | 
    
         
            -
                  if (retval > 0) {
         
     | 
| 
       320 
     | 
    
         
            -
                    break;
         
     | 
| 
       321 
     | 
    
         
            -
                  }
         
     | 
| 
       322 
     | 
    
         
            -
                }
         
     | 
| 
      
 468 
     | 
    
         
            +
                async_args.fd = wrapper->client->net.fd;
         
     | 
| 
      
 469 
     | 
    
         
            +
                async_args.self = self;
         
     | 
| 
       323 
470 
     | 
    
         | 
| 
       324 
     | 
    
         
            -
                VALUE  
     | 
| 
      
 471 
     | 
    
         
            +
                rb_rescue2(do_query, (VALUE)&async_args, disconnect_and_raise, self, rb_eException, (VALUE)0);
         
     | 
| 
       325 
472 
     | 
    
         | 
| 
       326 
     | 
    
         
            -
                return  
     | 
| 
      
 473 
     | 
    
         
            +
                return rb_mysql_client_async_result(self);
         
     | 
| 
       327 
474 
     | 
    
         
             
              } else {
         
     | 
| 
       328 
475 
     | 
    
         
             
                return Qnil;
         
     | 
| 
       329 
476 
     | 
    
         
             
              }
         
     | 
| 
      
 477 
     | 
    
         
            +
            #else
         
     | 
| 
      
 478 
     | 
    
         
            +
              do_send_query(&args);
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
      
 480 
     | 
    
         
            +
              // this will just block until the result is ready
         
     | 
| 
      
 481 
     | 
    
         
            +
              return rb_ensure(rb_mysql_client_async_result, self, finish_and_mark_inactive, self);
         
     | 
| 
      
 482 
     | 
    
         
            +
            #endif
         
     | 
| 
       330 
483 
     | 
    
         
             
            }
         
     | 
| 
       331 
484 
     | 
    
         | 
| 
       332 
     | 
    
         
            -
            static VALUE  
     | 
| 
       333 
     | 
    
         
            -
               
     | 
| 
      
 485 
     | 
    
         
            +
            static VALUE rb_mysql_client_real_escape(VALUE self, VALUE str) {
         
     | 
| 
      
 486 
     | 
    
         
            +
              unsigned char *newStr;
         
     | 
| 
      
 487 
     | 
    
         
            +
              VALUE rb_str;
         
     | 
| 
       334 
488 
     | 
    
         
             
              unsigned long newLen, oldLen;
         
     | 
| 
      
 489 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 490 
     | 
    
         
            +
              rb_encoding *default_internal_enc;
         
     | 
| 
      
 491 
     | 
    
         
            +
              rb_encoding *conn_enc;
         
     | 
| 
      
 492 
     | 
    
         
            +
            #endif
         
     | 
| 
       335 
493 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       336 
494 
     | 
    
         | 
| 
       337 
495 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       338 
496 
     | 
    
         
             
              Check_Type(str, T_STRING);
         
     | 
| 
       339 
497 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       340 
     | 
    
         
            -
               
     | 
| 
       341 
     | 
    
         
            -
               
     | 
| 
      
 498 
     | 
    
         
            +
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
      
 499 
     | 
    
         
            +
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       342 
500 
     | 
    
         
             
              // ensure the string is in the encoding the connection is expecting
         
     | 
| 
       343 
501 
     | 
    
         
             
              str = rb_str_export_to_enc(str, conn_enc);
         
     | 
| 
       344 
502 
     | 
    
         
             
            #endif
         
     | 
| 
       345 
503 
     | 
    
         | 
| 
       346 
504 
     | 
    
         
             
              oldLen = RSTRING_LEN(str);
         
     | 
| 
       347 
     | 
    
         
            -
              newStr =  
     | 
| 
      
 505 
     | 
    
         
            +
              newStr = malloc(oldLen*2+1);
         
     | 
| 
       348 
506 
     | 
    
         | 
| 
       349 
     | 
    
         
            -
              newLen = mysql_real_escape_string(wrapper->client,  
     | 
| 
      
 507 
     | 
    
         
            +
              newLen = mysql_real_escape_string(wrapper->client, (char *)newStr, StringValuePtr(str), oldLen);
         
     | 
| 
       350 
508 
     | 
    
         
             
              if (newLen == oldLen) {
         
     | 
| 
       351 
509 
     | 
    
         
             
                // no need to return a new ruby string if nothing changed
         
     | 
| 
      
 510 
     | 
    
         
            +
                free(newStr);
         
     | 
| 
       352 
511 
     | 
    
         
             
                return str;
         
     | 
| 
       353 
512 
     | 
    
         
             
              } else {
         
     | 
| 
       354 
     | 
    
         
            -
                 
     | 
| 
      
 513 
     | 
    
         
            +
                rb_str = rb_str_new((const char*)newStr, newLen);
         
     | 
| 
       355 
514 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       356 
     | 
    
         
            -
                rb_enc_associate( 
     | 
| 
      
 515 
     | 
    
         
            +
                rb_enc_associate(rb_str, conn_enc);
         
     | 
| 
       357 
516 
     | 
    
         
             
                if (default_internal_enc) {
         
     | 
| 
       358 
     | 
    
         
            -
                   
     | 
| 
      
 517 
     | 
    
         
            +
                  rb_str = rb_str_export_to_enc(rb_str, default_internal_enc);
         
     | 
| 
       359 
518 
     | 
    
         
             
                }
         
     | 
| 
       360 
519 
     | 
    
         
             
            #endif
         
     | 
| 
       361 
     | 
    
         
            -
                 
     | 
| 
      
 520 
     | 
    
         
            +
                free(newStr);
         
     | 
| 
      
 521 
     | 
    
         
            +
                return rb_str;
         
     | 
| 
       362 
522 
     | 
    
         
             
              }
         
     | 
| 
       363 
523 
     | 
    
         
             
            }
         
     | 
| 
       364 
524 
     | 
    
         | 
| 
       365 
525 
     | 
    
         
             
            static VALUE rb_mysql_client_info(VALUE self) {
         
     | 
| 
       366 
     | 
    
         
            -
              VALUE version 
     | 
| 
      
 526 
     | 
    
         
            +
              VALUE version, client_info;
         
     | 
| 
      
 527 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 528 
     | 
    
         
            +
              rb_encoding *default_internal_enc;
         
     | 
| 
      
 529 
     | 
    
         
            +
              rb_encoding *conn_enc;
         
     | 
| 
      
 530 
     | 
    
         
            +
            #endif
         
     | 
| 
       367 
531 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
      
 532 
     | 
    
         
            +
              version = rb_hash_new();
         
     | 
| 
       368 
533 
     | 
    
         | 
| 
       369 
534 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       370 
     | 
    
         
            -
               
     | 
| 
       371 
     | 
    
         
            -
               
     | 
| 
      
 535 
     | 
    
         
            +
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
      
 536 
     | 
    
         
            +
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       372 
537 
     | 
    
         
             
            #endif
         
     | 
| 
       373 
538 
     | 
    
         | 
| 
       374 
539 
     | 
    
         
             
              rb_hash_aset(version, sym_id, LONG2NUM(mysql_get_client_version()));
         
     | 
| 
         @@ -385,12 +550,16 @@ static VALUE rb_mysql_client_info(VALUE self) { 
     | 
|
| 
       385 
550 
     | 
    
         | 
| 
       386 
551 
     | 
    
         
             
            static VALUE rb_mysql_client_server_info(VALUE self) {
         
     | 
| 
       387 
552 
     | 
    
         
             
              VALUE version, server_info;
         
     | 
| 
      
 553 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 554 
     | 
    
         
            +
              rb_encoding *default_internal_enc;
         
     | 
| 
      
 555 
     | 
    
         
            +
              rb_encoding *conn_enc;
         
     | 
| 
      
 556 
     | 
    
         
            +
            #endif
         
     | 
| 
       388 
557 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       389 
558 
     | 
    
         | 
| 
       390 
559 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       391 
560 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       392 
     | 
    
         
            -
               
     | 
| 
       393 
     | 
    
         
            -
               
     | 
| 
      
 561 
     | 
    
         
            +
              default_internal_enc = rb_default_internal_encoding();
         
     | 
| 
      
 562 
     | 
    
         
            +
              conn_enc = rb_to_encoding(wrapper->encoding);
         
     | 
| 
       394 
563 
     | 
    
         
             
            #endif
         
     | 
| 
       395 
564 
     | 
    
         | 
| 
       396 
565 
     | 
    
         
             
              version = rb_hash_new();
         
     | 
| 
         @@ -408,8 +577,13 @@ static VALUE rb_mysql_client_server_info(VALUE self) { 
     | 
|
| 
       408 
577 
     | 
    
         | 
| 
       409 
578 
     | 
    
         
             
            static VALUE rb_mysql_client_socket(VALUE self) {
         
     | 
| 
       410 
579 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
      
 580 
     | 
    
         
            +
            #ifndef _WIN32
         
     | 
| 
       411 
581 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       412 
     | 
    
         
            -
               
     | 
| 
      
 582 
     | 
    
         
            +
              int fd_set_fd = wrapper->client->net.fd;
         
     | 
| 
      
 583 
     | 
    
         
            +
              return INT2NUM(fd_set_fd);
         
     | 
| 
      
 584 
     | 
    
         
            +
            #else
         
     | 
| 
      
 585 
     | 
    
         
            +
              rb_raise(cMysql2Error, "Raw access to the mysql file descriptor isn't supported on Windows");
         
     | 
| 
      
 586 
     | 
    
         
            +
            #endif
         
     | 
| 
       413 
587 
     | 
    
         
             
            }
         
     | 
| 
       414 
588 
     | 
    
         | 
| 
       415 
589 
     | 
    
         
             
            static VALUE rb_mysql_client_last_id(VALUE self) {
         
     | 
| 
         @@ -419,17 +593,49 @@ static VALUE rb_mysql_client_last_id(VALUE self) { 
     | 
|
| 
       419 
593 
     | 
    
         
             
            }
         
     | 
| 
       420 
594 
     | 
    
         | 
| 
       421 
595 
     | 
    
         
             
            static VALUE rb_mysql_client_affected_rows(VALUE self) {
         
     | 
| 
       422 
     | 
    
         
            -
              GET_CLIENT(self);
         
     | 
| 
       423 
596 
     | 
    
         
             
              my_ulonglong retVal;
         
     | 
| 
      
 597 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
       424 
598 
     | 
    
         | 
| 
       425 
599 
     | 
    
         
             
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
       426 
600 
     | 
    
         
             
              retVal = mysql_affected_rows(wrapper->client);
         
     | 
| 
       427 
601 
     | 
    
         
             
              if (retVal == (my_ulonglong)-1) {
         
     | 
| 
       428 
     | 
    
         
            -
                rb_raise_mysql2_error(wrapper 
     | 
| 
      
 602 
     | 
    
         
            +
                rb_raise_mysql2_error(wrapper);
         
     | 
| 
       429 
603 
     | 
    
         
             
              }
         
     | 
| 
       430 
604 
     | 
    
         
             
              return ULL2NUM(retVal);
         
     | 
| 
       431 
605 
     | 
    
         
             
            }
         
     | 
| 
       432 
606 
     | 
    
         | 
| 
      
 607 
     | 
    
         
            +
            static VALUE rb_mysql_client_thread_id(VALUE self) {
         
     | 
| 
      
 608 
     | 
    
         
            +
              unsigned long retVal;
         
     | 
| 
      
 609 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 610 
     | 
    
         
            +
             
     | 
| 
      
 611 
     | 
    
         
            +
              REQUIRE_OPEN_DB(wrapper);
         
     | 
| 
      
 612 
     | 
    
         
            +
              retVal = mysql_thread_id(wrapper->client);
         
     | 
| 
      
 613 
     | 
    
         
            +
              return ULL2NUM(retVal);
         
     | 
| 
      
 614 
     | 
    
         
            +
            }
         
     | 
| 
      
 615 
     | 
    
         
            +
             
     | 
| 
      
 616 
     | 
    
         
            +
            static VALUE nogvl_ping(void *ptr) {
         
     | 
| 
      
 617 
     | 
    
         
            +
              MYSQL *client = ptr;
         
     | 
| 
      
 618 
     | 
    
         
            +
             
     | 
| 
      
 619 
     | 
    
         
            +
              return mysql_ping(client) == 0 ? Qtrue : Qfalse;
         
     | 
| 
      
 620 
     | 
    
         
            +
            }
         
     | 
| 
      
 621 
     | 
    
         
            +
             
     | 
| 
      
 622 
     | 
    
         
            +
            static VALUE rb_mysql_client_ping(VALUE self) {
         
     | 
| 
      
 623 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 624 
     | 
    
         
            +
             
     | 
| 
      
 625 
     | 
    
         
            +
              if (wrapper->closed) {
         
     | 
| 
      
 626 
     | 
    
         
            +
                return Qfalse;
         
     | 
| 
      
 627 
     | 
    
         
            +
              } else {
         
     | 
| 
      
 628 
     | 
    
         
            +
                return rb_thread_blocking_region(nogvl_ping, wrapper->client, RUBY_UBF_IO, 0);
         
     | 
| 
      
 629 
     | 
    
         
            +
              }
         
     | 
| 
      
 630 
     | 
    
         
            +
            }
         
     | 
| 
      
 631 
     | 
    
         
            +
             
     | 
| 
      
 632 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 633 
     | 
    
         
            +
            static VALUE rb_mysql_client_encoding(VALUE self) {
         
     | 
| 
      
 634 
     | 
    
         
            +
              GET_CLIENT(self);
         
     | 
| 
      
 635 
     | 
    
         
            +
              return wrapper->encoding;
         
     | 
| 
      
 636 
     | 
    
         
            +
            }
         
     | 
| 
      
 637 
     | 
    
         
            +
            #endif
         
     | 
| 
      
 638 
     | 
    
         
            +
             
     | 
| 
       433 
639 
     | 
    
         
             
            static VALUE set_reconnect(VALUE self, VALUE value) {
         
     | 
| 
       434 
640 
     | 
    
         
             
              my_bool reconnect;
         
     | 
| 
       435 
641 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
         @@ -437,6 +643,7 @@ static VALUE set_reconnect(VALUE self, VALUE value) { 
     | 
|
| 
       437 
643 
     | 
    
         
             
              if(!NIL_P(value)) {
         
     | 
| 
       438 
644 
     | 
    
         
             
                reconnect = value == Qfalse ? 0 : 1;
         
     | 
| 
       439 
645 
     | 
    
         | 
| 
      
 646 
     | 
    
         
            +
                wrapper->reconnect_enabled = reconnect;
         
     | 
| 
       440 
647 
     | 
    
         
             
                /* set default reconnect behavior */
         
     | 
| 
       441 
648 
     | 
    
         
             
                if (mysql_options(wrapper->client, MYSQL_OPT_RECONNECT, &reconnect)) {
         
     | 
| 
       442 
649 
     | 
    
         
             
                  /* TODO: warning - unable to set reconnect behavior */
         
     | 
| 
         @@ -465,13 +672,16 @@ static VALUE set_connect_timeout(VALUE self, VALUE value) { 
     | 
|
| 
       465 
672 
     | 
    
         | 
| 
       466 
673 
     | 
    
         
             
            static VALUE set_charset_name(VALUE self, VALUE value) {
         
     | 
| 
       467 
674 
     | 
    
         
             
              char * charset_name;
         
     | 
| 
      
 675 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 676 
     | 
    
         
            +
              VALUE new_encoding;
         
     | 
| 
      
 677 
     | 
    
         
            +
            #endif
         
     | 
| 
       468 
678 
     | 
    
         
             
              GET_CLIENT(self);
         
     | 
| 
       469 
679 
     | 
    
         | 
| 
       470 
680 
     | 
    
         
             
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
       471 
     | 
    
         
            -
              VALUE new_encoding;
         
     | 
| 
       472 
681 
     | 
    
         
             
              new_encoding = rb_funcall(cMysql2Client, intern_encoding_from_charset, 1, value);
         
     | 
| 
       473 
682 
     | 
    
         
             
              if (new_encoding == Qnil) {
         
     | 
| 
       474 
     | 
    
         
            -
                 
     | 
| 
      
 683 
     | 
    
         
            +
                VALUE inspect = rb_inspect(value);
         
     | 
| 
      
 684 
     | 
    
         
            +
                rb_raise(cMysql2Error, "Unsupported charset: '%s'", RSTRING_PTR(inspect));
         
     | 
| 
       475 
685 
     | 
    
         
             
              } else {
         
     | 
| 
       476 
686 
     | 
    
         
             
                if (wrapper->encoding == Qnil) {
         
     | 
| 
       477 
687 
     | 
    
         
             
                  wrapper->encoding = new_encoding;
         
     | 
| 
         @@ -509,7 +719,7 @@ static VALUE init_connection(VALUE self) { 
     | 
|
| 
       509 
719 
     | 
    
         | 
| 
       510 
720 
     | 
    
         
             
              if (rb_thread_blocking_region(nogvl_init, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
         
     | 
| 
       511 
721 
     | 
    
         
             
                /* TODO: warning - not enough memory? */
         
     | 
| 
       512 
     | 
    
         
            -
                return rb_raise_mysql2_error(wrapper 
     | 
| 
      
 722 
     | 
    
         
            +
                return rb_raise_mysql2_error(wrapper);
         
     | 
| 
       513 
723 
     | 
    
         
             
              }
         
     | 
| 
       514 
724 
     | 
    
         | 
| 
       515 
725 
     | 
    
         
             
              wrapper->closed = 0;
         
     | 
| 
         @@ -517,19 +727,43 @@ static VALUE init_connection(VALUE self) { 
     | 
|
| 
       517 
727 
     | 
    
         
             
            }
         
     | 
| 
       518 
728 
     | 
    
         | 
| 
       519 
729 
     | 
    
         
             
            void init_mysql2_client() {
         
     | 
| 
      
 730 
     | 
    
         
            +
              // verify the libmysql we're about to use was the version we were built against
         
     | 
| 
      
 731 
     | 
    
         
            +
              // https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99
         
     | 
| 
      
 732 
     | 
    
         
            +
              int i;
         
     | 
| 
      
 733 
     | 
    
         
            +
              int dots = 0;
         
     | 
| 
      
 734 
     | 
    
         
            +
              const char *lib = mysql_get_client_info();
         
     | 
| 
      
 735 
     | 
    
         
            +
              for (i = 0; lib[i] != 0 && MYSQL_SERVER_VERSION[i] != 0; i++) {
         
     | 
| 
      
 736 
     | 
    
         
            +
                if (lib[i] == '.') {
         
     | 
| 
      
 737 
     | 
    
         
            +
                  dots++;
         
     | 
| 
      
 738 
     | 
    
         
            +
                          // we only compare MAJOR and MINOR
         
     | 
| 
      
 739 
     | 
    
         
            +
                  if (dots == 2) break;
         
     | 
| 
      
 740 
     | 
    
         
            +
                }
         
     | 
| 
      
 741 
     | 
    
         
            +
                if (lib[i] != MYSQL_SERVER_VERSION[i]) {
         
     | 
| 
      
 742 
     | 
    
         
            +
                  rb_raise(rb_eRuntimeError, "Incorrect MySQL client library version! This gem was compiled for %s but the client library is %s.", MYSQL_SERVER_VERSION, lib);
         
     | 
| 
      
 743 
     | 
    
         
            +
                  return;
         
     | 
| 
      
 744 
     | 
    
         
            +
                }
         
     | 
| 
      
 745 
     | 
    
         
            +
              }
         
     | 
| 
      
 746 
     | 
    
         
            +
             
     | 
| 
       520 
747 
     | 
    
         
             
              cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
         
     | 
| 
       521 
748 
     | 
    
         | 
| 
       522 
749 
     | 
    
         
             
              rb_define_alloc_func(cMysql2Client, allocate);
         
     | 
| 
       523 
750 
     | 
    
         | 
| 
      
 751 
     | 
    
         
            +
              rb_define_singleton_method(cMysql2Client, "escape", rb_mysql_client_escape, 1);
         
     | 
| 
      
 752 
     | 
    
         
            +
             
     | 
| 
       524 
753 
     | 
    
         
             
              rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
         
     | 
| 
       525 
754 
     | 
    
         
             
              rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
         
     | 
| 
       526 
     | 
    
         
            -
              rb_define_method(cMysql2Client, "escape",  
     | 
| 
      
 755 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "escape", rb_mysql_client_real_escape, 1);
         
     | 
| 
       527 
756 
     | 
    
         
             
              rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
         
     | 
| 
       528 
757 
     | 
    
         
             
              rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
         
     | 
| 
       529 
758 
     | 
    
         
             
              rb_define_method(cMysql2Client, "socket", rb_mysql_client_socket, 0);
         
     | 
| 
       530 
759 
     | 
    
         
             
              rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
         
     | 
| 
       531 
760 
     | 
    
         
             
              rb_define_method(cMysql2Client, "last_id", rb_mysql_client_last_id, 0);
         
     | 
| 
       532 
761 
     | 
    
         
             
              rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
         
     | 
| 
      
 762 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
         
     | 
| 
      
 763 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
         
     | 
| 
      
 764 
     | 
    
         
            +
            #ifdef HAVE_RUBY_ENCODING_H
         
     | 
| 
      
 765 
     | 
    
         
            +
              rb_define_method(cMysql2Client, "encoding", rb_mysql_client_encoding, 0);
         
     | 
| 
      
 766 
     | 
    
         
            +
            #endif
         
     | 
| 
       533 
767 
     | 
    
         | 
| 
       534 
768 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "reconnect=", set_reconnect, 1);
         
     | 
| 
       535 
769 
     | 
    
         
             
              rb_define_private_method(cMysql2Client, "connect_timeout=", set_connect_timeout, 1);
         
     |