rdp-mysql2 0.2.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/CHANGELOG.md +142 -0
  5. data/Gemfile +3 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.rdoc +261 -0
  8. data/Rakefile +5 -0
  9. data/benchmark/active_record.rb +51 -0
  10. data/benchmark/active_record_threaded.rb +42 -0
  11. data/benchmark/allocations.rb +33 -0
  12. data/benchmark/escape.rb +36 -0
  13. data/benchmark/query_with_mysql_casting.rb +80 -0
  14. data/benchmark/query_without_mysql_casting.rb +47 -0
  15. data/benchmark/sequel.rb +37 -0
  16. data/benchmark/setup_db.rb +119 -0
  17. data/benchmark/threaded.rb +44 -0
  18. data/examples/eventmachine.rb +21 -0
  19. data/examples/threaded.rb +20 -0
  20. data/ext/mysql2/client.c +839 -0
  21. data/ext/mysql2/client.h +41 -0
  22. data/ext/mysql2/extconf.rb +72 -0
  23. data/ext/mysql2/mysql2_ext.c +12 -0
  24. data/ext/mysql2/mysql2_ext.h +42 -0
  25. data/ext/mysql2/result.c +488 -0
  26. data/ext/mysql2/result.h +20 -0
  27. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +64 -0
  28. data/lib/active_record/connection_adapters/mysql2_adapter.rb +654 -0
  29. data/lib/active_record/fiber_patches.rb +104 -0
  30. data/lib/arel/engines/sql/compilers/mysql2_compiler.rb +11 -0
  31. data/lib/mysql2.rb +16 -0
  32. data/lib/mysql2/client.rb +240 -0
  33. data/lib/mysql2/em.rb +37 -0
  34. data/lib/mysql2/em_fiber.rb +31 -0
  35. data/lib/mysql2/error.rb +15 -0
  36. data/lib/mysql2/result.rb +5 -0
  37. data/lib/mysql2/version.rb +3 -0
  38. data/mysql2.gemspec +32 -0
  39. data/spec/em/em_fiber_spec.rb +22 -0
  40. data/spec/em/em_spec.rb +49 -0
  41. data/spec/mysql2/client_spec.rb +430 -0
  42. data/spec/mysql2/error_spec.rb +69 -0
  43. data/spec/mysql2/result_spec.rb +333 -0
  44. data/spec/rcov.opts +3 -0
  45. data/spec/spec_helper.rb +66 -0
  46. data/tasks/benchmarks.rake +20 -0
  47. data/tasks/compile.rake +71 -0
  48. data/tasks/rspec.rake +16 -0
  49. data/tasks/vendor_mysql.rake +40 -0
  50. metadata +236 -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,333 @@
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
+ 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, Time if otherwise" do
157
+ if RUBY_PLATFORM =~ /mswin/
158
+ inside_year = 1970
159
+ outside_year = inside_year-1
160
+ else
161
+ inside_year = 1902
162
+ outside_year = inside_year-1
163
+ end
164
+ r = @client.query("SELECT CAST('#{inside_year}-1-1 01:01:01' AS DATETIME) as test")
165
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /rbx/
166
+ klass = DateTime
167
+ else
168
+ klass = Time
169
+ end
170
+ r.first['test'].class.should eql(klass)
171
+
172
+ r = @client.query("SELECT CAST('#{outside_year}-1-1 01:01:01' AS DATETIME) as test")
173
+ r.first['test'].class.should eql(DateTime)
174
+ end
175
+
176
+ it "should return Time for a TIMESTAMP value when within the supported range" do
177
+ @test_result['timestamp_test'].class.should eql(Time)
178
+ @test_result['timestamp_test'].strftime("%F %T").should eql('2010-04-04 11:44:00')
179
+ end
180
+
181
+ it "should return Time for a TIME value" do
182
+ @test_result['time_test'].class.should eql(Time)
183
+ @test_result['time_test'].strftime("%F %T").should eql('2000-01-01 11:44:00')
184
+ end
185
+
186
+ it "should return Date for a DATE value" do
187
+ @test_result['date_test'].class.should eql(Date)
188
+ @test_result['date_test'].strftime("%F").should eql('2010-04-04')
189
+ end
190
+
191
+ it "should return String for an ENUM value" do
192
+ @test_result['enum_test'].class.should eql(String)
193
+ @test_result['enum_test'].should eql('val1')
194
+ end
195
+
196
+ if defined? Encoding
197
+ context "string encoding for ENUM values" do
198
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
199
+ Encoding.default_internal = nil
200
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
201
+ result['enum_test'].encoding.should eql(Encoding.find('utf-8'))
202
+
203
+ client2 = Mysql2::Client.new :encoding => 'ascii'
204
+ client2.query "USE test"
205
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
206
+ result['enum_test'].encoding.should eql(Encoding.find('us-ascii'))
207
+ end
208
+
209
+ it "should use Encoding.default_internal" do
210
+ Encoding.default_internal = Encoding.find('utf-8')
211
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
212
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
213
+ Encoding.default_internal = Encoding.find('us-ascii')
214
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
215
+ result['enum_test'].encoding.should eql(Encoding.default_internal)
216
+ end
217
+ end
218
+ end
219
+
220
+ it "should return String for a SET value" do
221
+ @test_result['set_test'].class.should eql(String)
222
+ @test_result['set_test'].should eql('val1,val2')
223
+ end
224
+
225
+ if defined? Encoding
226
+ context "string encoding for SET values" do
227
+ it "should default to the connection's encoding if Encoding.default_internal is nil" do
228
+ Encoding.default_internal = nil
229
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
230
+ result['set_test'].encoding.should eql(Encoding.find('utf-8'))
231
+
232
+ client2 = Mysql2::Client.new :encoding => 'ascii'
233
+ client2.query "USE test"
234
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
235
+ result['set_test'].encoding.should eql(Encoding.find('us-ascii'))
236
+ end
237
+
238
+ it "should use Encoding.default_internal" do
239
+ Encoding.default_internal = Encoding.find('utf-8')
240
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
241
+ result['set_test'].encoding.should eql(Encoding.default_internal)
242
+ Encoding.default_internal = Encoding.find('us-ascii')
243
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
244
+ result['set_test'].encoding.should eql(Encoding.default_internal)
245
+ end
246
+ end
247
+ end
248
+
249
+ it "should return String for a BINARY value" do
250
+ @test_result['binary_test'].class.should eql(String)
251
+ @test_result['binary_test'].should eql("test#{"\000"*6}")
252
+ end
253
+
254
+ if defined? Encoding
255
+ context "string encoding for BINARY values" do
256
+ it "should default to binary if Encoding.default_internal is nil" do
257
+ Encoding.default_internal = nil
258
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
259
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
260
+ end
261
+
262
+ it "should not use Encoding.default_internal" do
263
+ Encoding.default_internal = Encoding.find('utf-8')
264
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
265
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
266
+ Encoding.default_internal = Encoding.find('us-ascii')
267
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
268
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
269
+ end
270
+ end
271
+ end
272
+
273
+ {
274
+ 'char_test' => 'CHAR',
275
+ 'varchar_test' => 'VARCHAR',
276
+ 'varbinary_test' => 'VARBINARY',
277
+ 'tiny_blob_test' => 'TINYBLOB',
278
+ 'tiny_text_test' => 'TINYTEXT',
279
+ 'blob_test' => 'BLOB',
280
+ 'text_test' => 'TEXT',
281
+ 'medium_blob_test' => 'MEDIUMBLOB',
282
+ 'medium_text_test' => 'MEDIUMTEXT',
283
+ 'long_blob_test' => 'LONGBLOB',
284
+ 'long_text_test' => 'LONGTEXT'
285
+ }.each do |field, type|
286
+ it "should return a String for #{type}" do
287
+ @test_result[field].class.should eql(String)
288
+ @test_result[field].should eql("test")
289
+ end
290
+
291
+ if defined? Encoding
292
+ context "string encoding for #{type} values" do
293
+ if ['VARBINARY', 'TINYBLOB', 'BLOB', 'MEDIUMBLOB', 'LONGBLOB'].include?(type)
294
+ it "should default to binary 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['binary_test'].encoding.should eql(Encoding.find('binary'))
298
+ end
299
+
300
+ it "should not use Encoding.default_internal" do
301
+ Encoding.default_internal = Encoding.find('utf-8')
302
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
303
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
304
+ Encoding.default_internal = Encoding.find('us-ascii')
305
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
306
+ result['binary_test'].encoding.should eql(Encoding.find('binary'))
307
+ end
308
+ else
309
+ it "should default to utf-8 if Encoding.default_internal is nil" do
310
+ Encoding.default_internal = nil
311
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
312
+ result[field].encoding.should eql(Encoding.find('utf-8'))
313
+
314
+ client2 = Mysql2::Client.new :encoding => 'ascii'
315
+ client2.query "USE test"
316
+ result = client2.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
317
+ result[field].encoding.should eql(Encoding.find('us-ascii'))
318
+ end
319
+
320
+ it "should use Encoding.default_internal" do
321
+ Encoding.default_internal = Encoding.find('utf-8')
322
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
323
+ result[field].encoding.should eql(Encoding.default_internal)
324
+ Encoding.default_internal = Encoding.find('us-ascii')
325
+ result = @client.query("SELECT * FROM mysql2_test ORDER BY id DESC LIMIT 1").first
326
+ result[field].encoding.should eql(Encoding.default_internal)
327
+ end
328
+ end
329
+ end
330
+ end
331
+ end
332
+ end
333
+ end
@@ -0,0 +1,3 @@
1
+ --exclude spec,gem
2
+ --text-summary
3
+ --sort coverage --sort-reverse
@@ -0,0 +1,66 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rspec'
4
+ require 'mysql2'
5
+ require 'timeout'
6
+
7
+ RSpec.configure do |config|
8
+ config.before(:all) do
9
+ client = Mysql2::Client.new :host => "localhost", :username => "root", :database => 'test'
10
+ client.query %[
11
+ CREATE TABLE IF NOT EXISTS mysql2_test (
12
+ id MEDIUMINT NOT NULL AUTO_INCREMENT,
13
+ null_test VARCHAR(10),
14
+ bit_test BIT(64),
15
+ tiny_int_test TINYINT,
16
+ bool_cast_test TINYINT(1),
17
+ small_int_test SMALLINT,
18
+ medium_int_test MEDIUMINT,
19
+ int_test INT,
20
+ big_int_test BIGINT,
21
+ float_test FLOAT(10,3),
22
+ float_zero_test FLOAT(10,3),
23
+ double_test DOUBLE(10,3),
24
+ decimal_test DECIMAL(10,3),
25
+ decimal_zero_test DECIMAL(10,3),
26
+ date_test DATE,
27
+ date_time_test DATETIME,
28
+ timestamp_test TIMESTAMP,
29
+ time_test TIME,
30
+ year_test YEAR(4),
31
+ char_test CHAR(10),
32
+ varchar_test VARCHAR(10),
33
+ binary_test BINARY(10),
34
+ varbinary_test VARBINARY(10),
35
+ tiny_blob_test TINYBLOB,
36
+ tiny_text_test TINYTEXT,
37
+ blob_test BLOB,
38
+ text_test TEXT,
39
+ medium_blob_test MEDIUMBLOB,
40
+ medium_text_test MEDIUMTEXT,
41
+ long_blob_test LONGBLOB,
42
+ long_text_test LONGTEXT,
43
+ enum_test ENUM('val1', 'val2'),
44
+ set_test SET('val1', 'val2'),
45
+ PRIMARY KEY (id)
46
+ )
47
+ ]
48
+ client.query %[
49
+ INSERT INTO mysql2_test (
50
+ null_test, bit_test, tiny_int_test, bool_cast_test, small_int_test, medium_int_test, int_test, big_int_test,
51
+ float_test, float_zero_test, double_test, decimal_test, decimal_zero_test, date_test, date_time_test, timestamp_test, time_test,
52
+ year_test, char_test, varchar_test, binary_test, varbinary_test, tiny_blob_test,
53
+ tiny_text_test, blob_test, text_test, medium_blob_test, medium_text_test,
54
+ long_blob_test, long_text_test, enum_test, set_test
55
+ )
56
+
57
+ VALUES (
58
+ NULL, b'101', 1, 1, 10, 10, 10, 10,
59
+ 10.3, 0, 10.3, 10.3, 0, '2010-4-4', '2010-4-4 11:44:00', '2010-4-4 11:44:00', '11:44:00',
60
+ 2009, "test", "test", "test", "test", "test",
61
+ "test", "test", "test", "test", "test",
62
+ "test", "test", 'val1', 'val1,val2'
63
+ )
64
+ ]
65
+ end
66
+ end