mysql2 0.1.8 → 0.1.9

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.
@@ -1,5 +1,6 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+ require 'spec_helper'
3
+ require 'rubygems'
3
4
  require 'active_record'
4
5
  require 'active_record/connection_adapters/mysql2_adapter'
5
6
 
@@ -28,6 +29,7 @@ describe ActiveRecord::ConnectionAdapters::Mysql2Adapter do
28
29
  context "columns" do
29
30
  before(:all) do
30
31
  ActiveRecord::Base.default_timezone = 'Pacific Time (US & Canada)'
32
+ ActiveRecord::Base.time_zone_aware_attributes = true
31
33
  ActiveRecord::Base.establish_connection(:adapter => 'mysql2', :database => 'test')
32
34
  Mysql2Test2.connection.execute %[
33
35
  CREATE TABLE IF NOT EXISTS mysql2_test2 (
@@ -123,9 +125,9 @@ describe ActiveRecord::ConnectionAdapters::Mysql2Adapter do
123
125
  test.double_test.should eql('1.0000'.to_f)
124
126
  test.decimal_test.should eql(BigDecimal.new('1.0000'))
125
127
  test.date_test.should eql(Date.parse('2010-01-01'))
126
- test.date_time_test.should eql(DateTime.parse('2010-01-01 00:00:00'))
128
+ test.date_time_test.should eql(Time.utc(2010,1,1,0,0,0))
127
129
  test.timestamp_test.class.should eql(ActiveSupport::TimeWithZone)
128
- test.time_test.class.should eql(ActiveSupport::TimeWithZone)
130
+ test.time_test.class.should eql(Time)
129
131
  test.year_test.should eql(2010)
130
132
  test.char_test.should eql('abcdefghij')
131
133
  test.varchar_test.should eql('abcdefghij')
@@ -144,4 +146,4 @@ describe ActiveRecord::ConnectionAdapters::Mysql2Adapter do
144
146
  test.set_test.should eql('val1,val2')
145
147
  end
146
148
  end
147
- end
149
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+ require 'spec_helper'
3
3
  require 'mysql2/em'
4
4
 
5
5
  describe Mysql2::EM::Client do
@@ -23,4 +23,4 @@ describe Mysql2::EM::Client do
23
23
  results[0].keys.should include("second_query")
24
24
  results[1].keys.should include("first_query")
25
25
  end
26
- end
26
+ end
@@ -1,11 +1,19 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+ require 'spec_helper'
3
3
 
4
4
  describe Mysql2::Client do
5
5
  before(:each) do
6
6
  @client = Mysql2::Client.new
7
7
  end
8
8
 
9
+ if defined? Encoding
10
+ it "should raise an exception on create for invalid encodings" do
11
+ lambda {
12
+ c = Mysql2::Client.new(:encoding => "fake")
13
+ }.should raise_error(Mysql2::Error)
14
+ end
15
+ end
16
+
9
17
  it "should be able to connect via SSL options" do
10
18
  pending("DON'T WORRY, THIS TEST PASSES :) - but is machine-specific. You need to have MySQL running with SSL configured and enabled. Then update the paths in this test to your needs and remove the pending state.")
11
19
  ssl_client = nil
@@ -74,6 +82,25 @@ describe Mysql2::Client do
74
82
  info[:version].class.should eql(String)
75
83
  end
76
84
 
85
+ if defined? Encoding
86
+ context "strings returned by #info" do
87
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
88
+ Encoding.default_internal = nil
89
+ @client.info[:version].encoding.should eql(Encoding.find('utf-8'))
90
+
91
+ client2 = Mysql2::Client.new :encoding => 'ascii'
92
+ client2.info[:version].encoding.should eql(Encoding.find('us-ascii'))
93
+ end
94
+
95
+ it "should use Encoding.default_internal" do
96
+ Encoding.default_internal = Encoding.find('utf-8')
97
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
98
+ Encoding.default_internal = Encoding.find('us-ascii')
99
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
100
+ end
101
+ end
102
+ end
103
+
77
104
  it "should respond to #server_info" do
78
105
  @client.should respond_to :server_info
79
106
  end
@@ -87,6 +114,25 @@ describe Mysql2::Client do
87
114
  server_info[:version].class.should eql(String)
88
115
  end
89
116
 
117
+ if defined? Encoding
118
+ context "strings returned by #server_info" do
119
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
120
+ Encoding.default_internal = nil
121
+ @client.server_info[:version].encoding.should eql(Encoding.find('utf-8'))
122
+
123
+ client2 = Mysql2::Client.new :encoding => 'ascii'
124
+ client2.server_info[:version].encoding.should eql(Encoding.find('us-ascii'))
125
+ end
126
+
127
+ it "should use Encoding.default_internal" do
128
+ Encoding.default_internal = Encoding.find('utf-8')
129
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
130
+ Encoding.default_internal = Encoding.find('us-ascii')
131
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
132
+ end
133
+ end
134
+ end
135
+
90
136
  it "should respond to #socket" do
91
137
  @client.should respond_to :socket
92
138
  end
@@ -158,4 +204,4 @@ describe Mysql2::Client do
158
204
  @client.affected_rows.should eql(1)
159
205
  end
160
206
  end
161
- end
207
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+ require 'spec_helper'
3
3
 
4
4
  describe Mysql2::Error do
5
5
  before(:each) do
@@ -13,4 +13,4 @@ describe Mysql2::Error do
13
13
  it "should respond to #sql_state" do
14
14
  @error.should respond_to(:sql_state)
15
15
  end
16
- end
16
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+ require 'spec_helper'
3
3
 
4
4
  describe Mysql2::Result do
5
5
  before(:all) do
@@ -47,6 +47,22 @@ describe Mysql2::Result do
47
47
  end
48
48
  end
49
49
 
50
+ context "#fields" do
51
+ before(:all) do
52
+ @client.query "USE test"
53
+ @test_result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1")
54
+ end
55
+
56
+ it "method should exist" do
57
+ @test_result.should respond_to(:fields)
58
+ end
59
+
60
+ it "should return an array of field names in proper order" do
61
+ result = @client.query "SELECT 'a', 'b', 'c'"
62
+ result.fields.should eql(['a', 'b', 'c'])
63
+ end
64
+ end
65
+
50
66
  context "row data type mapping" do
51
67
  before(:all) do
52
68
  @client.query "USE test"
@@ -176,7 +192,7 @@ describe Mysql2::Result do
176
192
 
177
193
  it "should return Time for a TIME value" do
178
194
  @test_result['time_test'].class.should eql(Time)
179
- if RUBY_VERSION =~ /1.9.2/
195
+ if RUBY_VERSION >= "1.9.2"
180
196
  @test_result['time_test'].strftime("%F %T").should eql('0000-01-01 11:44:00')
181
197
  else
182
198
  @test_result['time_test'].strftime("%F %T").should eql('2000-01-01 11:44:00')
@@ -193,16 +209,83 @@ describe Mysql2::Result do
193
209
  @test_result['enum_test'].should eql('val1')
194
210
  end
195
211
 
212
+ if defined? Encoding
213
+ context "string encoding for ENUM values" do
214
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
215
+ Encoding.default_internal = nil
216
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
217
+ result['enum_test'].encoding.should eql(Encoding.find('utf-8'))
218
+
219
+ client2 = Mysql2::Client.new :encoding => 'ascii'
220
+ client2.query "USE test"
221
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
222
+ result['enum_test'].encoding.should eql(Encoding.find('us-ascii'))
223
+ end
224
+
225
+ it "should use Encoding.default_internal" do
226
+ Encoding.default_internal = Encoding.find('utf-8')
227
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
228
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
229
+ Encoding.default_internal = Encoding.find('us-ascii')
230
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
231
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
232
+ end
233
+ end
234
+ end
235
+
196
236
  it "should return String for a SET value" do
197
237
  @test_result['set_test'].class.should eql(String)
198
238
  @test_result['set_test'].should eql('val1,val2')
199
239
  end
200
240
 
241
+ if defined? Encoding
242
+ context "string encoding for SET values" do
243
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
244
+ Encoding.default_internal = nil
245
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
246
+ result['set_test'].encoding.should eql(Encoding.find('utf-8'))
247
+
248
+ client2 = Mysql2::Client.new :encoding => 'ascii'
249
+ client2.query "USE test"
250
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
251
+ result['set_test'].encoding.should eql(Encoding.find('us-ascii'))
252
+ end
253
+
254
+ it "should use Encoding.default_internal" do
255
+ Encoding.default_internal = Encoding.find('utf-8')
256
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
257
+ result['set_test'].encoding.should eql(Encoding.default_internal)
258
+ Encoding.default_internal = Encoding.find('us-ascii')
259
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
260
+ result['set_test'].encoding.should eql(Encoding.default_internal)
261
+ end
262
+ end
263
+ end
264
+
201
265
  it "should return String for a BINARY value" do
202
266
  @test_result['binary_test'].class.should eql(String)
203
267
  @test_result['binary_test'].should eql("test#{"\000"*6}")
204
268
  end
205
269
 
270
+ if defined? Encoding
271
+ context "string encoding for BINARY values" do
272
+ it "should default to binary if Encoding.default_internal is nil" do
273
+ Encoding.default_internal = nil
274
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
275
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
276
+ end
277
+
278
+ it "should not use Encoding.default_internal" do
279
+ Encoding.default_internal = Encoding.find('utf-8')
280
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
281
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
282
+ Encoding.default_internal = Encoding.find('us-ascii')
283
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
284
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
285
+ end
286
+ end
287
+ end
288
+
206
289
  {
207
290
  'char_test' => 'CHAR',
208
291
  'varchar_test' => 'VARCHAR',
@@ -220,6 +303,47 @@ describe Mysql2::Result do
220
303
  @test_result[field].class.should eql(String)
221
304
  @test_result[field].should eql("test")
222
305
  end
306
+
307
+ if defined? Encoding
308
+ context "string encoding for #{type} values" do
309
+ if ['VARBINARY', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB'].include?(type)
310
+ it "should default to binary if Encoding.default_internal is nil" do
311
+ Encoding.default_internal = nil
312
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
313
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
314
+ end
315
+
316
+ it "should not use Encoding.default_internal" do
317
+ Encoding.default_internal = Encoding.find('utf-8')
318
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
319
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
320
+ Encoding.default_internal = Encoding.find('us-ascii')
321
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
322
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
323
+ end
324
+ else
325
+ it "should default to utf-8 if Encoding.default_internal is nil" do
326
+ Encoding.default_internal = nil
327
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
328
+ result[field].encoding.should eql(Encoding.find('utf-8'))
329
+
330
+ client2 = Mysql2::Client.new :encoding => 'ascii'
331
+ client2.query "USE test"
332
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
333
+ result[field].encoding.should eql(Encoding.find('us-ascii'))
334
+ end
335
+
336
+ it "should use Encoding.default_internal" do
337
+ Encoding.default_internal = Encoding.find('utf-8')
338
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
339
+ result[field].encoding.should eql(Encoding.default_internal)
340
+ Encoding.default_internal = Encoding.find('us-ascii')
341
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
342
+ result[field].encoding.should eql(Encoding.default_internal)
343
+ end
344
+ end
345
+ end
346
+ end
223
347
  end
224
348
  end
225
- end
349
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 9
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 8
9
- version: 0.1.8
9
+ - 9
10
+ version: 0.1.9
10
11
  platform: ruby
11
12
  authors:
12
13
  - Brian Lopez
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-06-02 00:00:00 -07:00
18
+ date: 2010-07-17 00:00:00 -07:00
18
19
  default_executable:
19
20
  dependencies: []
20
21
 
@@ -23,7 +24,7 @@ email: seniorlopez@gmail.com
23
24
  executables: []
24
25
 
25
26
  extensions:
26
- - ext/extconf.rb
27
+ - ext/mysql2/extconf.rb
27
28
  extra_rdoc_files:
28
29
  - README.rdoc
29
30
  files:
@@ -40,13 +41,20 @@ files:
40
41
  - benchmark/sequel.rb
41
42
  - benchmark/setup_db.rb
42
43
  - examples/eventmachine.rb
43
- - ext/extconf.rb
44
- - ext/mysql2_ext.c
45
- - ext/mysql2_ext.h
44
+ - ext/mysql2/extconf.rb
45
+ - ext/mysql2/mysql2_ext.c
46
+ - ext/mysql2/mysql2_ext.h
47
+ - ext/mysql2/result.c
48
+ - ext/mysql2/result.h
49
+ - lib/active_record/connection_adapters/em_mysql2_adapter.rb
46
50
  - lib/active_record/connection_adapters/mysql2_adapter.rb
51
+ - lib/active_record/fiber_patches.rb
47
52
  - lib/arel/engines/sql/compilers/mysql2_compiler.rb
48
53
  - lib/mysql2.rb
54
+ - lib/mysql2/client.rb
49
55
  - lib/mysql2/em.rb
56
+ - lib/mysql2/error.rb
57
+ - lib/mysql2/result.rb
50
58
  - lib/sequel/adapters/mysql2.rb
51
59
  - mysql2.gemspec
52
60
  - spec/active_record/active_record_spec.rb
@@ -68,23 +76,27 @@ require_paths:
68
76
  - lib
69
77
  - ext
70
78
  required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
71
80
  requirements:
72
81
  - - ">="
73
82
  - !ruby/object:Gem::Version
83
+ hash: 3
74
84
  segments:
75
85
  - 0
76
86
  version: "0"
77
87
  required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
78
89
  requirements:
79
90
  - - ">="
80
91
  - !ruby/object:Gem::Version
92
+ hash: 3
81
93
  segments:
82
94
  - 0
83
95
  version: "0"
84
96
  requirements: []
85
97
 
86
98
  rubyforge_project:
87
- rubygems_version: 1.3.6
99
+ rubygems_version: 1.3.7
88
100
  signing_key:
89
101
  specification_version: 3
90
102
  summary: A simple, fast Mysql library for Ruby, binding to libmysql
@@ -1,748 +0,0 @@
1
- #include "mysql2_ext.h"
2
-
3
- /*
4
- * non-blocking mysql_*() functions that we won't be wrapping since
5
- * they do not appear to hit the network nor issue any interruptible
6
- * or blocking system calls.
7
- *
8
- * - mysql_affected_rows()
9
- * - mysql_error()
10
- * - mysql_fetch_fields()
11
- * - mysql_fetch_lengths() - calls cli_fetch_lengths or emb_fetch_lengths
12
- * - mysql_field_count()
13
- * - mysql_get_client_info()
14
- * - mysql_get_client_version()
15
- * - mysql_get_server_info()
16
- * - mysql_get_server_version()
17
- * - mysql_insert_id()
18
- * - mysql_num_fields()
19
- * - mysql_num_rows()
20
- * - mysql_options()
21
- * - mysql_real_escape_string()
22
- * - mysql_ssl_set()
23
- */
24
-
25
- static VALUE nogvl_init(void *ptr) {
26
- struct nogvl_connect_args *args = ptr;
27
-
28
- /* may initialize embedded server and read /etc/services off disk */
29
- args->mysql = mysql_init(NULL);
30
-
31
- return args->mysql == NULL ? Qfalse : Qtrue;
32
- }
33
-
34
- static VALUE nogvl_connect(void *ptr)
35
- {
36
- struct nogvl_connect_args *args = ptr;
37
- MYSQL *client;
38
-
39
- client = mysql_real_connect(args->mysql, args->host,
40
- args->user, args->passwd,
41
- args->db, args->port, args->unix_socket,
42
- args->client_flag);
43
-
44
- return client ? Qtrue : Qfalse;
45
- }
46
-
47
- /* Mysql2::Client */
48
- static VALUE rb_mysql_client_new(int argc, VALUE * argv, VALUE klass) {
49
- mysql2_client_wrapper * client;
50
- struct nogvl_connect_args args = {
51
- .host = "localhost",
52
- .user = NULL,
53
- .passwd = NULL,
54
- .db = NULL,
55
- .port = 3306,
56
- .unix_socket = NULL,
57
- .client_flag = 0
58
- };
59
- VALUE obj, opts;
60
- VALUE rb_host, rb_socket, rb_port, rb_database,
61
- rb_username, rb_password, rb_reconnect,
62
- rb_connect_timeout;
63
- VALUE rb_ssl_client_key, rb_ssl_client_cert, rb_ssl_ca_cert,
64
- rb_ssl_ca_path, rb_ssl_cipher;
65
- char *ssl_client_key = NULL, *ssl_client_cert = NULL, *ssl_ca_cert = NULL,
66
- *ssl_ca_path = NULL, *ssl_cipher = NULL;
67
- unsigned int connect_timeout = 0;
68
- my_bool reconnect = 1;
69
-
70
- obj = Data_Make_Struct(klass, mysql2_client_wrapper, NULL, rb_mysql_client_free, client);
71
-
72
- if (rb_scan_args(argc, argv, "01", &opts) == 1) {
73
- Check_Type(opts, T_HASH);
74
-
75
- if ((rb_host = rb_hash_aref(opts, sym_host)) != Qnil) {
76
- Check_Type(rb_host, T_STRING);
77
- args.host = RSTRING_PTR(rb_host);
78
- }
79
-
80
- if ((rb_socket = rb_hash_aref(opts, sym_socket)) != Qnil) {
81
- Check_Type(rb_socket, T_STRING);
82
- args.unix_socket = RSTRING_PTR(rb_socket);
83
- }
84
-
85
- if ((rb_port = rb_hash_aref(opts, sym_port)) != Qnil) {
86
- Check_Type(rb_port, T_FIXNUM);
87
- args.port = FIX2INT(rb_port);
88
- }
89
-
90
- if ((rb_username = rb_hash_aref(opts, sym_username)) != Qnil) {
91
- Check_Type(rb_username, T_STRING);
92
- args.user = RSTRING_PTR(rb_username);
93
- }
94
-
95
- if ((rb_password = rb_hash_aref(opts, sym_password)) != Qnil) {
96
- Check_Type(rb_password, T_STRING);
97
- args.passwd = RSTRING_PTR(rb_password);
98
- }
99
-
100
- if ((rb_database = rb_hash_aref(opts, sym_database)) != Qnil) {
101
- Check_Type(rb_database, T_STRING);
102
- args.db = RSTRING_PTR(rb_database);
103
- }
104
-
105
- if ((rb_reconnect = rb_hash_aref(opts, sym_reconnect)) != Qnil) {
106
- reconnect = rb_reconnect == Qfalse ? 0 : 1;
107
- }
108
-
109
- if ((rb_connect_timeout = rb_hash_aref(opts, sym_connect_timeout)) != Qnil) {
110
- Check_Type(rb_connect_timeout, T_FIXNUM);
111
- connect_timeout = FIX2INT(rb_connect_timeout);
112
- }
113
-
114
- // SSL options
115
- if ((rb_ssl_client_key = rb_hash_aref(opts, sym_sslkey)) != Qnil) {
116
- Check_Type(rb_ssl_client_key, T_STRING);
117
- ssl_client_key = RSTRING_PTR(rb_ssl_client_key);
118
- }
119
-
120
- if ((rb_ssl_client_cert = rb_hash_aref(opts, sym_sslcert)) != Qnil) {
121
- Check_Type(rb_ssl_client_cert, T_STRING);
122
- ssl_client_cert = RSTRING_PTR(rb_ssl_client_cert);
123
- }
124
-
125
- if ((rb_ssl_ca_cert = rb_hash_aref(opts, sym_sslca)) != Qnil) {
126
- Check_Type(rb_ssl_ca_cert, T_STRING);
127
- ssl_ca_cert = RSTRING_PTR(rb_ssl_ca_cert);
128
- }
129
-
130
- if ((rb_ssl_ca_path = rb_hash_aref(opts, sym_sslcapath)) != Qnil) {
131
- Check_Type(rb_ssl_ca_path, T_STRING);
132
- ssl_ca_path = RSTRING_PTR(rb_ssl_ca_path);
133
- }
134
-
135
- if ((rb_ssl_cipher = rb_hash_aref(opts, sym_sslcipher)) != Qnil) {
136
- Check_Type(rb_ssl_cipher, T_STRING);
137
- ssl_cipher = RSTRING_PTR(rb_ssl_cipher);
138
- }
139
- }
140
-
141
- if (rb_thread_blocking_region(nogvl_init, &args, RUBY_UBF_IO, 0) == Qfalse) {
142
- // TODO: warning - not enough memory?
143
- return rb_raise_mysql2_error(args.mysql);
144
- }
145
-
146
- // set default reconnect behavior
147
- if (mysql_options(args.mysql, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
148
- // TODO: warning - unable to set reconnect behavior
149
- rb_warn("%s\n", mysql_error(args.mysql));
150
- }
151
-
152
- // set default connection timeout behavior
153
- if (connect_timeout != 0 && mysql_options(args.mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&connect_timeout) != 0) {
154
- // TODO: warning - unable to set connection timeout
155
- rb_warn("%s\n", mysql_error(args.mysql));
156
- }
157
-
158
- // force the encoding to utf8
159
- if (mysql_options(args.mysql, MYSQL_SET_CHARSET_NAME, "utf8") != 0) {
160
- // TODO: warning - unable to set charset
161
- rb_warn("%s\n", mysql_error(args.mysql));
162
- }
163
-
164
- if (ssl_ca_cert != NULL || ssl_client_key != NULL) {
165
- mysql_ssl_set(args.mysql, ssl_client_key, ssl_client_cert, ssl_ca_cert, ssl_ca_path, ssl_cipher);
166
- }
167
-
168
- if (rb_thread_blocking_region(nogvl_connect, &args, RUBY_UBF_IO, 0) == Qfalse) {
169
- // unable to connect
170
- return rb_raise_mysql2_error(args.mysql);;
171
- }
172
-
173
- client->client = args.mysql;
174
-
175
- rb_obj_call_init(obj, argc, argv);
176
- return obj;
177
- }
178
-
179
- static VALUE rb_mysql_client_init(RB_MYSQL_UNUSED int argc, RB_MYSQL_UNUSED VALUE * argv, VALUE self) {
180
- return self;
181
- }
182
-
183
- static void rb_mysql_client_free(void * ptr) {
184
- mysql2_client_wrapper * client = ptr;
185
-
186
- if (client->client) {
187
- /*
188
- * we'll send a QUIT message to the server, but that message is more of a
189
- * formality than a hard requirement since the socket is getting shutdown
190
- * anyways, so ensure the socket write does not block our interpreter
191
- */
192
- int fd = client->client->net.fd;
193
- int flags;
194
-
195
- if (fd >= 0) {
196
- /*
197
- * if the socket is dead we have no chance of blocking,
198
- * so ignore any potential fcntl errors since they don't matter
199
- */
200
- flags = fcntl(fd, F_GETFL);
201
- if (flags > 0 && !(flags & O_NONBLOCK))
202
- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
203
- }
204
-
205
- mysql_close(client->client);
206
- }
207
- xfree(ptr);
208
- }
209
-
210
- static VALUE nogvl_close(void * ptr) {
211
- mysql_close((MYSQL *)ptr);
212
- return Qnil;
213
- }
214
-
215
- /*
216
- * Immediately disconnect from the server, normally the garbage collector
217
- * will disconnect automatically when a connection is no longer needed.
218
- * Explicitly closing this will free up server resources sooner than waiting
219
- * for the garbage collector.
220
- */
221
- static VALUE rb_mysql_client_close(VALUE self) {
222
- mysql2_client_wrapper *client;
223
-
224
- Data_Get_Struct(self, mysql2_client_wrapper, client);
225
-
226
- if (client->client) {
227
- rb_thread_blocking_region(nogvl_close, client->client, RUBY_UBF_IO, 0);
228
- client->client = NULL;
229
- } else {
230
- rb_raise(cMysql2Error, "already closed MySQL connection");
231
- }
232
- return Qnil;
233
- }
234
-
235
- /*
236
- * mysql_send_query is unlikely to block since most queries are small
237
- * enough to fit in a socket buffer, but sometimes large UPDATE and
238
- * INSERTs will cause the process to block
239
- */
240
- static VALUE nogvl_send_query(void *ptr)
241
- {
242
- struct nogvl_send_query_args *args = ptr;
243
- int rv;
244
- const char *sql = RSTRING_PTR(args->sql);
245
- long sql_len = RSTRING_LEN(args->sql);
246
-
247
- rv = mysql_send_query(args->mysql, sql, sql_len);
248
-
249
- return rv == 0 ? Qtrue : Qfalse;
250
- }
251
-
252
- static VALUE rb_mysql_client_query(int argc, VALUE * argv, VALUE self) {
253
- struct nogvl_send_query_args args;
254
- fd_set fdset;
255
- int fd, retval;
256
- int async = 0;
257
- VALUE opts;
258
- VALUE rb_async;
259
-
260
- if (rb_scan_args(argc, argv, "11", &args.sql, &opts) == 2) {
261
- if ((rb_async = rb_hash_aref(opts, sym_async)) != Qnil) {
262
- async = rb_async == Qtrue ? 1 : 0;
263
- }
264
- }
265
-
266
- Check_Type(args.sql, T_STRING);
267
-
268
- GetMysql2Client(self, args.mysql);
269
- if (!args.mysql) {
270
- rb_raise(cMysql2Error, "closed MySQL connection");
271
- return Qnil;
272
- }
273
- if (rb_thread_blocking_region(nogvl_send_query, &args, RUBY_UBF_IO, 0) == Qfalse) {
274
- return rb_raise_mysql2_error(args.mysql);;
275
- }
276
-
277
- if (!async) {
278
- // the below code is largely from do_mysql
279
- // http://github.com/datamapper/do
280
- fd = args.mysql->net.fd;
281
- for(;;) {
282
- FD_ZERO(&fdset);
283
- FD_SET(fd, &fdset);
284
-
285
- retval = rb_thread_select(fd + 1, &fdset, NULL, NULL, NULL);
286
-
287
- if (retval < 0) {
288
- rb_sys_fail(0);
289
- }
290
-
291
- if (retval > 0) {
292
- break;
293
- }
294
- }
295
-
296
- return rb_mysql_client_async_result(self);
297
- } else {
298
- return Qnil;
299
- }
300
- }
301
-
302
- static VALUE rb_mysql_client_escape(VALUE self, VALUE str) {
303
- MYSQL * client;
304
- VALUE newStr;
305
- unsigned long newLen, oldLen;
306
-
307
- Check_Type(str, T_STRING);
308
- oldLen = RSTRING_LEN(str);
309
- char escaped[(oldLen*2)+1];
310
-
311
- GetMysql2Client(self, client);
312
- if (!client) {
313
- rb_raise(cMysql2Error, "closed MySQL connection");
314
- return Qnil;
315
- }
316
- newLen = mysql_real_escape_string(client, escaped, RSTRING_PTR(str), RSTRING_LEN(str));
317
- if (newLen == oldLen) {
318
- // no need to return a new ruby string if nothing changed
319
- return str;
320
- } else {
321
- newStr = rb_str_new(escaped, newLen);
322
- #ifdef HAVE_RUBY_ENCODING_H
323
- rb_enc_associate_index(newStr, utf8Encoding);
324
- #endif
325
- return newStr;
326
- }
327
- }
328
-
329
- static VALUE rb_mysql_client_info(RB_MYSQL_UNUSED VALUE self) {
330
- VALUE version = rb_hash_new();
331
- rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_client_version()));
332
- rb_hash_aset(version, sym_version, rb_str_new2(mysql_get_client_info()));
333
- return version;
334
- }
335
-
336
- static VALUE rb_mysql_client_server_info(VALUE self) {
337
- MYSQL * client;
338
- VALUE version;
339
-
340
- GetMysql2Client(self, client);
341
- if (!client) {
342
- rb_raise(cMysql2Error, "closed MySQL connection");
343
- return Qnil;
344
- }
345
- version = rb_hash_new();
346
- rb_hash_aset(version, sym_id, LONG2FIX(mysql_get_server_version(client)));
347
- rb_hash_aset(version, sym_version, rb_str_new2(mysql_get_server_info(client)));
348
- return version;
349
- }
350
-
351
- static VALUE rb_mysql_client_socket(VALUE self) {
352
- MYSQL * client = GetMysql2Client(self, client);
353
- if (!client) {
354
- rb_raise(cMysql2Error, "closed MySQL connection");
355
- return Qnil;
356
- }
357
- return INT2NUM(client->net.fd);
358
- }
359
-
360
- /*
361
- * even though we did rb_thread_select before calling this, a large
362
- * response can overflow the socket buffers and cause us to eventually
363
- * block while calling mysql_read_query_result
364
- */
365
- static VALUE nogvl_read_query_result(void *ptr)
366
- {
367
- MYSQL * client = ptr;
368
- my_bool res = mysql_read_query_result(client);
369
-
370
- return res == 0 ? Qtrue : Qfalse;
371
- }
372
-
373
- /* mysql_store_result may (unlikely) read rows off the socket */
374
- static VALUE nogvl_store_result(void *ptr)
375
- {
376
- MYSQL * client = ptr;
377
- return (VALUE)mysql_store_result(client);
378
- }
379
-
380
- static VALUE rb_mysql_client_async_result(VALUE self) {
381
- MYSQL * client;
382
- MYSQL_RES * result;
383
- GetMysql2Client(self, client);
384
- if (!client) {
385
- rb_raise(cMysql2Error, "closed MySQL connection");
386
- return Qnil;
387
- }
388
- if (rb_thread_blocking_region(nogvl_read_query_result, client, RUBY_UBF_IO, 0) == Qfalse) {
389
- return rb_raise_mysql2_error(client);
390
- }
391
-
392
- result = (MYSQL_RES *)rb_thread_blocking_region(nogvl_store_result, client, RUBY_UBF_IO, 0);
393
- if (result == NULL) {
394
- if (mysql_field_count(client) != 0) {
395
- rb_raise_mysql2_error(client);
396
- }
397
- return Qnil;
398
- }
399
-
400
- return rb_mysql_result_to_obj(result);
401
- }
402
-
403
- static VALUE rb_mysql_client_last_id(VALUE self) {
404
- MYSQL * client;
405
- GetMysql2Client(self, client);
406
- if (!client) {
407
- rb_raise(cMysql2Error, "closed MySQL connection");
408
- return Qnil;
409
- }
410
- return ULL2NUM(mysql_insert_id(client));
411
- }
412
-
413
- static VALUE rb_mysql_client_affected_rows(VALUE self) {
414
- MYSQL * client;
415
- GetMysql2Client(self, client);
416
- if (!client) {
417
- rb_raise(cMysql2Error, "closed MySQL connection");
418
- return Qnil;
419
- }
420
- return ULL2NUM(mysql_affected_rows(client));
421
- }
422
-
423
- /* Mysql2::Result */
424
- static VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
425
- VALUE obj;
426
- mysql2_result_wrapper * wrapper;
427
- obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
428
- wrapper->numberOfFields = 0;
429
- wrapper->numberOfRows = 0;
430
- wrapper->lastRowProcessed = 0;
431
- wrapper->resultFreed = 0;
432
- wrapper->result = r;
433
- rb_obj_call_init(obj, 0, NULL);
434
- return obj;
435
- }
436
-
437
- /* this may be called manually or during GC */
438
- static void rb_mysql_result_free_result(mysql2_result_wrapper * wrapper) {
439
- if (wrapper && wrapper->resultFreed != 1) {
440
- mysql_free_result(wrapper->result);
441
- wrapper->resultFreed = 1;
442
- }
443
- }
444
-
445
- /* this is called during GC */
446
- static void rb_mysql_result_free(void * wrapper) {
447
- mysql2_result_wrapper * w = wrapper;
448
- /* FIXME: this may call flush_use_result, which can hit the socket */
449
- rb_mysql_result_free_result(w);
450
- xfree(wrapper);
451
- }
452
-
453
- static void rb_mysql_result_mark(void * wrapper) {
454
- mysql2_result_wrapper * w = wrapper;
455
- if (w) {
456
- rb_gc_mark(w->fields);
457
- rb_gc_mark(w->rows);
458
- }
459
- }
460
-
461
- /*
462
- * for small results, this won't hit the network, but there's no
463
- * reliable way for us to tell this so we'll always release the GVL
464
- * to be safe
465
- */
466
- static VALUE nogvl_fetch_row(void *ptr)
467
- {
468
- MYSQL_RES *result = ptr;
469
-
470
- return (VALUE)mysql_fetch_row(result);
471
- }
472
-
473
- static VALUE rb_mysql_result_fetch_row(int argc, VALUE * argv, VALUE self) {
474
- VALUE rowHash, opts, block;
475
- mysql2_result_wrapper * wrapper;
476
- MYSQL_ROW row;
477
- MYSQL_FIELD * fields = NULL;
478
- unsigned int i = 0, symbolizeKeys = 0;
479
- unsigned long * fieldLengths;
480
- void * ptr;
481
-
482
- GetMysql2Result(self, wrapper);
483
-
484
- if (rb_scan_args(argc, argv, "01&", &opts, &block) == 1) {
485
- Check_Type(opts, T_HASH);
486
- if (rb_hash_aref(opts, sym_symbolize_keys) == Qtrue) {
487
- symbolizeKeys = 1;
488
- }
489
- }
490
-
491
- ptr = wrapper->result;
492
- row = (MYSQL_ROW)rb_thread_blocking_region(nogvl_fetch_row, ptr, RUBY_UBF_IO, 0);
493
- if (row == NULL) {
494
- return Qnil;
495
- }
496
-
497
- if (wrapper->numberOfFields == 0) {
498
- wrapper->numberOfFields = mysql_num_fields(wrapper->result);
499
- wrapper->fields = rb_ary_new2(wrapper->numberOfFields);
500
- }
501
-
502
- rowHash = rb_hash_new();
503
- fields = mysql_fetch_fields(wrapper->result);
504
- fieldLengths = mysql_fetch_lengths(wrapper->result);
505
- for (i = 0; i < wrapper->numberOfFields; i++) {
506
-
507
- // lazily create fields, but only once
508
- // we'll use cached versions from here on out
509
- VALUE field = rb_ary_entry(wrapper->fields, i);
510
- if (field == Qnil) {
511
- if (symbolizeKeys) {
512
- char buf[fields[i].name_length+1];
513
- memcpy(buf, fields[i].name, fields[i].name_length);
514
- buf[fields[i].name_length] = 0;
515
- field = ID2SYM(rb_intern(buf));
516
- } else {
517
- field = rb_str_new(fields[i].name, fields[i].name_length);
518
- #ifdef HAVE_RUBY_ENCODING_H
519
- rb_enc_associate_index(field, utf8Encoding);
520
- #endif
521
- }
522
- rb_ary_store(wrapper->fields, i, field);
523
- }
524
-
525
- if (row[i]) {
526
- VALUE val;
527
- switch(fields[i].type) {
528
- case MYSQL_TYPE_NULL: // NULL-type field
529
- val = Qnil;
530
- break;
531
- case MYSQL_TYPE_BIT: // BIT field (MySQL 5.0.3 and up)
532
- val = rb_str_new(row[i], fieldLengths[i]);
533
- break;
534
- case MYSQL_TYPE_TINY: // TINYINT field
535
- case MYSQL_TYPE_SHORT: // SMALLINT field
536
- case MYSQL_TYPE_LONG: // INTEGER field
537
- case MYSQL_TYPE_INT24: // MEDIUMINT field
538
- case MYSQL_TYPE_LONGLONG: // BIGINT field
539
- case MYSQL_TYPE_YEAR: // YEAR field
540
- val = rb_cstr2inum(row[i], 10);
541
- break;
542
- case MYSQL_TYPE_DECIMAL: // DECIMAL or NUMERIC field
543
- case MYSQL_TYPE_NEWDECIMAL: // Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up)
544
- val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
545
- break;
546
- case MYSQL_TYPE_FLOAT: // FLOAT field
547
- case MYSQL_TYPE_DOUBLE: // DOUBLE or REAL field
548
- val = rb_float_new(strtod(row[i], NULL));
549
- break;
550
- case MYSQL_TYPE_TIME: { // TIME field
551
- int hour, min, sec, tokens;
552
- tokens = sscanf(row[i], "%2d:%2d:%2d", &hour, &min, &sec);
553
- val = rb_funcall(rb_cTime, intern_utc, 6, INT2NUM(0), INT2NUM(1), INT2NUM(1), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
554
- break;
555
- }
556
- case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP field
557
- case MYSQL_TYPE_DATETIME: { // DATETIME field
558
- int year, month, day, hour, min, sec, tokens;
559
- tokens = sscanf(row[i], "%4d-%2d-%2d %2d:%2d:%2d", &year, &month, &day, &hour, &min, &sec);
560
- if (year+month+day+hour+min+sec == 0) {
561
- val = Qnil;
562
- } else {
563
- if (month < 1 || day < 1) {
564
- rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
565
- val = Qnil;
566
- } else {
567
- val = rb_funcall(rb_cTime, intern_utc, 6, INT2NUM(year), INT2NUM(month), INT2NUM(day), INT2NUM(hour), INT2NUM(min), INT2NUM(sec));
568
- }
569
- }
570
- break;
571
- }
572
- case MYSQL_TYPE_DATE: // DATE field
573
- case MYSQL_TYPE_NEWDATE: { // Newer const used > 5.0
574
- int year, month, day, tokens;
575
- tokens = sscanf(row[i], "%4d-%2d-%2d", &year, &month, &day);
576
- if (year+month+day == 0) {
577
- val = Qnil;
578
- } else {
579
- if (month < 1 || day < 1) {
580
- rb_raise(cMysql2Error, "Invalid date: %s", row[i]);
581
- val = Qnil;
582
- } else {
583
- val = rb_funcall(cDate, intern_new, 3, INT2NUM(year), INT2NUM(month), INT2NUM(day));
584
- }
585
- }
586
- break;
587
- }
588
- case MYSQL_TYPE_TINY_BLOB:
589
- case MYSQL_TYPE_MEDIUM_BLOB:
590
- case MYSQL_TYPE_LONG_BLOB:
591
- case MYSQL_TYPE_BLOB:
592
- case MYSQL_TYPE_VAR_STRING:
593
- case MYSQL_TYPE_VARCHAR:
594
- case MYSQL_TYPE_STRING: // CHAR or BINARY field
595
- case MYSQL_TYPE_SET: // SET field
596
- case MYSQL_TYPE_ENUM: // ENUM field
597
- case MYSQL_TYPE_GEOMETRY: // Spatial fielda
598
- default:
599
- val = rb_str_new(row[i], fieldLengths[i]);
600
- #ifdef HAVE_RUBY_ENCODING_H
601
- // rudimentary check for binary content
602
- if ((fields[i].flags & BINARY_FLAG) || fields[i].charsetnr == 63) {
603
- rb_enc_associate_index(val, binaryEncoding);
604
- } else {
605
- rb_enc_associate_index(val, utf8Encoding);
606
- }
607
- #endif
608
- break;
609
- }
610
- rb_hash_aset(rowHash, field, val);
611
- } else {
612
- rb_hash_aset(rowHash, field, Qnil);
613
- }
614
- }
615
- return rowHash;
616
- }
617
-
618
- static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
619
- VALUE opts, block;
620
- mysql2_result_wrapper * wrapper;
621
- unsigned long i;
622
-
623
- GetMysql2Result(self, wrapper);
624
-
625
- rb_scan_args(argc, argv, "01&", &opts, &block);
626
-
627
- if (wrapper->lastRowProcessed == 0) {
628
- wrapper->numberOfRows = mysql_num_rows(wrapper->result);
629
- if (wrapper->numberOfRows == 0) {
630
- return Qnil;
631
- }
632
- wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
633
- }
634
-
635
- if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
636
- // we've already read the entire dataset from the C result into our
637
- // internal array. Lets hand that over to the user since it's ready to go
638
- for (i = 0; i < wrapper->numberOfRows; i++) {
639
- rb_yield(rb_ary_entry(wrapper->rows, i));
640
- }
641
- } else {
642
- unsigned long rowsProcessed = 0;
643
- rowsProcessed = RARRAY_LEN(wrapper->rows);
644
- for (i = 0; i < wrapper->numberOfRows; i++) {
645
- VALUE row;
646
- if (i < rowsProcessed) {
647
- row = rb_ary_entry(wrapper->rows, i);
648
- } else {
649
- row = rb_mysql_result_fetch_row(argc, argv, self);
650
- rb_ary_store(wrapper->rows, i, row);
651
- wrapper->lastRowProcessed++;
652
- }
653
-
654
- if (row == Qnil) {
655
- // we don't need the mysql C dataset around anymore, peace it
656
- rb_mysql_result_free_result(wrapper);
657
- return Qnil;
658
- }
659
-
660
- if (block != Qnil) {
661
- rb_yield(row);
662
- }
663
- }
664
- if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
665
- // we don't need the mysql C dataset around anymore, peace it
666
- rb_mysql_result_free_result(wrapper);
667
- }
668
- }
669
-
670
- return wrapper->rows;
671
- }
672
-
673
- static VALUE rb_mysql_error_error_number(VALUE obj) {
674
- return rb_iv_get(obj, "error_number");
675
- }
676
-
677
- static VALUE rb_mysql_error_sql_state(VALUE obj) {
678
- return rb_iv_get(obj, "sql_state");
679
- }
680
-
681
- static VALUE rb_raise_mysql2_error(MYSQL *client) {
682
- VALUE e = rb_exc_new2(cMysql2Error, mysql_error(client));
683
- rb_iv_set(e, "error_number", INT2FIX(mysql_errno(client)));
684
- rb_iv_set(e, "sql_state", rb_tainted_str_new2(mysql_sqlstate(client)));
685
- rb_exc_raise(e);
686
- return Qnil;
687
- }
688
-
689
- /* Ruby Extension initializer */
690
- void Init_mysql2_ext() {
691
- rb_require("date");
692
- rb_require("bigdecimal");
693
-
694
- cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
695
- cDate = rb_const_get(rb_cObject, rb_intern("Date"));
696
- cDateTime = rb_const_get(rb_cObject, rb_intern("DateTime"));
697
-
698
- VALUE mMysql2 = rb_define_module("Mysql2");
699
-
700
- VALUE cMysql2Client = rb_define_class_under(mMysql2, "Client", rb_cObject);
701
- rb_define_singleton_method(cMysql2Client, "new", rb_mysql_client_new, -1);
702
- rb_define_method(cMysql2Client, "initialize", rb_mysql_client_init, -1);
703
- rb_define_method(cMysql2Client, "close", rb_mysql_client_close, 0);
704
- rb_define_method(cMysql2Client, "query", rb_mysql_client_query, -1);
705
- rb_define_method(cMysql2Client, "escape", rb_mysql_client_escape, 1);
706
- rb_define_method(cMysql2Client, "info", rb_mysql_client_info, 0);
707
- rb_define_method(cMysql2Client, "server_info", rb_mysql_client_server_info, 0);
708
- rb_define_method(cMysql2Client, "socket", rb_mysql_client_socket, 0);
709
- rb_define_method(cMysql2Client, "async_result", rb_mysql_client_async_result, 0);
710
- rb_define_method(cMysql2Client, "last_id", rb_mysql_client_last_id, 0);
711
- rb_define_method(cMysql2Client, "affected_rows", rb_mysql_client_affected_rows, 0);
712
-
713
- cMysql2Error = rb_define_class_under(mMysql2, "Error", rb_eStandardError);
714
- rb_define_method(cMysql2Error, "error_number", rb_mysql_error_error_number, 0);
715
- rb_define_method(cMysql2Error, "sql_state", rb_mysql_error_sql_state, 0);
716
-
717
- cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
718
- rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
719
-
720
- VALUE mEnumerable = rb_const_get(rb_cObject, rb_intern("Enumerable"));
721
- rb_include_module(cMysql2Result, mEnumerable);
722
-
723
- intern_new = rb_intern("new");
724
- intern_utc = rb_intern("utc");
725
-
726
- sym_symbolize_keys = ID2SYM(rb_intern("symbolize_keys"));
727
- sym_reconnect = ID2SYM(rb_intern("reconnect"));
728
- sym_database = ID2SYM(rb_intern("database"));
729
- sym_username = ID2SYM(rb_intern("username"));
730
- sym_password = ID2SYM(rb_intern("password"));
731
- sym_host = ID2SYM(rb_intern("host"));
732
- sym_port = ID2SYM(rb_intern("port"));
733
- sym_socket = ID2SYM(rb_intern("socket"));
734
- sym_connect_timeout = ID2SYM(rb_intern("connect_timeout"));
735
- sym_id = ID2SYM(rb_intern("id"));
736
- sym_version = ID2SYM(rb_intern("version"));
737
- sym_sslkey = ID2SYM(rb_intern("sslkey"));
738
- sym_sslcert = ID2SYM(rb_intern("sslcert"));
739
- sym_sslca = ID2SYM(rb_intern("sslca"));
740
- sym_sslcapath = ID2SYM(rb_intern("sslcapath"));
741
- sym_sslcipher = ID2SYM(rb_intern("sslcipher"));
742
- sym_async = ID2SYM(rb_intern("async"));
743
-
744
- #ifdef HAVE_RUBY_ENCODING_H
745
- utf8Encoding = rb_enc_find_index("UTF-8");
746
- binaryEncoding = rb_enc_find_index("binary");
747
- #endif
748
- }