mysql2 0.2.6-x86-mingw32

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.
Files changed (45) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/CHANGELOG.md +117 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +240 -0
  6. data/Rakefile +5 -0
  7. data/VERSION +1 -0
  8. data/benchmark/active_record.rb +53 -0
  9. data/benchmark/allocations.rb +33 -0
  10. data/benchmark/escape.rb +39 -0
  11. data/benchmark/query_with_mysql_casting.rb +83 -0
  12. data/benchmark/query_without_mysql_casting.rb +50 -0
  13. data/benchmark/sequel.rb +39 -0
  14. data/benchmark/setup_db.rb +115 -0
  15. data/examples/eventmachine.rb +21 -0
  16. data/examples/threaded.rb +20 -0
  17. data/ext/mysql2/client.c +659 -0
  18. data/ext/mysql2/client.h +41 -0
  19. data/ext/mysql2/extconf.rb +65 -0
  20. data/ext/mysql2/mysql2_ext.c +12 -0
  21. data/ext/mysql2/mysql2_ext.h +32 -0
  22. data/ext/mysql2/result.c +475 -0
  23. data/ext/mysql2/result.h +20 -0
  24. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +63 -0
  25. data/lib/active_record/connection_adapters/mysql2_adapter.rb +654 -0
  26. data/lib/active_record/fiber_patches.rb +104 -0
  27. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +11 -0
  28. data/lib/mysql2.rb +16 -0
  29. data/lib/mysql2/client.rb +235 -0
  30. data/lib/mysql2/em.rb +33 -0
  31. data/lib/mysql2/error.rb +15 -0
  32. data/lib/mysql2/result.rb +5 -0
  33. data/mysql2.gemspec +89 -0
  34. data/spec/em/em_spec.rb +49 -0
  35. data/spec/mysql2/client_spec.rb +348 -0
  36. data/spec/mysql2/error_spec.rb +25 -0
  37. data/spec/mysql2/result_spec.rb +318 -0
  38. data/spec/rcov.opts +3 -0
  39. data/spec/spec_helper.rb +67 -0
  40. data/tasks/benchmarks.rake +8 -0
  41. data/tasks/compile.rake +54 -0
  42. data/tasks/jeweler.rake +17 -0
  43. data/tasks/rspec.rake +16 -0
  44. data/tasks/vendor_mysql.rake +41 -0
  45. metadata +120 -0
@@ -0,0 +1,49 @@
1
+ # encoding: UTF-8
2
+ if defined? EventMachine
3
+ require 'spec_helper'
4
+ require 'mysql2/em'
5
+
6
+ describe Mysql2::EM::Client do
7
+ it "should support async queries" do
8
+ results = []
9
+ EM.run do
10
+ client1 = Mysql2::EM::Client.new
11
+ defer1 = client1.query "SELECT sleep(0.1) as first_query"
12
+ defer1.callback do |result|
13
+ results << result.first
14
+ EM.stop_event_loop
15
+ end
16
+
17
+ client2 = Mysql2::EM::Client.new
18
+ defer2 = client2.query "SELECT sleep(0.025) second_query"
19
+ defer2.callback do |result|
20
+ results << result.first
21
+ end
22
+ end
23
+
24
+ results[0].keys.should include("second_query")
25
+ results[1].keys.should include("first_query")
26
+ end
27
+
28
+ it "should support queries in callbacks" do
29
+ results = []
30
+ EM.run do
31
+ client = Mysql2::EM::Client.new
32
+ defer1 = client.query "SELECT sleep(0.025) as first_query"
33
+ defer1.callback do |result|
34
+ results << result.first
35
+ defer2 = client.query "SELECT sleep(0.025) as second_query"
36
+ defer2.callback do |result|
37
+ results << result.first
38
+ EM.stop_event_loop
39
+ end
40
+ end
41
+ end
42
+
43
+ results[0].keys.should include("first_query")
44
+ results[1].keys.should include("second_query")
45
+ end
46
+ end
47
+ else
48
+ puts "EventMachine not installed, skipping the specs that use it"
49
+ end
@@ -0,0 +1,348 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Client do
5
+ before(:each) do
6
+ @client = Mysql2::Client.new
7
+ end
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
+
17
+ it "should accept connect flags and pass them to #connect" do
18
+ klient = Class.new(Mysql2::Client) do
19
+ attr_reader :connect_args
20
+ def connect *args
21
+ @connect_args ||= []
22
+ @connect_args << args
23
+ end
24
+ end
25
+ client = klient.new :flags => Mysql2::Client::FOUND_ROWS
26
+ (client.connect_args.last.last & Mysql2::Client::FOUND_ROWS).should be_true
27
+ end
28
+
29
+ it "should default flags to (REMEMBER_OPTIONS, LONG_PASSWORD, LONG_FLAG, TRANSACTIONS, PROTOCOL_41, SECURE_CONNECTION)" do
30
+ klient = Class.new(Mysql2::Client) do
31
+ attr_reader :connect_args
32
+ def connect *args
33
+ @connect_args ||= []
34
+ @connect_args << args
35
+ end
36
+ end
37
+ client = klient.new
38
+ (client.connect_args.last.last & (Mysql2::Client::REMEMBER_OPTIONS |
39
+ Mysql2::Client::LONG_PASSWORD |
40
+ Mysql2::Client::LONG_FLAG |
41
+ Mysql2::Client::TRANSACTIONS |
42
+ Mysql2::Client::PROTOCOL_41 |
43
+ Mysql2::Client::SECURE_CONNECTION)).should be_true
44
+ end
45
+
46
+ it "should have a global default_query_options hash" do
47
+ Mysql2::Client.should respond_to(:default_query_options)
48
+ end
49
+
50
+ it "should be able to connect via SSL options" do
51
+ 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.")
52
+ ssl_client = nil
53
+ lambda {
54
+ ssl_client = Mysql2::Client.new(
55
+ :sslkey => '/path/to/client-key.pem',
56
+ :sslcert => '/path/to/client-cert.pem',
57
+ :sslca => '/path/to/ca-cert.pem',
58
+ :sslcapath => '/path/to/newcerts/',
59
+ :sslcipher => 'DHE-RSA-AES256-SHA'
60
+ )
61
+ }.should_not raise_error(Mysql2::Error)
62
+
63
+ results = ssl_client.query("SHOW STATUS WHERE Variable_name = \"Ssl_version\" OR Variable_name = \"Ssl_cipher\"").to_a
64
+ results[0]['Variable_name'].should eql('Ssl_cipher')
65
+ results[0]['Value'].should_not be_nil
66
+ results[0]['Value'].class.should eql(String)
67
+
68
+ results[1]['Variable_name'].should eql('Ssl_version')
69
+ results[1]['Value'].should_not be_nil
70
+ results[1]['Value'].class.should eql(String)
71
+ end
72
+
73
+ it "should respond to #close" do
74
+ @client.should respond_to(:close)
75
+ end
76
+
77
+ it "should be able to close properly" do
78
+ @client.close.should be_nil
79
+ lambda {
80
+ @client.query "SELECT 1"
81
+ }.should raise_error(Mysql2::Error)
82
+ end
83
+
84
+ it "should respond to #query" do
85
+ @client.should respond_to(:query)
86
+ end
87
+
88
+ context "#query" do
89
+ it "should accept an options hash that inherits from Mysql2::Client.default_query_options" do
90
+ @client.query "SELECT 1", :something => :else
91
+ @client.query_options.should eql(@client.query_options.merge(:something => :else))
92
+ end
93
+
94
+ it "should return results as a hash by default" do
95
+ @client.query("SELECT 1").first.class.should eql(Hash)
96
+ end
97
+
98
+ it "should be able to return results as an array" do
99
+ @client.query("SELECT 1", :as => :array).first.class.should eql(Array)
100
+ @client.query("SELECT 1").each(:as => :array)
101
+ end
102
+
103
+ it "should be able to return results with symbolized keys" do
104
+ @client.query("SELECT 1", :symbolize_keys => true).first.keys[0].class.should eql(Symbol)
105
+ end
106
+
107
+ it "should not allow another query to be sent without fetching a result first" do
108
+ @client.query("SELECT 1", :async => true)
109
+ lambda {
110
+ @client.query("SELECT 1")
111
+ }.should raise_error(Mysql2::Error)
112
+ end
113
+
114
+ it "should require an open connection" do
115
+ @client.close
116
+ lambda {
117
+ @client.query "SELECT 1"
118
+ }.should raise_error(Mysql2::Error)
119
+ end
120
+
121
+ # XXX this test is not deterministic (because Unix signal handling is not)
122
+ # and may fail on a loaded system
123
+ if RUBY_PLATFORM !~ /mingw|mswin/
124
+ it "should run signal handlers while waiting for a response" do
125
+ mark = {}
126
+ trap(:USR1) { mark[:USR1] = Time.now }
127
+ begin
128
+ mark[:START] = Time.now
129
+ pid = fork do
130
+ sleep 1 # wait for client "SELECT sleep(2)" query to start
131
+ Process.kill(:USR1, Process.ppid)
132
+ sleep # wait for explicit kill to prevent GC disconnect
133
+ end
134
+ @client.query("SELECT sleep(2)")
135
+ mark[:END] = Time.now
136
+ mark.include?(:USR1).should be_true
137
+ (mark[:USR1] - mark[:START]).should >= 1
138
+ (mark[:USR1] - mark[:START]).should < 1.1
139
+ (mark[:END] - mark[:USR1]).should > 0.9
140
+ (mark[:END] - mark[:START]).should >= 2
141
+ (mark[:END] - mark[:START]).should < 2.1
142
+ Process.kill(:TERM, pid)
143
+ Process.waitpid2(pid)
144
+ ensure
145
+ trap(:USR1, 'DEFAULT')
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ it "should respond to #escape" do
152
+ @client.should respond_to(:escape)
153
+ end
154
+
155
+ context "#escape" do
156
+ it "should return a new SQL-escape version of the passed string" do
157
+ @client.escape("abc'def\"ghi\0jkl%mno").should eql("abc\\'def\\\"ghi\\0jkl%mno")
158
+ end
159
+
160
+ it "should return the passed string if nothing was escaped" do
161
+ str = "plain"
162
+ @client.escape(str).object_id.should eql(str.object_id)
163
+ end
164
+
165
+ it "should not overflow the thread stack" do
166
+ lambda {
167
+ Thread.new { @client.escape("'" * 256 * 1024) }.join
168
+ }.should_not raise_error(SystemStackError)
169
+ end
170
+
171
+ it "should not overflow the process stack" do
172
+ lambda {
173
+ Thread.new { @client.escape("'" * 1024 * 1024 * 4) }.join
174
+ }.should_not raise_error(SystemStackError)
175
+ end
176
+
177
+ it "should require an open connection" do
178
+ @client.close
179
+ lambda {
180
+ @client.escape ""
181
+ }.should raise_error(Mysql2::Error)
182
+ end
183
+ end
184
+
185
+ it "should respond to #info" do
186
+ @client.should respond_to(:info)
187
+ end
188
+
189
+ it "#info should return a hash containing the client version ID and String" do
190
+ info = @client.info
191
+ info.class.should eql(Hash)
192
+ info.should have_key(:id)
193
+ info[:id].class.should eql(Fixnum)
194
+ info.should have_key(:version)
195
+ info[:version].class.should eql(String)
196
+ end
197
+
198
+ if defined? Encoding
199
+ context "strings returned by #info" do
200
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
201
+ Encoding.default_internal = nil
202
+ @client.info[:version].encoding.should eql(Encoding.find('utf-8'))
203
+
204
+ client2 = Mysql2::Client.new :encoding => 'ascii'
205
+ client2.info[:version].encoding.should eql(Encoding.find('us-ascii'))
206
+ end
207
+
208
+ it "should use Encoding.default_internal" do
209
+ Encoding.default_internal = Encoding.find('utf-8')
210
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
211
+ Encoding.default_internal = Encoding.find('us-ascii')
212
+ @client.info[:version].encoding.should eql(Encoding.default_internal)
213
+ end
214
+ end
215
+ end
216
+
217
+ it "should respond to #server_info" do
218
+ @client.should respond_to(:server_info)
219
+ end
220
+
221
+ it "#server_info should return a hash containing the client version ID and String" do
222
+ server_info = @client.server_info
223
+ server_info.class.should eql(Hash)
224
+ server_info.should have_key(:id)
225
+ server_info[:id].class.should eql(Fixnum)
226
+ server_info.should have_key(:version)
227
+ server_info[:version].class.should eql(String)
228
+ end
229
+
230
+ it "#server_info should require an open connection" do
231
+ @client.close
232
+ lambda {
233
+ @client.server_info
234
+ }.should raise_error(Mysql2::Error)
235
+ end
236
+
237
+ if defined? Encoding
238
+ context "strings returned by #server_info" do
239
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
240
+ Encoding.default_internal = nil
241
+ @client.server_info[:version].encoding.should eql(Encoding.find('utf-8'))
242
+
243
+ client2 = Mysql2::Client.new :encoding => 'ascii'
244
+ client2.server_info[:version].encoding.should eql(Encoding.find('us-ascii'))
245
+ end
246
+
247
+ it "should use Encoding.default_internal" do
248
+ Encoding.default_internal = Encoding.find('utf-8')
249
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
250
+ Encoding.default_internal = Encoding.find('us-ascii')
251
+ @client.server_info[:version].encoding.should eql(Encoding.default_internal)
252
+ end
253
+ end
254
+ end
255
+
256
+ it "should respond to #socket" do
257
+ @client.should respond_to(:socket)
258
+ end
259
+
260
+ it "#socket should return a Fixnum (file descriptor from C)" do
261
+ @client.socket.class.should eql(Fixnum)
262
+ @client.socket.should_not eql(0)
263
+ end
264
+
265
+ it "#socket should require an open connection" do
266
+ @client.close
267
+ lambda {
268
+ @client.socket
269
+ }.should raise_error(Mysql2::Error)
270
+ end
271
+
272
+ it "should raise a Mysql2::Error exception upon connection failure" do
273
+ lambda {
274
+ bad_client = Mysql2::Client.new :host => "dfjhdi9wrhw", :username => 'asdfasdf8d2h'
275
+ }.should raise_error(Mysql2::Error)
276
+
277
+ lambda {
278
+ good_client = Mysql2::Client.new
279
+ }.should_not raise_error(Mysql2::Error)
280
+ end
281
+
282
+ it "threaded queries should be supported" do
283
+ threads, results = [], {}
284
+ connect = lambda{ Mysql2::Client.new(:host => "localhost", :username => "root") }
285
+ Timeout.timeout(0.7) do
286
+ 5.times {
287
+ threads << Thread.new do
288
+ results[Thread.current.object_id] = connect.call.query("SELECT sleep(0.5) as result")
289
+ end
290
+ }
291
+ end
292
+ threads.each{|t| t.join }
293
+ results.keys.sort.should eql(threads.map{|t| t.object_id }.sort)
294
+ end
295
+
296
+ it "evented async queries should be supported" do
297
+ # should immediately return nil
298
+ @client.query("SELECT sleep(0.1)", :async => true).should eql(nil)
299
+
300
+ io_wrapper = IO.for_fd(@client.socket)
301
+ loops = 0
302
+ loop do
303
+ if IO.select([io_wrapper], nil, nil, 0.05)
304
+ break
305
+ else
306
+ loops += 1
307
+ end
308
+ end
309
+
310
+ # make sure we waited some period of time
311
+ (loops >= 1).should be_true
312
+
313
+ result = @client.async_result
314
+ result.class.should eql(Mysql2::Result)
315
+ end
316
+
317
+ context 'write operations api' do
318
+ before(:each) do
319
+ @client.query "USE test"
320
+ @client.query "CREATE TABLE lastIdTest (`id` int(11) NOT NULL AUTO_INCREMENT, blah INT(11), PRIMARY KEY (`id`))"
321
+ end
322
+
323
+ after(:each) do
324
+ @client.query "DROP TABLE lastIdTest"
325
+ end
326
+
327
+ it "should respond to #last_id" do
328
+ @client.should respond_to(:last_id)
329
+ end
330
+
331
+ it "#last_id should return a Fixnum, the from the last INSERT/UPDATE" do
332
+ @client.last_id.should eql(0)
333
+ @client.query "INSERT INTO lastIdTest (blah) VALUES (1234)"
334
+ @client.last_id.should eql(1)
335
+ end
336
+
337
+ it "should respond to #last_id" do
338
+ @client.should respond_to(:last_id)
339
+ end
340
+
341
+ it "#last_id should return a Fixnum, the from the last INSERT/UPDATE" do
342
+ @client.query "INSERT INTO lastIdTest (blah) VALUES (1234)"
343
+ @client.affected_rows.should eql(1)
344
+ @client.query "UPDATE lastIdTest SET blah=4321 WHERE id=1"
345
+ @client.affected_rows.should eql(1)
346
+ end
347
+ end
348
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Error do
5
+ before(:each) do
6
+ @error = Mysql2::Error.new "testing"
7
+ end
8
+
9
+ it "should respond to #error_number" do
10
+ @error.should respond_to(:error_number)
11
+ end
12
+
13
+ it "should respond to #sql_state" do
14
+ @error.should respond_to(:sql_state)
15
+ end
16
+
17
+ # Mysql gem compatibility
18
+ it "should alias #error_number to #errno" do
19
+ @error.should respond_to(:errno)
20
+ end
21
+
22
+ it "should alias #message to #error" do
23
+ @error.should respond_to(:error)
24
+ end
25
+ end
@@ -0,0 +1,318 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Result do
5
+ before(:each) do
6
+ @client = Mysql2::Client.new :host => "localhost", :username => "root"
7
+ end
8
+
9
+ before(:each) do
10
+ @result = @client.query "SELECT 1"
11
+ end
12
+
13
+ it "should have included Enumerable" do
14
+ Mysql2::Result.ancestors.include?(Enumerable).should be_true
15
+ end
16
+
17
+ it "should respond to #each" do
18
+ @result.should respond_to(:each)
19
+ end
20
+
21
+ it "should raise a Mysql2::Error exception upon a bad query" do
22
+ lambda {
23
+ @client.query "bad sql"
24
+ }.should raise_error(Mysql2::Error)
25
+
26
+ lambda {
27
+ @client.query "SELECT 1"
28
+ }.should_not raise_error(Mysql2::Error)
29
+ end
30
+
31
+ context "#each" do
32
+ it "should yield rows as hash's" do
33
+ @result.each do |row|
34
+ row.class.should eql(Hash)
35
+ end
36
+ end
37
+
38
+ it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
39
+ @result.each(:symbolize_keys => true) do |row|
40
+ row.keys.first.class.should eql(Symbol)
41
+ end
42
+ end
43
+
44
+ it "should be able to return results as an array" do
45
+ @result.each(:as => :array) do |row|
46
+ row.class.should eql(Array)
47
+ end
48
+ end
49
+
50
+ it "should cache previously yielded results by default" do
51
+ @result.first.object_id.should eql(@result.first.object_id)
52
+ end
53
+
54
+ it "should not cache previously yielded results if cache_rows is disabled" do
55
+ result = @client.query "SELECT 1", :cache_rows => false
56
+ result.first.object_id.should_not eql(result.first.object_id)
57
+ end
58
+ end
59
+
60
+ context "#fields" do
61
+ before(:each) do
62
+ @client.query "USE test"
63
+ @test_result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1")
64
+ end
65
+
66
+ it "method should exist" do
67
+ @test_result.should respond_to(:fields)
68
+ end
69
+
70
+ it "should return an array of field names in proper order" do
71
+ result = @client.query "SELECT 'a', 'b', 'c'"
72
+ result.fields.should eql(['a', 'b', 'c'])
73
+ end
74
+ end
75
+
76
+ context "row data type mapping" do
77
+ before(:each) do
78
+ @client.query "USE test"
79
+ @test_result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
80
+ end
81
+
82
+ it "should return nil for a NULL value" do
83
+ @test_result['null_test'].class.should eql(NilClass)
84
+ @test_result['null_test'].should eql(nil)
85
+ end
86
+
87
+ it "should return Fixnum for a BIT value" do
88
+ @test_result['bit_test'].class.should eql(String)
89
+ @test_result['bit_test'].should eql("\000\000\000\000\000\000\000\005")
90
+ end
91
+
92
+ it "should return Fixnum for a TINYINT value" do
93
+ [Fixnum, Bignum].should include(@test_result['tiny_int_test'].class)
94
+ @test_result['tiny_int_test'].should eql(1)
95
+ end
96
+
97
+ it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
98
+ @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (1)'
99
+ id1 = @client.last_id
100
+ @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
101
+ id2 = @client.last_id
102
+
103
+ result1 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast_booleans => true
104
+ result2 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 0 LIMIT 1', :cast_booleans => true
105
+ result1.first['bool_cast_test'].should be_true
106
+ result2.first['bool_cast_test'].should be_false
107
+
108
+ @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
109
+ end
110
+
111
+ it "should return Fixnum for a SMALLINT value" do
112
+ [Fixnum, Bignum].should include(@test_result['small_int_test'].class)
113
+ @test_result['small_int_test'].should eql(10)
114
+ end
115
+
116
+ it "should return Fixnum for a MEDIUMINT value" do
117
+ [Fixnum, Bignum].should include(@test_result['medium_int_test'].class)
118
+ @test_result['medium_int_test'].should eql(10)
119
+ end
120
+
121
+ it "should return Fixnum for an INT value" do
122
+ [Fixnum, Bignum].should include(@test_result['int_test'].class)
123
+ @test_result['int_test'].should eql(10)
124
+ end
125
+
126
+ it "should return Fixnum for a BIGINT value" do
127
+ [Fixnum, Bignum].should include(@test_result['big_int_test'].class)
128
+ @test_result['big_int_test'].should eql(10)
129
+ end
130
+
131
+ it "should return Fixnum for a YEAR value" do
132
+ [Fixnum, Bignum].should include(@test_result['year_test'].class)
133
+ @test_result['year_test'].should eql(2009)
134
+ end
135
+
136
+ it "should return BigDecimal for a DECIMAL value" do
137
+ @test_result['decimal_test'].class.should eql(BigDecimal)
138
+ @test_result['decimal_test'].should eql(10.3)
139
+ end
140
+
141
+ it "should return Float for a FLOAT value" do
142
+ @test_result['float_test'].class.should eql(Float)
143
+ @test_result['float_test'].should eql(10.3)
144
+ end
145
+
146
+ it "should return Float for a DOUBLE value" do
147
+ @test_result['double_test'].class.should eql(Float)
148
+ @test_result['double_test'].should eql(10.3)
149
+ end
150
+
151
+ it "should return Time for a DATETIME value when within the supported range" do
152
+ @test_result['date_time_test'].class.should eql(Time)
153
+ @test_result['date_time_test'].strftime("%F %T").should eql('2010-04-04 11:44:00')
154
+ end
155
+
156
+ it "should return DateTime for a DATETIME value when outside the supported range" do
157
+ r = @client.query("SELECT CAST('1901-1-1 01:01:01' AS DATETIME) as test")
158
+ r.first['test'].class.should eql(DateTime)
159
+ end
160
+
161
+ it "should return Time for a TIMESTAMP value when within the supported range" do
162
+ @test_result['timestamp_test'].class.should eql(Time)
163
+ @test_result['timestamp_test'].strftime("%F %T").should eql('2010-04-04 11:44:00')
164
+ end
165
+
166
+ it "should return Time for a TIME value" do
167
+ @test_result['time_test'].class.should eql(Time)
168
+ @test_result['time_test'].strftime("%F %T").should eql('2000-01-01 11:44:00')
169
+ end
170
+
171
+ it "should return Date for a DATE value" do
172
+ @test_result['date_test'].class.should eql(Date)
173
+ @test_result['date_test'].strftime("%F").should eql('2010-04-04')
174
+ end
175
+
176
+ it "should return String for an ENUM value" do
177
+ @test_result['enum_test'].class.should eql(String)
178
+ @test_result['enum_test'].should eql('val1')
179
+ end
180
+
181
+ if defined? Encoding
182
+ context "string encoding for ENUM values" do
183
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
184
+ Encoding.default_internal = nil
185
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
186
+ result['enum_test'].encoding.should eql(Encoding.find('utf-8'))
187
+
188
+ client2 = Mysql2::Client.new :encoding => 'ascii'
189
+ client2.query "USE test"
190
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
191
+ result['enum_test'].encoding.should eql(Encoding.find('us-ascii'))
192
+ end
193
+
194
+ it "should use Encoding.default_internal" do
195
+ Encoding.default_internal = Encoding.find('utf-8')
196
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
197
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
198
+ Encoding.default_internal = Encoding.find('us-ascii')
199
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
200
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
201
+ end
202
+ end
203
+ end
204
+
205
+ it "should return String for a SET value" do
206
+ @test_result['set_test'].class.should eql(String)
207
+ @test_result['set_test'].should eql('val1,val2')
208
+ end
209
+
210
+ if defined? Encoding
211
+ context "string encoding for SET values" do
212
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
213
+ Encoding.default_internal = nil
214
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
215
+ result['set_test'].encoding.should eql(Encoding.find('utf-8'))
216
+
217
+ client2 = Mysql2::Client.new :encoding => 'ascii'
218
+ client2.query "USE test"
219
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
220
+ result['set_test'].encoding.should eql(Encoding.find('us-ascii'))
221
+ end
222
+
223
+ it "should use Encoding.default_internal" do
224
+ Encoding.default_internal = Encoding.find('utf-8')
225
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
226
+ result['set_test'].encoding.should eql(Encoding.default_internal)
227
+ Encoding.default_internal = Encoding.find('us-ascii')
228
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
229
+ result['set_test'].encoding.should eql(Encoding.default_internal)
230
+ end
231
+ end
232
+ end
233
+
234
+ it "should return String for a BINARY value" do
235
+ @test_result['binary_test'].class.should eql(String)
236
+ @test_result['binary_test'].should eql("test#{"\000"*6}")
237
+ end
238
+
239
+ if defined? Encoding
240
+ context "string encoding for BINARY values" do
241
+ it "should default to binary if Encoding.default_internal is nil" do
242
+ Encoding.default_internal = nil
243
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
244
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
245
+ end
246
+
247
+ it "should not use Encoding.default_internal" do
248
+ Encoding.default_internal = Encoding.find('utf-8')
249
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
250
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
251
+ Encoding.default_internal = Encoding.find('us-ascii')
252
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
253
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
254
+ end
255
+ end
256
+ end
257
+
258
+ {
259
+ 'char_test' => 'CHAR',
260
+ 'varchar_test' => 'VARCHAR',
261
+ 'varbinary_test' => 'VARBINARY',
262
+ 'tiny_blob_test' => 'TINYBLOB',
263
+ 'tiny_text_test' => 'TINYTEXT',
264
+ 'blob_test' => 'BLOB',
265
+ 'text_test' => 'TEXT',
266
+ 'medium_blob_test' => 'MEDIUMBLOB',
267
+ 'medium_text_test' => 'MEDIUMTEXT',
268
+ 'long_blob_test' => 'LONGBLOB',
269
+ 'long_text_test' => 'LONGTEXT'
270
+ }.each do |field, type|
271
+ it "should return a String for #{type}" do
272
+ @test_result[field].class.should eql(String)
273
+ @test_result[field].should eql("test")
274
+ end
275
+
276
+ if defined? Encoding
277
+ context "string encoding for #{type} values" do
278
+ if ['VARBINARY', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB'].include?(type)
279
+ it "should default to binary if Encoding.default_internal is nil" do
280
+ Encoding.default_internal = nil
281
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
282
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
283
+ end
284
+
285
+ it "should not use Encoding.default_internal" do
286
+ Encoding.default_internal = Encoding.find('utf-8')
287
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
288
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
289
+ Encoding.default_internal = Encoding.find('us-ascii')
290
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
291
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
292
+ end
293
+ else
294
+ it "should default to utf-8 if Encoding.default_internal is nil" do
295
+ Encoding.default_internal = nil
296
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
297
+ result[field].encoding.should eql(Encoding.find('utf-8'))
298
+
299
+ client2 = Mysql2::Client.new :encoding => 'ascii'
300
+ client2.query "USE test"
301
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
302
+ result[field].encoding.should eql(Encoding.find('us-ascii'))
303
+ end
304
+
305
+ it "should use Encoding.default_internal" do
306
+ Encoding.default_internal = Encoding.find('utf-8')
307
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
308
+ result[field].encoding.should eql(Encoding.default_internal)
309
+ Encoding.default_internal = Encoding.find('us-ascii')
310
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
311
+ result[field].encoding.should eql(Encoding.default_internal)
312
+ end
313
+ end
314
+ end
315
+ end
316
+ end
317
+ end
318
+ end