mysql2 0.3.18 → 0.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -0
  3. data/LICENSE +21 -0
  4. data/README.md +132 -55
  5. data/examples/eventmachine.rb +1 -1
  6. data/examples/threaded.rb +4 -6
  7. data/ext/mysql2/client.c +374 -197
  8. data/ext/mysql2/client.h +13 -3
  9. data/ext/mysql2/extconf.rb +119 -35
  10. data/ext/mysql2/infile.c +2 -2
  11. data/ext/mysql2/mysql2_ext.c +1 -0
  12. data/ext/mysql2/mysql2_ext.h +7 -6
  13. data/ext/mysql2/mysql_enc_name_to_ruby.h +2 -2
  14. data/ext/mysql2/mysql_enc_to_ruby.h +25 -22
  15. data/ext/mysql2/result.c +512 -138
  16. data/ext/mysql2/result.h +13 -6
  17. data/ext/mysql2/statement.c +595 -0
  18. data/ext/mysql2/statement.h +19 -0
  19. data/lib/mysql2/client.rb +85 -26
  20. data/lib/mysql2/console.rb +1 -1
  21. data/lib/mysql2/em.rb +5 -6
  22. data/lib/mysql2/error.rb +18 -27
  23. data/lib/mysql2/field.rb +3 -0
  24. data/lib/mysql2/statement.rb +17 -0
  25. data/lib/mysql2/version.rb +1 -1
  26. data/lib/mysql2.rb +38 -18
  27. data/spec/configuration.yml.example +0 -6
  28. data/spec/em/em_spec.rb +22 -21
  29. data/spec/mysql2/client_spec.rb +530 -388
  30. data/spec/mysql2/error_spec.rb +38 -39
  31. data/spec/mysql2/result_spec.rb +223 -214
  32. data/spec/mysql2/statement_spec.rb +763 -0
  33. data/spec/spec_helper.rb +80 -59
  34. data/spec/ssl/ca-cert.pem +17 -0
  35. data/spec/ssl/ca-key.pem +27 -0
  36. data/spec/ssl/ca.cnf +22 -0
  37. data/spec/ssl/cert.cnf +22 -0
  38. data/spec/ssl/client-cert.pem +17 -0
  39. data/spec/ssl/client-key.pem +27 -0
  40. data/spec/ssl/client-req.pem +15 -0
  41. data/spec/ssl/gen_certs.sh +48 -0
  42. data/spec/ssl/pkcs8-client-key.pem +28 -0
  43. data/spec/ssl/pkcs8-server-key.pem +28 -0
  44. data/spec/ssl/server-cert.pem +17 -0
  45. data/spec/ssl/server-key.pem +27 -0
  46. data/spec/ssl/server-req.pem +15 -0
  47. data/support/mysql_enc_to_ruby.rb +7 -8
  48. data/support/ruby_enc_to_mysql.rb +1 -1
  49. metadata +42 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 791bc0352c6464ca1765498b0babcedfad3c284e
4
- data.tar.gz: 08b44b761494ec18a0c9903fcb67bfe61718b77b
3
+ metadata.gz: 81b2c704867b20697229ff4dd023e934fff560bb
4
+ data.tar.gz: c528b0bfb4d5ab7f25282c949c41d8d821d7f7e3
5
5
  SHA512:
6
- metadata.gz: 5554897f395a4fcd71e26612ef895da5d3e1d528ef29604380974950f7216783bf7636197d04228c39b471a51863f75c56e9140e05bb79410e1582c64842d0dc
7
- data.tar.gz: afad060a7a899d69b75ca2c44aa69a07c743984fc6897cce825c6d9ec3269bbb3733671243afe7fb33a615e61e4aa8c7b9e7863fa18289578ab29abc8409e2e8
6
+ metadata.gz: 2851f6e453dc7ab3ead0dc08601f38fbe155b426e41a1ea1fea4a3264d134e56203ed7bf2f41ba7bb1ce7d884fc8594481bfe62f94bcdd2c9960b57d68a93f70
7
+ data.tar.gz: c46c2639a067be942a4192157141fc579f360985052561807537b2fda6363f93cf7e864ab379d443f033cfeef0a4326eaa5d9c1a57235ad5efd498196f1373a2
data/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ Changes are maintained under [Releases](https://github.com/brianmario/mysql2/releases)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Brian Lopez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -9,12 +9,14 @@ This one is not.
9
9
 
10
10
  It also forces the use of UTF-8 [or binary] for the connection [and all strings in 1.9, unless Encoding.default_internal is set then it'll convert from UTF-8 to that encoding] and uses encoding-aware MySQL API calls where it can.
11
11
 
12
- The API consists of two classes:
12
+ The API consists of three classes:
13
13
 
14
14
  `Mysql2::Client` - your connection to the database.
15
15
 
16
16
  `Mysql2::Result` - returned from issuing a #query on the connection. It includes Enumerable.
17
17
 
18
+ `Mysql2::Statement` - returned from issuing a #prepare on the connection. Execute the statement to get a Result.
19
+
18
20
  ## Installing
19
21
  ### General Instructions
20
22
  ``` sh
@@ -56,6 +58,20 @@ This may be needed if you deploy to a system where these libraries
56
58
  are located somewhere different than on your build system.
57
59
  This overrides any rpath calculated by default or by the options above.
58
60
 
61
+ * `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` -
62
+ Enable sanitizers for Clang / GCC. If no argument is given, try to enable
63
+ all sanitizers or fail if none are available. If a command-separated list of
64
+ specific sanitizers is given, configure will fail unless they all are available.
65
+ Note that the some sanitizers may incur a performance penalty, and the Address
66
+ Sanitizer may require a runtime library.
67
+ To see line numbers in backtraces, declare these environment variables
68
+ (adjust the llvm-symbolizer path as needed for your system):
69
+
70
+ ``` sh
71
+ export ASAN_SYMBOLIZER_PATH=/usr/bin/llvm-symbolizer-3.4
72
+ export ASAN_OPTIONS=symbolize=1
73
+ ```
74
+
59
75
  ### Linux and other Unixes
60
76
 
61
77
  You may need to install a package such as `libmysqlclient-dev` or `mysql-devel`;
@@ -69,6 +85,9 @@ You may use MacPorts, Homebrew, or a native MySQL installer package. The most
69
85
  common paths will be automatically searched. If you want to select a specific
70
86
  MySQL directory, use the `--with-mysql-dir` or `--with-mysql-config` options above.
71
87
 
88
+ If you have not done so already, you will need to install the XCode select tools by running
89
+ `xcode-select --install`.
90
+
72
91
  ### Windows
73
92
  Make sure that you have Ruby and the DevKit compilers installed. We recommend
74
93
  the [Ruby Installer](http://rubyinstaller.org) distribution.
@@ -93,7 +112,7 @@ Connect to a database:
93
112
  ``` ruby
94
113
  # this takes a hash of options, almost all of which map directly
95
114
  # to the familiar database.yml in rails
96
- # See http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html
115
+ # See http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html
97
116
  client = Mysql2::Client.new(:host => "localhost", :username => "root")
98
117
  ```
99
118
 
@@ -148,11 +167,25 @@ by the query like this:
148
167
  ``` ruby
149
168
  headers = results.fields # <= that's an array of field names, in order
150
169
  results.each(:as => :array) do |row|
151
- # Each row is an array, ordered the same as the query results
152
- # An otter's den is called a "holt" or "couch"
170
+ # Each row is an array, ordered the same as the query results
171
+ # An otter's den is called a "holt" or "couch"
153
172
  end
154
173
  ```
155
174
 
175
+ Prepared statements are supported, as well. In a prepared statement, use a `?`
176
+ in place of each value and then execute the statement to retrieve a result set.
177
+ Pass your arguments to the execute method in the same number and order as the
178
+ question marks in the statement.
179
+
180
+ ``` ruby
181
+ statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
182
+ result1 = statement.execute(1)
183
+ result2 = statement.execute(2)
184
+
185
+ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
186
+ result = statement.execute(1, "CA")
187
+ ```
188
+
156
189
  ## Connection options
157
190
 
158
191
  You may set the following connection options in Mysql2::Client.new(...):
@@ -173,12 +206,25 @@ Mysql2::Client.new(
173
206
  :reconnect = true/false,
174
207
  :local_infile = true/false,
175
208
  :secure_auth = true/false,
209
+ :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
176
210
  :default_file = '/path/to/my.cfg',
177
211
  :default_group = 'my.cfg section',
178
212
  :init_command => sql
179
213
  )
180
214
  ```
181
215
 
216
+ ### Connecting to MySQL on localhost and elsewhere
217
+
218
+ The underlying MySQL client library uses the `:host` parameter to determine the
219
+ type of connection to make, with special interpretation you should be aware of:
220
+
221
+ * An empty value or `"localhost"` will attempt a local connection:
222
+ * On Unix, connect to the default local socket path. (To set a custom socket
223
+ path, use the `:socket` parameter).
224
+ * On Windows, connect using a shared-memory connection, if enabled, or TCP.
225
+ * A value of `"."` on Windows specifies a named-pipe connection.
226
+ * An IPv4 or IPv6 address will result in a TCP connection.
227
+ * Any other value will be looked up as a hostname for a TCP connection.
182
228
 
183
229
  ### SSL options
184
230
 
@@ -186,7 +232,8 @@ Setting any of the following options will enable an SSL connection, but only if
186
232
  your MySQL client library and server have been compiled with SSL support.
187
233
  MySQL client library defaults will be used for any parameters that are left out
188
234
  or set to nil. Relative paths are allowed, and may be required by managed
189
- hosting providers such as Heroku.
235
+ hosting providers such as Heroku. Set `:sslverify => true` to require that the
236
+ server presents a valid certificate.
190
237
 
191
238
  ``` ruby
192
239
  Mysql2::Client.new(
@@ -195,10 +242,67 @@ Mysql2::Client.new(
195
242
  :sslcert => '/path/to/client-cert.pem',
196
243
  :sslca => '/path/to/ca-cert.pem',
197
244
  :sslcapath => '/path/to/cacerts',
198
- :sslcipher => 'DHE-RSA-AES256-SHA'
245
+ :sslcipher => 'DHE-RSA-AES256-SHA',
246
+ :sslverify => true,
199
247
  )
200
248
  ```
201
249
 
250
+ ### Secure auth
251
+
252
+ Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
253
+ When secure_auth is enabled, the server will refuse a connection if the account password is stored in old pre-MySQL 4.1 format.
254
+ The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password.
255
+ To bypass this restriction in the client, pass the option `:secure_auth => false` to Mysql2::Client.new().
256
+
257
+ ### Flags option parsing
258
+
259
+ The `:flags` parameter accepts an integer, a string, or an array. The integer
260
+ form allows the client to assemble flags from constants defined under
261
+ `Mysql2::Client` such as `Mysql2::Client::FOUND_ROWS`. Use a bitwise `|` (OR)
262
+ to specify several flags.
263
+
264
+ The string form will be split on whitespace and parsed as with the array form:
265
+ Plain flags are added to the default flags, while flags prefixed with `-`
266
+ (minus) are removed from the default flags.
267
+
268
+ This allows easier use with ActiveRecord's database.yml, avoiding the need for magic flag numbers.
269
+ For example, to disable protocol compression, and enable multiple statements and result sets:
270
+
271
+ ``` yaml
272
+ development:
273
+ adapter: mysql2
274
+ encoding: utf8
275
+ database: my_db_name
276
+ username: root
277
+ password: my_password
278
+ host: 127.0.0.1
279
+ port: 3306
280
+ flags:
281
+ - -COMPRESS
282
+ - FOUND_ROWS
283
+ - MULTI_STATEMENTS
284
+ secure_auth: false
285
+ ```
286
+
287
+ ### Reading a MySQL config file
288
+
289
+ You may read configuration options from a MySQL configuration file by passing
290
+ the `:default_file` and `:default_group` parameters. For example:
291
+
292
+ ``` ruby
293
+ Mysql2::Client.new(:default_file => '/user/.my.cnf', :default_group => 'client')
294
+ ```
295
+
296
+ ### Initial command on connect and reconnect
297
+
298
+ If you specify the `:init_command` option, the SQL string you provide will be executed after the connection is established.
299
+ If `:reconnect` is set to `true`, init_command will also be executed after a successful reconnect.
300
+ It is useful if you want to provide session options which survive reconnection.
301
+
302
+ ``` ruby
303
+ Mysql2::Client.new(:init_command => "SET @@SESSION.sql_mode = 'STRICT_ALL_TABLES'")
304
+ ```
305
+
202
306
  ### Multiple result sets
203
307
 
204
308
  You can also retrieve multiple result sets. For this to work you need to
@@ -240,47 +344,6 @@ Yields:
240
344
  next_result: Unknown column 'A' in 'field list' (Mysql2::Error)
241
345
  ```
242
346
 
243
- See https://gist.github.com/1367987 for using MULTI_STATEMENTS with Active Record.
244
-
245
- ### Secure auth
246
-
247
- Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
248
- When secure_auth is enabled, the server will refuse a connection if the account password is stored in old pre-MySQL 4.1 format.
249
- The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password.
250
- To bypass this restriction in the client, pass the option :secure_auth => false to Mysql2::Client.new().
251
- If using ActiveRecord, your database.yml might look something like this:
252
-
253
- ``` yaml
254
- development:
255
- adapter: mysql2
256
- encoding: utf8
257
- database: my_db_name
258
- username: root
259
- password: my_password
260
- host: 127.0.0.1
261
- port: 3306
262
- secure_auth: false
263
- ```
264
-
265
- ### Reading a MySQL config file
266
-
267
- You may read configuration options from a MySQL configuration file by passing
268
- the `:default_file` and `:default_group` paramters. For example:
269
-
270
- ``` ruby
271
- Mysql2::Client.new(:default_file => '/user/.my.cnf', :default_group => 'client')
272
- ```
273
-
274
- ### Initial command on connect and reconnect
275
-
276
- If you specify the init_command option, the SQL string you provide will be executed after the connection is established.
277
- If `:reconnect` is set to `true`, init_command will also be executed after a successful reconnect.
278
- It is useful if you want to provide session options which survive reconnection.
279
-
280
- ``` ruby
281
- Mysql2::Client.new(:init_command => "SET @@SESSION.sql_mode = 'STRICT_ALL_TABLES'")
282
- ```
283
-
284
347
  ## Cascading config
285
348
 
286
349
  The default config hash is at:
@@ -351,6 +414,15 @@ client = Mysql2::Client.new
351
414
  result = client.query("SELECT * FROM table_with_boolean_field", :cast_booleans => true)
352
415
  ```
353
416
 
417
+ Keep in mind that this works only with fields and not with computed values, e.g. this result will contain `1`, not `true`:
418
+
419
+ ``` ruby
420
+ client = Mysql2::Client.new
421
+ result = client.query("SELECT true", :cast_booleans => true)
422
+ ```
423
+
424
+ CAST function wouldn't help here as there's no way to cast to TINYINT(1). Apparently the only way to solve this is to use a stored procedure with return type set to TINYINT(1).
425
+
354
426
  ### Skipping casting
355
427
 
356
428
  Mysql2 casting is fast, but not as fast as not casting data. In rare cases where typecasting is not needed, it will be faster to disable it by providing :cast => false. (Note that :cast => false overrides :cast_booleans => true.)
@@ -437,20 +509,21 @@ As for field values themselves, I'm workin on it - but expect that soon.
437
509
 
438
510
  This gem is tested with the following Ruby versions on Linux and Mac OS X:
439
511
 
440
- * Ruby MRI 1.8.7, 1.9.2, 1.9.3, 2.0.0, 2.1.x, 2.2.x (ongoing patch releases)
512
+ * Ruby MRI 1.8.7, 1.9.3, 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x
441
513
  * Ruby Enterprise Edition (based on MRI 1.8.7)
442
- * Rubinius 2.x
514
+ * Rubinius 2.x and 3.x do work but may fail under some workloads
443
515
 
444
516
  This gem is tested with the following MySQL and MariaDB versions:
445
517
 
446
- * MySQL 5.0, 5.1, 5.5, 5.6, 5.7
518
+ * MySQL 5.5, 5.6, 5.7, 8.0
447
519
  * MySQL Connector/C 6.0 and 6.1 (primarily on Windows)
448
- * MariaDB 5.5, 10.0
520
+ * MariaDB 5.5, 10.0, 10.1
449
521
 
450
- ### Active Record
522
+ ### Ruby on Rails / Active Record
451
523
 
452
- * mysql2 0.2.x includes an Active Record driver compatible with AR 2.3 and 3.0
453
- * mysql2 0.3.x does not include an AR driver because it is included in AR 3.1 and above
524
+ * mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
525
+ * mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
526
+ * mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.
454
527
 
455
528
  ### Asynchronous Active Record
456
529
 
@@ -536,4 +609,8 @@ though.
536
609
  * Yury Korolev (http://github.com/yury) - for TONS of help testing the Active Record adapter
537
610
  * Aaron Patterson (http://github.com/tenderlove) - tons of contributions, suggestions and general badassness
538
611
  * Mike Perham (http://github.com/mperham) - Async Active Record adapter (uses Fibers and EventMachine)
539
- * Aaron Stone (http://github.com/sodabrew) - additional client settings, local files, microsecond time, maintenance support.
612
+ * Aaron Stone (http://github.com/sodabrew) - additional client settings, local files, microsecond time, maintenance support
613
+ * Kouhei Ueno (https://github.com/nyaxt) - for the original work on Prepared Statements way back in 2012
614
+ * John Cant (http://github.com/johncant) - polishing and updating Prepared Statements support
615
+ * Justin Case (http://github.com/justincase) - polishing and updating Prepared Statements support and getting it merged
616
+ * Tamir Duberstein (http://github.com/tamird) - for help with timeouts and all around updates and cleanups
@@ -18,4 +18,4 @@ EM.run do
18
18
  defer2.callback do |result|
19
19
  puts "Result: #{result.to_a.inspect}"
20
20
  end
21
- end
21
+ end
data/examples/threaded.rb CHANGED
@@ -4,17 +4,15 @@ $LOAD_PATH.unshift 'lib'
4
4
  require 'mysql2'
5
5
  require 'timeout'
6
6
 
7
- threads = []
8
7
  # Should never exceed worst case 3.5 secs across all 20 threads
9
8
  Timeout.timeout(3.5) do
10
- 20.times do
11
- threads << Thread.new do
9
+ 20.times.map do
10
+ Thread.new do
12
11
  overhead = rand(3)
13
12
  puts ">> thread #{Thread.current.object_id} query, #{overhead} sec overhead"
14
13
  # 3 second overhead per query
15
14
  Mysql2::Client.new(:host => "localhost", :username => "root").query("SELECT sleep(#{overhead}) as result")
16
15
  puts "<< thread #{Thread.current.object_id} result, #{overhead} sec overhead"
17
16
  end
18
- end
19
- threads.each{|t| t.join }
20
- end
17
+ end.each(&:join)
18
+ end