solaris-mysql2 0.3.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +3 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +7 -0
  5. data/CHANGELOG.md +244 -0
  6. data/Gemfile +3 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +334 -0
  9. data/Rakefile +5 -0
  10. data/benchmark/active_record.rb +51 -0
  11. data/benchmark/active_record_threaded.rb +42 -0
  12. data/benchmark/allocations.rb +33 -0
  13. data/benchmark/escape.rb +36 -0
  14. data/benchmark/query_with_mysql_casting.rb +80 -0
  15. data/benchmark/query_without_mysql_casting.rb +56 -0
  16. data/benchmark/sequel.rb +37 -0
  17. data/benchmark/setup_db.rb +119 -0
  18. data/benchmark/threaded.rb +44 -0
  19. data/examples/eventmachine.rb +21 -0
  20. data/examples/threaded.rb +20 -0
  21. data/ext/mysql2/client.c +901 -0
  22. data/ext/mysql2/client.h +42 -0
  23. data/ext/mysql2/extconf.rb +74 -0
  24. data/ext/mysql2/mysql2_ext.c +12 -0
  25. data/ext/mysql2/mysql2_ext.h +42 -0
  26. data/ext/mysql2/result.c +566 -0
  27. data/ext/mysql2/result.h +20 -0
  28. data/ext/mysql2/wait_for_single_fd.h +36 -0
  29. data/lib/mysql2.rb +21 -0
  30. data/lib/mysql2/client.rb +264 -0
  31. data/lib/mysql2/em.rb +37 -0
  32. data/lib/mysql2/error.rb +15 -0
  33. data/lib/mysql2/result.rb +5 -0
  34. data/lib/mysql2/version.rb +3 -0
  35. data/solaris-mysql2.gemspec +29 -0
  36. data/spec/em/em_spec.rb +50 -0
  37. data/spec/mysql2/client_spec.rb +465 -0
  38. data/spec/mysql2/error_spec.rb +69 -0
  39. data/spec/mysql2/result_spec.rb +388 -0
  40. data/spec/rcov.opts +3 -0
  41. data/spec/spec_helper.rb +67 -0
  42. data/tasks/benchmarks.rake +20 -0
  43. data/tasks/compile.rake +71 -0
  44. data/tasks/rspec.rake +16 -0
  45. data/tasks/vendor_mysql.rake +40 -0
  46. metadata +198 -0
@@ -0,0 +1,69 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Mysql2::Error do
5
+ before(:each) do
6
+ @client = Mysql2::Client.new :encoding => "utf8"
7
+ begin
8
+ @client.query("HAHAHA")
9
+ rescue Mysql2::Error => e
10
+ @error = e
11
+ end
12
+
13
+ @client2 = Mysql2::Client.new :encoding => "big5"
14
+ begin
15
+ @client2.query("HAHAHA")
16
+ rescue Mysql2::Error => e
17
+ @error2 = e
18
+ end
19
+ end
20
+
21
+ it "should respond to #error_number" do
22
+ @error.should respond_to(:error_number)
23
+ end
24
+
25
+ it "should respond to #sql_state" do
26
+ @error.should respond_to(:sql_state)
27
+ end
28
+
29
+ # Mysql gem compatibility
30
+ it "should alias #error_number to #errno" do
31
+ @error.should respond_to(:errno)
32
+ end
33
+
34
+ it "should alias #message to #error" do
35
+ @error.should respond_to(:error)
36
+ end
37
+
38
+ if RUBY_VERSION =~ /1.9/
39
+ it "#message encoding should match the connection's encoding, or Encoding.default_internal if set" do
40
+ if Encoding.default_internal.nil?
41
+ @error.message.encoding.should eql(@client.encoding)
42
+ @error2.message.encoding.should eql(@client2.encoding)
43
+ else
44
+ @error.message.encoding.should eql(Encoding.default_internal)
45
+ @error2.message.encoding.should eql(Encoding.default_internal)
46
+ end
47
+ end
48
+
49
+ it "#error encoding should match the connection's encoding, or Encoding.default_internal if set" do
50
+ if Encoding.default_internal.nil?
51
+ @error.error.encoding.should eql(@client.encoding)
52
+ @error2.error.encoding.should eql(@client2.encoding)
53
+ else
54
+ @error.error.encoding.should eql(Encoding.default_internal)
55
+ @error2.error.encoding.should eql(Encoding.default_internal)
56
+ end
57
+ end
58
+
59
+ it "#sql_state encoding should match the connection's encoding, or Encoding.default_internal if set" do
60
+ if Encoding.default_internal.nil?
61
+ @error.sql_state.encoding.should eql(@client.encoding)
62
+ @error2.sql_state.encoding.should eql(@client2.encoding)
63
+ else
64
+ @error.sql_state.encoding.should eql(Encoding.default_internal)
65
+ @error2.sql_state.encoding.should eql(Encoding.default_internal)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,388 @@
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", :database => 'test'
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
+ it "should respond to #count, which is aliased as #size" do
32
+ r = @client.query "SELECT 1"
33
+ r.should respond_to :count
34
+ r.should respond_to :size
35
+ end
36
+
37
+ it "should be able to return the number of rows in the result set" do
38
+ r = @client.query "SELECT 1"
39
+ r.count.should eql(1)
40
+ r.size.should eql(1)
41
+ end
42
+
43
+ context "metadata queries" do
44
+ it "should show tables" do
45
+ @result = @client.query "SHOW TABLES"
46
+ end
47
+ end
48
+
49
+ context "#each" do
50
+ it "should yield rows as hash's" do
51
+ @result.each do |row|
52
+ row.class.should eql(Hash)
53
+ end
54
+ end
55
+
56
+ it "should yield rows as hash's with symbol keys if :symbolize_keys was set to true" do
57
+ @result.each(:symbolize_keys => true) do |row|
58
+ row.keys.first.class.should eql(Symbol)
59
+ end
60
+ end
61
+
62
+ it "should be able to return results as an array" do
63
+ @result.each(:as => :array) do |row|
64
+ row.class.should eql(Array)
65
+ end
66
+ end
67
+
68
+ it "should cache previously yielded results by default" do
69
+ @result.first.object_id.should eql(@result.first.object_id)
70
+ end
71
+
72
+ it "should not cache previously yielded results if cache_rows is disabled" do
73
+ result = @client.query "SELECT 1", :cache_rows => false
74
+ result.first.object_id.should_not eql(result.first.object_id)
75
+ end
76
+ end
77
+
78
+ context "#fields" do
79
+ before(:each) do
80
+ @client.query "USE test"
81
+ @test_result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1")
82
+ end
83
+
84
+ it "method should exist" do
85
+ @test_result.should respond_to(:fields)
86
+ end
87
+
88
+ it "should return an array of field names in proper order" do
89
+ result = @client.query "SELECT 'a', 'b', 'c'"
90
+ result.fields.should eql(['a', 'b', 'c'])
91
+ end
92
+ end
93
+
94
+ context "row data type mapping" do
95
+ before(:each) do
96
+ @client.query "USE test"
97
+ @test_result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
98
+ end
99
+
100
+ it "should return nil values for NULL and strings for everything else when :cast is false" do
101
+ result = @client.query('SELECT null_test, tiny_int_test, bool_cast_test, int_test, date_test, enum_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast => false).first
102
+ result["null_test"].should be_nil
103
+ result["tiny_int_test"].should == "1"
104
+ result["bool_cast_test"].should == "1"
105
+ result["int_test"].should == "10"
106
+ result["date_test"].should == "2010-04-04"
107
+ result["enum_test"].should == "val1"
108
+ end
109
+
110
+ it "should return nil for a NULL value" do
111
+ @test_result['null_test'].class.should eql(NilClass)
112
+ @test_result['null_test'].should eql(nil)
113
+ end
114
+
115
+ it "should return Fixnum for a BIT value" do
116
+ @test_result['bit_test'].class.should eql(String)
117
+ @test_result['bit_test'].should eql("\000\000\000\000\000\000\000\005")
118
+ end
119
+
120
+ it "should return Fixnum for a TINYINT value" do
121
+ [Fixnum, Bignum].should include(@test_result['tiny_int_test'].class)
122
+ @test_result['tiny_int_test'].should eql(1)
123
+ end
124
+
125
+ it "should return TrueClass or FalseClass for a TINYINT value if :cast_booleans is enabled" do
126
+ @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (1)'
127
+ id1 = @client.last_id
128
+ @client.query 'INSERT INTO mysql2_test (bool_cast_test) VALUES (0)'
129
+ id2 = @client.last_id
130
+
131
+ result1 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 1 LIMIT 1', :cast_booleans => true
132
+ result2 = @client.query 'SELECT bool_cast_test FROM mysql2_test WHERE bool_cast_test = 0 LIMIT 1', :cast_booleans => true
133
+ result1.first['bool_cast_test'].should be_true
134
+ result2.first['bool_cast_test'].should be_false
135
+
136
+ @client.query "DELETE from mysql2_test WHERE id IN(#{id1},#{id2})"
137
+ end
138
+
139
+ it "should return Fixnum for a SMALLINT value" do
140
+ [Fixnum, Bignum].should include(@test_result['small_int_test'].class)
141
+ @test_result['small_int_test'].should eql(10)
142
+ end
143
+
144
+ it "should return Fixnum for a MEDIUMINT value" do
145
+ [Fixnum, Bignum].should include(@test_result['medium_int_test'].class)
146
+ @test_result['medium_int_test'].should eql(10)
147
+ end
148
+
149
+ it "should return Fixnum for an INT value" do
150
+ [Fixnum, Bignum].should include(@test_result['int_test'].class)
151
+ @test_result['int_test'].should eql(10)
152
+ end
153
+
154
+ it "should return Fixnum for a BIGINT value" do
155
+ [Fixnum, Bignum].should include(@test_result['big_int_test'].class)
156
+ @test_result['big_int_test'].should eql(10)
157
+ end
158
+
159
+ it "should return Fixnum for a YEAR value" do
160
+ [Fixnum, Bignum].should include(@test_result['year_test'].class)
161
+ @test_result['year_test'].should eql(2009)
162
+ end
163
+
164
+ it "should return BigDecimal for a DECIMAL value" do
165
+ @test_result['decimal_test'].class.should eql(BigDecimal)
166
+ @test_result['decimal_test'].should eql(10.3)
167
+ end
168
+
169
+ it "should return Float for a FLOAT value" do
170
+ @test_result['float_test'].class.should eql(Float)
171
+ @test_result['float_test'].should eql(10.3)
172
+ end
173
+
174
+ it "should return Float for a DOUBLE value" do
175
+ @test_result['double_test'].class.should eql(Float)
176
+ @test_result['double_test'].should eql(10.3)
177
+ end
178
+
179
+ it "should return Time for a DATETIME value when within the supported range" do
180
+ @test_result['date_time_test'].class.should eql(Time)
181
+ @test_result['date_time_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2010-04-04 11:44:00')
182
+ end
183
+
184
+ if 1.size == 4 # 32bit
185
+ if RUBY_VERSION =~ /1.9/
186
+ klass = Time
187
+ else
188
+ klass = DateTime
189
+ end
190
+
191
+ it "should return DateTime when timestamp is < 1901-12-13 20:45:52" do
192
+ # 1901-12-13T20:45:52 is the min for 32bit Ruby 1.8
193
+ r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
194
+ r.first['test'].class.should eql(klass)
195
+ end
196
+
197
+ it "should return DateTime when timestamp is > 2038-01-19T03:14:07" do
198
+ # 2038-01-19T03:14:07 is the max for 32bit Ruby 1.8
199
+ r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
200
+ r.first['test'].class.should eql(klass)
201
+ end
202
+ elsif 1.size == 8 # 64bit
203
+ if RUBY_VERSION =~ /1.9/
204
+ it "should return Time when timestamp is < 1901-12-13 20:45:52" do
205
+ r = @client.query("SELECT CAST('1901-12-13 20:45:51' AS DATETIME) as test")
206
+ r.first['test'].class.should eql(Time)
207
+ end
208
+
209
+ it "should return Time when timestamp is > 2038-01-19T03:14:07" do
210
+ r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
211
+ r.first['test'].class.should eql(Time)
212
+ end
213
+ else
214
+ it "should return Time when timestamp is > 0138-12-31 11:59:59" do
215
+ r = @client.query("SELECT CAST('0139-1-1 00:00:00' AS DATETIME) as test")
216
+ r.first['test'].class.should eql(Time)
217
+ end
218
+
219
+ it "should return DateTime when timestamp is < 0139-1-1T00:00:00" do
220
+ r = @client.query("SELECT CAST('0138-12-31 11:59:59' AS DATETIME) as test")
221
+ r.first['test'].class.should eql(DateTime)
222
+ end
223
+
224
+ it "should return Time when timestamp is > 2038-01-19T03:14:07" do
225
+ r = @client.query("SELECT CAST('2038-01-19 03:14:08' AS DATETIME) as test")
226
+ r.first['test'].class.should eql(Time)
227
+ end
228
+ end
229
+ end
230
+
231
+ it "should return Time for a TIMESTAMP value when within the supported range" do
232
+ @test_result['timestamp_test'].class.should eql(Time)
233
+ @test_result['timestamp_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2010-04-04 11:44:00')
234
+ end
235
+
236
+ it "should return Time for a TIME value" do
237
+ @test_result['time_test'].class.should eql(Time)
238
+ @test_result['time_test'].strftime("%Y-%m-%d %H:%M:%S").should eql('2000-01-01 11:44:00')
239
+ end
240
+
241
+ it "should return Date for a DATE value" do
242
+ @test_result['date_test'].class.should eql(Date)
243
+ @test_result['date_test'].strftime("%Y-%m-%d").should eql('2010-04-04')
244
+ end
245
+
246
+ it "should return String for an ENUM value" do
247
+ @test_result['enum_test'].class.should eql(String)
248
+ @test_result['enum_test'].should eql('val1')
249
+ end
250
+
251
+ if defined? Encoding
252
+ context "string encoding for ENUM values" do
253
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
254
+ Encoding.default_internal = nil
255
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
256
+ result['enum_test'].encoding.should eql(Encoding.find('utf-8'))
257
+
258
+ client2 = Mysql2::Client.new :encoding => 'ascii'
259
+ client2.query "USE test"
260
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
261
+ result['enum_test'].encoding.should eql(Encoding.find('us-ascii'))
262
+ end
263
+
264
+ it "should use Encoding.default_internal" do
265
+ Encoding.default_internal = Encoding.find('utf-8')
266
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
267
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
268
+ Encoding.default_internal = Encoding.find('us-ascii')
269
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
270
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
271
+ end
272
+ end
273
+ end
274
+
275
+ it "should return String for a SET value" do
276
+ @test_result['set_test'].class.should eql(String)
277
+ @test_result['set_test'].should eql('val1,val2')
278
+ end
279
+
280
+ if defined? Encoding
281
+ context "string encoding for SET values" do
282
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
283
+ Encoding.default_internal = nil
284
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
285
+ result['set_test'].encoding.should eql(Encoding.find('utf-8'))
286
+
287
+ client2 = Mysql2::Client.new :encoding => 'ascii'
288
+ client2.query "USE test"
289
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
290
+ result['set_test'].encoding.should eql(Encoding.find('us-ascii'))
291
+ end
292
+
293
+ it "should use Encoding.default_internal" do
294
+ Encoding.default_internal = Encoding.find('utf-8')
295
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
296
+ result['set_test'].encoding.should eql(Encoding.default_internal)
297
+ Encoding.default_internal = Encoding.find('us-ascii')
298
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
299
+ result['set_test'].encoding.should eql(Encoding.default_internal)
300
+ end
301
+ end
302
+ end
303
+
304
+ it "should return String for a BINARY value" do
305
+ @test_result['binary_test'].class.should eql(String)
306
+ @test_result['binary_test'].should eql("test#{"\000"*6}")
307
+ end
308
+
309
+ if defined? Encoding
310
+ context "string encoding for BINARY values" do
311
+ it "should default to binary if Encoding.default_internal is nil" do
312
+ Encoding.default_internal = nil
313
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
314
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
315
+ end
316
+
317
+ it "should not use Encoding.default_internal" do
318
+ Encoding.default_internal = Encoding.find('utf-8')
319
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
320
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
321
+ Encoding.default_internal = Encoding.find('us-ascii')
322
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
323
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
324
+ end
325
+ end
326
+ end
327
+
328
+ {
329
+ 'char_test' => 'CHAR',
330
+ 'varchar_test' => 'VARCHAR',
331
+ 'varbinary_test' => 'VARBINARY',
332
+ 'tiny_blob_test' => 'TINYBLOB',
333
+ 'tiny_text_test' => 'TINYTEXT',
334
+ 'blob_test' => 'BLOB',
335
+ 'text_test' => 'TEXT',
336
+ 'medium_blob_test' => 'MEDIUMBLOB',
337
+ 'medium_text_test' => 'MEDIUMTEXT',
338
+ 'long_blob_test' => 'LONGBLOB',
339
+ 'long_text_test' => 'LONGTEXT'
340
+ }.each do |field, type|
341
+ it "should return a String for #{type}" do
342
+ @test_result[field].class.should eql(String)
343
+ @test_result[field].should eql("test")
344
+ end
345
+
346
+ if defined? Encoding
347
+ context "string encoding for #{type} values" do
348
+ if ['VARBINARY', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB'].include?(type)
349
+ it "should default to binary if Encoding.default_internal is nil" do
350
+ Encoding.default_internal = nil
351
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
352
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
353
+ end
354
+
355
+ it "should not use Encoding.default_internal" do
356
+ Encoding.default_internal = Encoding.find('utf-8')
357
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
358
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
359
+ Encoding.default_internal = Encoding.find('us-ascii')
360
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
361
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
362
+ end
363
+ else
364
+ it "should default to utf-8 if Encoding.default_internal is nil" do
365
+ Encoding.default_internal = nil
366
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
367
+ result[field].encoding.should eql(Encoding.find('utf-8'))
368
+
369
+ client2 = Mysql2::Client.new :encoding => 'ascii'
370
+ client2.query "USE test"
371
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
372
+ result[field].encoding.should eql(Encoding.find('us-ascii'))
373
+ end
374
+
375
+ it "should use Encoding.default_internal" do
376
+ Encoding.default_internal = Encoding.find('utf-8')
377
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
378
+ result[field].encoding.should eql(Encoding.default_internal)
379
+ Encoding.default_internal = Encoding.find('us-ascii')
380
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
381
+ result[field].encoding.should eql(Encoding.default_internal)
382
+ end
383
+ end
384
+ end
385
+ end
386
+ end
387
+ end
388
+ end