rdp-mysql2 0.2.7.1

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 (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