mysql2 0.3.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -151
  3. data/LICENSE +21 -0
  4. data/README.md +634 -0
  5. data/examples/eventmachine.rb +1 -3
  6. data/examples/threaded.rb +5 -9
  7. data/ext/mysql2/client.c +1154 -342
  8. data/ext/mysql2/client.h +20 -33
  9. data/ext/mysql2/extconf.rb +229 -37
  10. data/ext/mysql2/infile.c +122 -0
  11. data/ext/mysql2/infile.h +1 -0
  12. data/ext/mysql2/mysql2_ext.c +3 -1
  13. data/ext/mysql2/mysql2_ext.h +18 -16
  14. data/ext/mysql2/mysql_enc_name_to_ruby.h +168 -0
  15. data/ext/mysql2/mysql_enc_to_ruby.h +259 -0
  16. data/ext/mysql2/result.c +708 -191
  17. data/ext/mysql2/result.h +15 -6
  18. data/ext/mysql2/statement.c +602 -0
  19. data/ext/mysql2/statement.h +17 -0
  20. data/ext/mysql2/wait_for_single_fd.h +37 -0
  21. data/lib/mysql2.rb +69 -7
  22. data/lib/mysql2/client.rb +126 -211
  23. data/lib/mysql2/console.rb +5 -0
  24. data/lib/mysql2/em.rb +24 -8
  25. data/lib/mysql2/error.rb +93 -8
  26. data/lib/mysql2/field.rb +3 -0
  27. data/lib/mysql2/result.rb +2 -0
  28. data/lib/mysql2/statement.rb +11 -0
  29. data/lib/mysql2/version.rb +2 -2
  30. data/spec/configuration.yml.example +11 -0
  31. data/spec/em/em_spec.rb +101 -15
  32. data/spec/my.cnf.example +9 -0
  33. data/spec/mysql2/client_spec.rb +874 -232
  34. data/spec/mysql2/error_spec.rb +55 -46
  35. data/spec/mysql2/result_spec.rb +306 -154
  36. data/spec/mysql2/statement_spec.rb +712 -0
  37. data/spec/spec_helper.rb +103 -57
  38. data/spec/ssl/ca-cert.pem +17 -0
  39. data/spec/ssl/ca-key.pem +27 -0
  40. data/spec/ssl/ca.cnf +22 -0
  41. data/spec/ssl/cert.cnf +22 -0
  42. data/spec/ssl/client-cert.pem +17 -0
  43. data/spec/ssl/client-key.pem +27 -0
  44. data/spec/ssl/client-req.pem +15 -0
  45. data/spec/ssl/gen_certs.sh +48 -0
  46. data/spec/ssl/pkcs8-client-key.pem +28 -0
  47. data/spec/ssl/pkcs8-server-key.pem +28 -0
  48. data/spec/ssl/server-cert.pem +17 -0
  49. data/spec/ssl/server-key.pem +27 -0
  50. data/spec/ssl/server-req.pem +15 -0
  51. data/spec/test_data +1 -0
  52. data/support/5072E1F5.asc +432 -0
  53. data/support/libmysql.def +219 -0
  54. data/support/mysql_enc_to_ruby.rb +81 -0
  55. data/support/ruby_enc_to_mysql.rb +61 -0
  56. metadata +82 -188
  57. data/.gitignore +0 -12
  58. data/.rspec +0 -2
  59. data/.rvmrc +0 -1
  60. data/Gemfile +0 -3
  61. data/MIT-LICENSE +0 -20
  62. data/README.rdoc +0 -257
  63. data/Rakefile +0 -5
  64. data/benchmark/active_record.rb +0 -51
  65. data/benchmark/active_record_threaded.rb +0 -42
  66. data/benchmark/allocations.rb +0 -33
  67. data/benchmark/escape.rb +0 -36
  68. data/benchmark/query_with_mysql_casting.rb +0 -80
  69. data/benchmark/query_without_mysql_casting.rb +0 -47
  70. data/benchmark/sequel.rb +0 -37
  71. data/benchmark/setup_db.rb +0 -119
  72. data/benchmark/threaded.rb +0 -44
  73. data/lib/active_record/connection_adapters/em_mysql2_adapter.rb +0 -64
  74. data/lib/active_record/fiber_patches.rb +0 -104
  75. data/lib/mysql2/em_fiber.rb +0 -31
  76. data/mysql2.gemspec +0 -32
  77. data/spec/em/em_fiber_spec.rb +0 -22
  78. data/tasks/benchmarks.rake +0 -20
  79. data/tasks/compile.rake +0 -71
  80. data/tasks/rspec.rake +0 -16
  81. data/tasks/vendor_mysql.rake +0 -40
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 62ba5d2530e40ed2dcefd98c2219c95b166a7385
4
+ data.tar.gz: c17840a416a95f241cd9259c57aaacac100d17f8
5
+ SHA512:
6
+ metadata.gz: 50d8ecc5c61d004953d4da51b69ca0d8166c1c665757f677eedea84c62173490a6b0b1b67cec9e661397306fb0607930f6cf5b062fd8f77c2d9c2ea02b8d2d69
7
+ data.tar.gz: d62e82ffffe4e1a84d37f1a3745c58c0d5b0f88d0cc1403b93a452a0af454e6aa1a49653cb70b494b092ffa7f924ed66293c58ec0ddbe2e8497eedcf631ffd7c
data/CHANGELOG.md CHANGED
@@ -1,151 +1 @@
1
- # Changelog
2
-
3
- ## 0.3.1 (April 26th, 2011)
4
- * Fix typo in initialization for older ActiveRecord versions
5
-
6
- ## 0.3.0 (April 26th, 2011)
7
- * switch to MySQL Connector/C for win32 builds
8
- * win32 bugfixes
9
- * BREAKING CHANGE: the ActiveRecord adapter has been pulled into Rails 3.1 and is no longer part of the gem
10
- * added Mysql2::Client.escape (class-level) for raw one-off non-encoding-aware escaping
11
-
12
- ## 0.2.7 (March 28th, 2011)
13
- * various fixes for em_mysql2 and fiber usage
14
- * use our own Mysql2IndexDefinition class for better compatibility across ActiveRecord versions
15
- * ensure the query is a string earlier in the Mysql2::Client#query codepath for 1.9
16
- * only set binary ruby encoding on fields that have a binary flag *and* encoding set
17
- * a few various optimizations
18
- * add support for :read_timeout to be set on a connection
19
- * Fix to install with MariDB on Windows
20
- * add fibered em connection without activerecord
21
- * fix some 1.9.3 compilation warnings
22
- * add LD_RUN_PATH when using hard coded mysql paths - this should help users with MySQL installed in non-standard locations
23
- * for windows support, duplicate the socket from libmysql and create a temporary CRT fd
24
- * fix for handling years before 1970 on Windows
25
- * fixes to the Fiber adapter
26
- * set wait_timeout maximum on Windows to 2147483
27
- * update supported range for Time objects
28
- * upon being required, make sure the libmysql we're using is the one we were built against
29
- * add Mysql2::Client#thread_id
30
- * add Mysql2::Client#ping
31
- * switch connection check in AR adapter to use Mysql2::Client#ping for efficiency
32
- * prefer linking against thread-safe version of libmysqlclient
33
- * define RSTRING_NOT_MODIFIED for an awesome rbx speed boost
34
- * expose Mysql2::Client#encoding in 1.9, make sure we set the error message and sqlstate encodings accordingly
35
- * do not segfault when raising for invalid charset (found in 1.9.3dev)
36
-
37
- ## 0.2.6 (October 19th, 2010)
38
- * version bump since the 0.2.5 win32 binary gems were broken
39
-
40
- ## 0.2.5 (October 19th, 2010)
41
- * fixes for easier Win32 binary gem deployment for targeting 1.8 and 1.9 in the same gem
42
- * refactor of connection checks and management to avoid race conditions with the GC/threading to prevent the unexpected loss of connections
43
- * update the default flags during connection
44
- * add support for setting wait_timeout on AR adapter
45
- * upgrade to rspec2
46
- * bugfix for an edge case where the GC would clean up a Mysql2::Client object before the underlying MYSQL pointer had been initialized
47
- * fix to CFLAGS to allow compilation on SPARC with sunstudio compiler - Anko painting <anko.com+github@gmail.com>
48
-
49
- ## 0.2.4 (September 17th, 2010)
50
- * a few patches for win32 support from Luis Lavena - thanks man!
51
- * bugfix from Eric Wong to avoid a potential stack overflow during Mysql2::Client#escape
52
- * added the ability to turn internal row caching on/off via the :cache_rows => true/false option
53
- * a couple of small patches for rbx compatibility
54
- * set IndexDefinition#length in AR adapter - Kouhei Yanagita <yanagi@shakenbu.org>
55
- * fix a long-standing data corruption bug - thank you thank you thank you to @joedamato (http://github.com/ice799)
56
- * bugfix from calling mysql_close on a closed/freed connection surfaced by the above fix
57
-
58
- ## 0.2.3 (August 20th, 2010)
59
- * connection flags can now be passed to the constructor via the :flags key
60
- * switch AR adapter connection over to use FOUND_ROWS option
61
- * patch to ensure we use DateTime objects in place of Time for timestamps that are out of the supported range on 32bit platforms < 1.9.2
62
-
63
- ## 0.2.2 (August 19th, 2010)
64
- * Change how AR adapter would send initial commands upon connecting
65
- ** we can make multiple session variable assignments in a single query
66
- * fix signal handling when waiting on queries
67
- * retry connect if interrupted by signals
68
-
69
- ## 0.2.1 (August 16th, 2010)
70
- * bring mysql2 ActiveRecord adapter back into gem
71
-
72
- ## 0.2.0 (August 16th, 2010)
73
- * switch back to letting libmysql manage all allocation/thread-state/freeing for the connection
74
- * cache various numeric type conversions in hot-spots of the code for a little speed boost
75
- * ActiveRecord adapter moved into Rails 3 core
76
- ** Don't worry 2.3.x users! We'll either release the adapter as a separate gem, or try to get it into 2.3.9
77
- * Fix for the "closed MySQL connection" error (GH #31)
78
- * Fix for the "can't modify frozen object" error in 1.9.2 (GH #37)
79
- * Introduce cascading query and result options (more info in README)
80
- * Sequel adapter pulled into core (will be in the next release - 3.15.0 at the time of writing)
81
- * add a safety check when attempting to send a query before a result has been fetched
82
-
83
- ## 0.1.9 (July 17th, 2010)
84
- * Support async ActiveRecord access with fibers and EventMachine (mperham)
85
- * string encoding support for 1.9, respecting Encoding.default_internal
86
- * added support for rake-compiler (tenderlove)
87
- * bugfixes for ActiveRecord driver
88
- ** one minor bugfix for TimeZone support
89
- ** fix the select_rows method to return what it should according to the docs (r-stu31)
90
- * Mysql2::Client#fields method added - returns the array of field names from a resultset, as strings
91
- * Sequel adapter
92
- ** bugfix regarding sybolized field names (Eric Wong)
93
- ** fix query logging in Sequel adapter
94
- * Lots of nice code cleanup (tenderlove)
95
- ** Mysql2::Error definition moved to pure-Ruby
96
- ** Mysql2::client#initialize definition moved to pure-Ruby
97
- ** Mysql2::Result partially moved to pure-Ruby
98
-
99
- ## 0.1.8 (June 2nd, 2010)
100
- * fixes for AR adapter for timezone juggling
101
- * fixes to be able to run benchmarks and specs under 1.9.2
102
-
103
- ## 0.1.7 (May 22nd, 2010)
104
- * fix a bug when using the disconnect! method on a closed connection in the AR driver
105
-
106
- ## 0.1.6 (May 14th, 2010)
107
- * more fixes to the AR adapter related to casting
108
- * add missing index creation override method to AR adapter
109
- * added sql_state and error_number methods to the Mysql2::Error exception class
110
-
111
- ## 0.1.5 (May 12th, 2010)
112
- * quite a few patches from Eric Wong related to thread-safety, non-blocking I/O and general cleanup
113
- ** wrap mysql_real_connect with rb_thread_blocking_region
114
- ** release GVL for possibly blocking mysql_* library calls
115
- ** [cleanup] quiet down warnings
116
- ** [cleanup] make all C symbols static
117
- ** add Mysql2::Client#close method
118
- ** correctly free the wrapped result in case of EOF
119
- ** Fix memory leak from the result wrapper struct itself
120
- ** make Mysql2::Client destructor safely non-blocking
121
- * bug fixes for ActiveRecord adapter
122
- ** added casting for default values since they all come back from Mysql as strings (!?!)
123
- ** missing constant was added
124
- ** fixed a typo in the show_variable method
125
- * switched over sscanf for date/time parsing in C
126
- * made some specs a little finer-grained
127
- * initial Sequel adapter added
128
- * updated query benchmarks to reflect the difference between casting in C and in Ruby
129
-
130
- ## 0.1.4 (April 23rd, 2010)
131
- * optimization: implemented a local cache for rows that are lazily created in ruby during iteration. The MySQL C result is freed as soon as all the results have been cached
132
- * optimization: implemented a local cache for field names so every row reuses the same objects as field names/keys
133
- * refactor the Mysql2 connection adapter for ActiveRecord to not extend the Mysql adapter - now being a free-standing connection adapter
134
-
135
- ## 0.1.3 (April 15th, 2010)
136
- * added an EventMachine Deferrable API
137
- * added an ActiveRecord connection adapter
138
- ** should be compatible with 2.3.5 and 3.0 (including Arel)
139
-
140
- ## 0.1.2 (April 9th, 2010)
141
- * fix a bug (copy/paste fail) around checking for empty TIME values and returning nil (thanks @marius)
142
-
143
- ## 0.1.1 (April 6th, 2010)
144
- * added affected_rows method (mysql_affected_rows)
145
- * added last_id method (last_insert_id)
146
- * enable reconnect option by default
147
- * added initial async query support
148
- * updated extconf (thanks to the mysqlplus project) for easier gem building
149
-
150
- ## 0.1.0 (April 6th, 2010)
151
- * initial release
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 ADDED
@@ -0,0 +1,634 @@
1
+ # Mysql2 - A modern, simple and very fast MySQL library for Ruby - binding to libmysql
2
+
3
+ Travis CI [![Travis CI Status](https://travis-ci.org/brianmario/mysql2.png)](https://travis-ci.org/brianmario/mysql2)
4
+ Appveyor CI [![Appveyor CI Status](https://ci.appveyor.com/api/projects/status/github/sodabrew/mysql2)](https://ci.appveyor.com/project/sodabrew/mysql2)
5
+
6
+ The Mysql2 gem is meant to serve the extremely common use-case of connecting, querying and iterating on results.
7
+ Some database libraries out there serve as direct 1:1 mappings of the already complex C APIs available.
8
+ This one is not.
9
+
10
+ It also forces the use of UTF-8 [or binary] for the connection and uses encoding-aware MySQL API calls where it can.
11
+
12
+ The API consists of three classes:
13
+
14
+ `Mysql2::Client` - your connection to the database.
15
+
16
+ `Mysql2::Result` - returned from issuing a #query on the connection. It includes Enumerable.
17
+
18
+ `Mysql2::Statement` - returned from issuing a #prepare on the connection. Execute the statement to get a Result.
19
+
20
+ ## Installing
21
+ ### General Instructions
22
+ ``` sh
23
+ gem install mysql2
24
+ ```
25
+
26
+ This gem links against MySQL's `libmysqlclient` library or `Connector/C`
27
+ library, and compatible alternatives such as MariaDB.
28
+ You may need to install a package such as `libmysqlclient-dev`, `mysql-devel`,
29
+ or other appropriate package for your system. See below for system-specific
30
+ instructions.
31
+
32
+ By default, the mysql2 gem will try to find a copy of MySQL in this order:
33
+
34
+ * Option `--with-mysql-dir`, if provided (see below).
35
+ * Option `--with-mysql-config`, if provided (see below).
36
+ * Several typical paths for `mysql_config` (default for the majority of users).
37
+ * The directory `/usr/local`.
38
+
39
+ ### Configuration options
40
+
41
+ Use these options by `gem install mysql2 -- [--optionA] [--optionB=argument]`.
42
+
43
+ * `--with-mysql-dir[=/path/to/mysqldir]` -
44
+ Specify the directory where MySQL is installed. The mysql2 gem will not use
45
+ `mysql_config`, but will instead look at `mysqldir/lib` and `mysqldir/include`
46
+ for the library and header files.
47
+ This option is mutually exclusive with `--with-mysql-config`.
48
+
49
+ * `--with-mysql-config[=/path/to/mysql_config]` -
50
+ Specify a path to the `mysql_config` binary provided by your copy of MySQL. The
51
+ mysql2 gem will ask this `mysql_config` binary about the compiler and linker
52
+ arguments needed.
53
+ This option is mutually exclusive with `--with-mysql-dir`.
54
+
55
+ * `--with-mysql-rpath=/path/to/mysql/lib` / `--without-mysql-rpath` -
56
+ Override the runtime path used to find the MySQL libraries.
57
+ This may be needed if you deploy to a system where these libraries
58
+ are located somewhere different than on your build system.
59
+ This overrides any rpath calculated by default or by the options above.
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
+
75
+ ### Linux and other Unixes
76
+
77
+ You may need to install a package such as `libmysqlclient-dev`, `mysql-devel`,
78
+ or `default-libmysqlclient-dev`; refer to your distribution's package guide to
79
+ find the particular package. The most common issue we see is a user who has
80
+ the library file `libmysqlclient.so` but is missing the header file `mysql.h`
81
+ -- double check that you have the _-dev_ packages installed.
82
+
83
+ ### Mac OS X
84
+
85
+ You may use MacPorts, Homebrew, or a native MySQL installer package. The most
86
+ common paths will be automatically searched. If you want to select a specific
87
+ MySQL directory, use the `--with-mysql-dir` or `--with-mysql-config` options above.
88
+
89
+ If you have not done so already, you will need to install the XCode select tools by running
90
+ `xcode-select --install`.
91
+
92
+ ### Windows
93
+ Make sure that you have Ruby and the DevKit compilers installed. We recommend
94
+ the [Ruby Installer](http://rubyinstaller.org) distribution.
95
+
96
+ By default, the mysql2 gem will download and use MySQL Connector/C from
97
+ mysql.com. If you prefer to use a local installation of Connector/C, add the
98
+ flag `--with-mysql-dir=c:/mysql-connector-c-x-y-z` (_this path may use forward slashes_).
99
+
100
+ By default, the `libmysql.dll` library will be copied into the mysql2 gem
101
+ directory. To prevent this, add the flag `--no-vendor-libmysql`. The mysql2 gem
102
+ will search for `libmysql.dll` in the following paths, in order:
103
+
104
+ * Environment variable `RUBY_MYSQL2_LIBMYSQL_DLL=C:\path\to\libmysql.dll`
105
+ (_note the Windows-style backslashes_).
106
+ * In the mysql2 gem's own directory `vendor/libmysql.dll`
107
+ * In the system's default library search paths.
108
+
109
+ ## Usage
110
+
111
+ Connect to a database:
112
+
113
+ ``` ruby
114
+ # this takes a hash of options, almost all of which map directly
115
+ # to the familiar database.yml in rails
116
+ # See http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html
117
+ client = Mysql2::Client.new(:host => "localhost", :username => "root")
118
+ ```
119
+
120
+ Then query it:
121
+
122
+ ``` ruby
123
+ results = client.query("SELECT * FROM users WHERE group='githubbers'")
124
+ ```
125
+
126
+ Need to escape something first?
127
+
128
+ ``` ruby
129
+ escaped = client.escape("gi'thu\"bbe\0r's")
130
+ results = client.query("SELECT * FROM users WHERE group='#{escaped}'")
131
+ ```
132
+
133
+ You can get a count of your results with `results.count`.
134
+
135
+ Finally, iterate over the results:
136
+
137
+ ``` ruby
138
+ results.each do |row|
139
+ # conveniently, row is a hash
140
+ # the keys are the fields, as you'd expect
141
+ # the values are pre-built ruby primitives mapped from their corresponding field types in MySQL
142
+ puts row["id"] # row["id"].is_a? Integer
143
+ if row["dne"] # non-existant hash entry is nil
144
+ puts row["dne"]
145
+ end
146
+ end
147
+ ```
148
+
149
+ Or, you might just keep it simple:
150
+
151
+ ``` ruby
152
+ client.query("SELECT * FROM users WHERE group='githubbers'").each do |row|
153
+ # do something with row, it's ready to rock
154
+ end
155
+ ```
156
+
157
+ How about with symbolized keys?
158
+
159
+ ``` ruby
160
+ client.query("SELECT * FROM users WHERE group='githubbers'", :symbolize_keys => true) do |row|
161
+ # do something with row, it's ready to rock
162
+ end
163
+ ```
164
+
165
+ You can get the headers and the columns in the order that they were returned
166
+ by the query like this:
167
+
168
+ ``` ruby
169
+ headers = results.fields # <= that's an array of field names, in order
170
+ results.each(:as => :array) do |row|
171
+ # Each row is an array, ordered the same as the query results
172
+ # An otter's den is called a "holt" or "couch"
173
+ end
174
+ ```
175
+
176
+ Prepared statements are supported, as well. In a prepared statement, use a `?`
177
+ in place of each value and then execute the statement to retrieve a result set.
178
+ Pass your arguments to the execute method in the same number and order as the
179
+ question marks in the statement. Query options can be passed as keyword arguments
180
+ to the execute method.
181
+
182
+ Be sure to read about the known limitations of prepared statements at
183
+ https://dev.mysql.com/doc/refman/5.6/en/c-api-prepared-statement-problems.html
184
+
185
+ ``` ruby
186
+ statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
187
+ result1 = statement.execute(1)
188
+ result2 = statement.execute(2)
189
+
190
+ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
191
+ result = statement.execute(1, "CA")
192
+
193
+ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND location LIKE ?")
194
+ result = statement.execute(1, "CA", :as => :array)
195
+ ```
196
+
197
+ ## Connection options
198
+
199
+ You may set the following connection options in Mysql2::Client.new(...):
200
+
201
+ ``` ruby
202
+ Mysql2::Client.new(
203
+ :host,
204
+ :username,
205
+ :password,
206
+ :port,
207
+ :database,
208
+ :socket = '/path/to/mysql.sock',
209
+ :flags = REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | MULTI_STATEMENTS,
210
+ :encoding = 'utf8',
211
+ :read_timeout = seconds,
212
+ :write_timeout = seconds,
213
+ :connect_timeout = seconds,
214
+ :connect_attrs = {:program_name => $PROGRAM_NAME, ...},
215
+ :reconnect = true/false,
216
+ :local_infile = true/false,
217
+ :secure_auth = true/false,
218
+ :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
219
+ :default_file = '/path/to/my.cfg',
220
+ :default_group = 'my.cfg section',
221
+ :init_command => sql
222
+ )
223
+ ```
224
+
225
+ ### Connecting to MySQL on localhost and elsewhere
226
+
227
+ The underlying MySQL client library uses the `:host` parameter to determine the
228
+ type of connection to make, with special interpretation you should be aware of:
229
+
230
+ * An empty value or `"localhost"` will attempt a local connection:
231
+ * On Unix, connect to the default local socket path. (To set a custom socket
232
+ path, use the `:socket` parameter).
233
+ * On Windows, connect using a shared-memory connection, if enabled, or TCP.
234
+ * A value of `"."` on Windows specifies a named-pipe connection.
235
+ * An IPv4 or IPv6 address will result in a TCP connection.
236
+ * Any other value will be looked up as a hostname for a TCP connection.
237
+
238
+ ### SSL options
239
+
240
+ Setting any of the following options will enable an SSL connection, but only if
241
+ your MySQL client library and server have been compiled with SSL support.
242
+ MySQL client library defaults will be used for any parameters that are left out
243
+ or set to nil. Relative paths are allowed, and may be required by managed
244
+ hosting providers such as Heroku. Set `:sslverify => true` to require that the
245
+ server presents a valid certificate.
246
+
247
+ ``` ruby
248
+ Mysql2::Client.new(
249
+ # ...options as above...,
250
+ :sslkey => '/path/to/client-key.pem',
251
+ :sslcert => '/path/to/client-cert.pem',
252
+ :sslca => '/path/to/ca-cert.pem',
253
+ :sslcapath => '/path/to/cacerts',
254
+ :sslcipher => 'DHE-RSA-AES256-SHA',
255
+ :sslverify => true,
256
+ )
257
+ ```
258
+
259
+ ### Secure auth
260
+
261
+ Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
262
+ When secure_auth is enabled, the server will refuse a connection if the account password is stored in old pre-MySQL 4.1 format.
263
+ The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password.
264
+ To bypass this restriction in the client, pass the option `:secure_auth => false` to Mysql2::Client.new().
265
+
266
+ ### Flags option parsing
267
+
268
+ The `:flags` parameter accepts an integer, a string, or an array. The integer
269
+ form allows the client to assemble flags from constants defined under
270
+ `Mysql2::Client` such as `Mysql2::Client::FOUND_ROWS`. Use a bitwise `|` (OR)
271
+ to specify several flags.
272
+
273
+ The string form will be split on whitespace and parsed as with the array form:
274
+ Plain flags are added to the default flags, while flags prefixed with `-`
275
+ (minus) are removed from the default flags.
276
+
277
+ This allows easier use with ActiveRecord's database.yml, avoiding the need for magic flag numbers.
278
+ For example, to disable protocol compression, and enable multiple statements and result sets:
279
+
280
+ ``` yaml
281
+ development:
282
+ adapter: mysql2
283
+ encoding: utf8
284
+ database: my_db_name
285
+ username: root
286
+ password: my_password
287
+ host: 127.0.0.1
288
+ port: 3306
289
+ flags:
290
+ - -COMPRESS
291
+ - FOUND_ROWS
292
+ - MULTI_STATEMENTS
293
+ secure_auth: false
294
+ ```
295
+
296
+ ### Reading a MySQL config file
297
+
298
+ You may read configuration options from a MySQL configuration file by passing
299
+ the `:default_file` and `:default_group` parameters. For example:
300
+
301
+ ``` ruby
302
+ Mysql2::Client.new(:default_file => '/user/.my.cnf', :default_group => 'client')
303
+ ```
304
+
305
+ ### Initial command on connect and reconnect
306
+
307
+ If you specify the `:init_command` option, the SQL string you provide will be executed after the connection is established.
308
+ If `:reconnect` is set to `true`, init_command will also be executed after a successful reconnect.
309
+ It is useful if you want to provide session options which survive reconnection.
310
+
311
+ ``` ruby
312
+ Mysql2::Client.new(:init_command => "SET @@SESSION.sql_mode = 'STRICT_ALL_TABLES'")
313
+ ```
314
+
315
+ ### Multiple result sets
316
+
317
+ You can also retrieve multiple result sets. For this to work you need to
318
+ connect with flags `Mysql2::Client::MULTI_STATEMENTS`. Multiple result sets can
319
+ be used with stored procedures that return more than one result set, and for
320
+ bundling several SQL statements into a single call to `client.query`.
321
+
322
+ ``` ruby
323
+ client = Mysql2::Client.new(:host => "localhost", :username => "root", :flags => Mysql2::Client::MULTI_STATEMENTS)
324
+ result = client.query('CALL sp_customer_list( 25, 10 )')
325
+ # result now contains the first result set
326
+ while client.next_result
327
+ result = client.store_result
328
+ # result now contains the next result set
329
+ end
330
+ ```
331
+
332
+ Repeated calls to `client.next_result` will return true, false, or raise an
333
+ exception if the respective query erred. When `client.next_result` returns true,
334
+ call `client.store_result` to retrieve a result object. Exceptions are not
335
+ raised until `client.next_result` is called to find the status of the respective
336
+ query. Subsequent queries are not executed if an earlier query raised an
337
+ exception. Subsequent calls to `client.next_result` will return false.
338
+
339
+ ``` ruby
340
+ result = client.query('SELECT 1; SELECT 2; SELECT A; SELECT 3')
341
+ p result.first
342
+
343
+ while client.next_result
344
+ result = client.store_result
345
+ p result.first
346
+ end
347
+ ```
348
+
349
+ Yields:
350
+ ```
351
+ {"1"=>1}
352
+ {"2"=>2}
353
+ next_result: Unknown column 'A' in 'field list' (Mysql2::Error)
354
+ ```
355
+
356
+ ## Cascading config
357
+
358
+ The default config hash is at:
359
+
360
+ ``` ruby
361
+ Mysql2::Client.default_query_options
362
+ ```
363
+
364
+ which defaults to:
365
+
366
+ ``` ruby
367
+ {:async => false, :as => :hash, :symbolize_keys => false}
368
+ ```
369
+
370
+ that can be used as so:
371
+
372
+ ``` ruby
373
+ # these are the defaults all Mysql2::Client instances inherit
374
+ Mysql2::Client.default_query_options.merge!(:as => :array)
375
+ ```
376
+
377
+ or
378
+
379
+ ``` ruby
380
+ # this will change the defaults for all future results returned by the #query method _for this connection only_
381
+ c = Mysql2::Client.new
382
+ c.query_options.merge!(:symbolize_keys => true)
383
+ ```
384
+
385
+ or
386
+
387
+ ``` ruby
388
+ # this will set the options for the Mysql2::Result instance returned from the #query method
389
+ c = Mysql2::Client.new
390
+ c.query(sql, :symbolize_keys => true)
391
+ ```
392
+
393
+ or
394
+
395
+ ``` ruby
396
+ # this will set the options for the Mysql2::Result instance returned from the #execute method
397
+ c = Mysql2::Client.new
398
+ s = c.prepare(sql)
399
+ s.execute(arg1, args2, :symbolize_keys => true)
400
+ ```
401
+
402
+ ## Result types
403
+
404
+ ### Array of Arrays
405
+
406
+ Pass the `:as => :array` option to any of the above methods of configuration
407
+
408
+ ### Array of Hashes
409
+
410
+ The default result type is set to :hash, but you can override a previous setting to something else with :as => :hash
411
+
412
+ ### Timezones
413
+
414
+ Mysql2 now supports two timezone options:
415
+
416
+ ``` ruby
417
+ :database_timezone # this is the timezone Mysql2 will assume fields are already stored as, and will use this when creating the initial Time objects in ruby
418
+ :application_timezone # this is the timezone Mysql2 will convert to before finally handing back to the caller
419
+ ```
420
+
421
+ In other words, if `:database_timezone` is set to `:utc` - Mysql2 will create the Time objects using `Time.utc(...)` from the raw value libmysql hands over initially.
422
+ Then, if `:application_timezone` is set to say - `:local` - Mysql2 will then convert the just-created UTC Time object to local time.
423
+
424
+ Both options only allow two values - `:local` or `:utc` - with the exception that `:application_timezone` can be [and defaults to] nil
425
+
426
+ ### Casting "boolean" columns
427
+
428
+ You can now tell Mysql2 to cast `tinyint(1)` fields to boolean values in Ruby with the `:cast_booleans` option.
429
+
430
+ ``` ruby
431
+ client = Mysql2::Client.new
432
+ result = client.query("SELECT * FROM table_with_boolean_field", :cast_booleans => true)
433
+ ```
434
+
435
+ Keep in mind that this works only with fields and not with computed values, e.g. this result will contain `1`, not `true`:
436
+
437
+ ``` ruby
438
+ client = Mysql2::Client.new
439
+ result = client.query("SELECT true", :cast_booleans => true)
440
+ ```
441
+
442
+ 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).
443
+
444
+ ### Skipping casting
445
+
446
+ 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.)
447
+
448
+ ``` ruby
449
+ client = Mysql2::Client.new
450
+ result = client.query("SELECT * FROM table", :cast => false)
451
+ ```
452
+
453
+ Here are the results from the `query_without_mysql_casting.rb` script in the benchmarks folder:
454
+
455
+ ``` sh
456
+ user system total real
457
+ Mysql2 (cast: true) 0.340000 0.000000 0.340000 ( 0.405018)
458
+ Mysql2 (cast: false) 0.160000 0.010000 0.170000 ( 0.209937)
459
+ Mysql 0.080000 0.000000 0.080000 ( 0.129355)
460
+ do_mysql 0.520000 0.010000 0.530000 ( 0.574619)
461
+ ```
462
+
463
+ Although Mysql2 performs reasonably well at retrieving uncasted data, it (currently) is not as fast as the Mysql gem. In spite of this small disadvantage, Mysql2 still sports a friendlier interface and doesn't block the entire ruby process when querying.
464
+
465
+ ### Async
466
+
467
+ NOTE: Not supported on Windows.
468
+
469
+ `Mysql2::Client` takes advantage of the MySQL C API's (undocumented) non-blocking function mysql_send_query for *all* queries.
470
+ But, in order to take full advantage of it in your Ruby code, you can do:
471
+
472
+ ``` ruby
473
+ client.query("SELECT sleep(5)", :async => true)
474
+ ```
475
+
476
+ Which will return nil immediately. At this point you'll probably want to use some socket monitoring mechanism
477
+ like EventMachine or even IO.select. Once the socket becomes readable, you can do:
478
+
479
+ ``` ruby
480
+ # result will be a Mysql2::Result instance
481
+ result = client.async_result
482
+ ```
483
+
484
+ NOTE: Because of the way MySQL's query API works, this method will block until the result is ready.
485
+ So if you really need things to stay async, it's best to just monitor the socket with something like EventMachine.
486
+ If you need multiple query concurrency take a look at using a connection pool.
487
+
488
+ ### Row Caching
489
+
490
+ By default, Mysql2 will cache rows that have been created in Ruby (since this happens lazily).
491
+ This is especially helpful since it saves the cost of creating the row in Ruby if you were to iterate over the collection again.
492
+
493
+ If you only plan on using each row once, then it's much more efficient to disable this behavior by setting the `:cache_rows` option to false.
494
+ This would be helpful if you wanted to iterate over the results in a streaming manner. Meaning the GC would cleanup rows you don't need anymore as you're iterating over the result set.
495
+
496
+ ### Streaming
497
+
498
+ `Mysql2::Client` can optionally only fetch rows from the server on demand by setting `:stream => true`. This is handy when handling very large result sets which might not fit in memory on the client.
499
+
500
+ ``` ruby
501
+ result = client.query("SELECT * FROM really_big_Table", :stream => true)
502
+ ```
503
+
504
+ There are a few things that need to be kept in mind while using streaming:
505
+
506
+ * `:cache_rows` is ignored currently. (if you want to use `:cache_rows` you probably don't want to be using `:stream`)
507
+ * You must fetch all rows in the result set of your query before you can make new queries. (i.e. with `Mysql2::Result#each`)
508
+
509
+ Read more about the consequences of using `mysql_use_result` (what streaming is implemented with) here: http://dev.mysql.com/doc/refman/5.0/en/mysql-use-result.html.
510
+
511
+ ### Lazy Everything
512
+
513
+ Well... almost ;)
514
+
515
+ Field name strings/symbols are shared across all the rows so only one object is ever created to represent the field name for an entire dataset.
516
+
517
+ Rows themselves are lazily created in ruby-land when an attempt to yield it is made via #each.
518
+ For example, if you were to yield 4 rows from a 100 row dataset, only 4 hashes will be created. The rest will sit and wait in C-land until you want them (or when the GC goes to cleanup your `Mysql2::Result` instance).
519
+ Now say you were to iterate over that same collection again, this time yielding 15 rows - the 4 previous rows that had already been turned into ruby hashes would be pulled from an internal cache, then 11 more would be created and stored in that cache.
520
+ Once the entire dataset has been converted into ruby objects, Mysql2::Result will free the Mysql C result object as it's no longer needed.
521
+
522
+ This caching behavior can be disabled by setting the `:cache_rows` option to false.
523
+
524
+ As for field values themselves, I'm workin on it - but expect that soon.
525
+
526
+ ## Compatibility
527
+
528
+ This gem is tested with the following Ruby versions on Linux and Mac OS X:
529
+
530
+ * Ruby MRI 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x
531
+ * Rubinius 2.x and 3.x do work but may fail under some workloads
532
+
533
+ This gem is tested with the following MySQL and MariaDB versions:
534
+
535
+ * MySQL 5.5, 5.6, 5.7, 8.0
536
+ * MySQL Connector/C 6.0 and 6.1 (primarily on Windows)
537
+ * MariaDB 5.5, 10.0, 10.1, 10.2, 10.3
538
+
539
+ ### Ruby on Rails / Active Record
540
+
541
+ * mysql2 0.5.x works with Rails / Active Record 5.0.7, 5.1.6, and higher.
542
+ * mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
543
+ * mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
544
+ * mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.
545
+
546
+ ### Asynchronous Active Record
547
+
548
+ Please see the [em-synchrony](https://github.com/igrigorik/em-synchrony) project for details about using EventMachine with mysql2 and Rails.
549
+
550
+ ### Sequel
551
+
552
+ Sequel includes a mysql2 adapter in all releases since 3.15 (2010-09-01).
553
+ Use the prefix "mysql2://" in your connection specification.
554
+
555
+ ### EventMachine
556
+
557
+ The mysql2 EventMachine deferrable api allows you to make async queries using EventMachine,
558
+ while specifying callbacks for success for failure. Here's a simple example:
559
+
560
+ ``` ruby
561
+ require 'mysql2/em'
562
+
563
+ EM.run do
564
+ client1 = Mysql2::EM::Client.new
565
+ defer1 = client1.query "SELECT sleep(3) as first_query"
566
+ defer1.callback do |result|
567
+ puts "Result: #{result.to_a.inspect}"
568
+ end
569
+
570
+ client2 = Mysql2::EM::Client.new
571
+ defer2 = client2.query "SELECT sleep(1) second_query"
572
+ defer2.callback do |result|
573
+ puts "Result: #{result.to_a.inspect}"
574
+ end
575
+ end
576
+ ```
577
+
578
+ ## Benchmarks and Comparison
579
+
580
+ The mysql2 gem converts MySQL field types to Ruby data types in C code, providing a serious speed benefit.
581
+
582
+ The do_mysql gem also converts MySQL fields types, but has a considerably more complex API and is still ~2x slower than mysql2.
583
+
584
+ The mysql gem returns only nil or string data types, leaving you to convert field values to Ruby types in Ruby-land, which is much slower than mysql2's C code.
585
+
586
+ For a comparative benchmark, the script below performs a basic "SELECT * FROM"
587
+ query on a table with 30k rows and fields of nearly every Ruby-representable
588
+ data type, then iterating over every row using an #each like method yielding a
589
+ block:
590
+
591
+ ``` sh
592
+ user system total real
593
+ Mysql2 0.750000 0.180000 0.930000 (1.821655)
594
+ do_mysql 1.650000 0.200000 1.850000 (2.811357)
595
+ Mysql 7.500000 0.210000 7.710000 (8.065871)
596
+ ```
597
+
598
+ These results are from the `query_with_mysql_casting.rb` script in the benchmarks folder.
599
+
600
+ ## Development
601
+
602
+ Use 'bundle install' to install the necessary development and testing gems:
603
+
604
+ ``` sh
605
+ bundle install
606
+ rake
607
+ ```
608
+
609
+ The tests require the "test" database to exist, and expect to connect
610
+ both as root and the running user, both with a blank password:
611
+
612
+ ``` sql
613
+ CREATE DATABASE test;
614
+ CREATE USER '<user>'@'localhost' IDENTIFIED BY '';
615
+ GRANT ALL PRIVILEGES ON test.* TO '<user>'@'localhost';
616
+ ```
617
+
618
+ You can change these defaults in the spec/configuration.yml which is generated
619
+ automatically when you run rake (or explicitly `rake spec/configuration.yml`).
620
+
621
+ For a normal installation on a Mac, you most likely do not need to do anything,
622
+ though.
623
+
624
+ ## Special Thanks
625
+
626
+ * Eric Wong - for the contribution (and the informative explanations) of some thread-safety, non-blocking I/O and cleanup patches. You rock dude
627
+ * Yury Korolev (http://github.com/yury) - for TONS of help testing the Active Record adapter
628
+ * Aaron Patterson (http://github.com/tenderlove) - tons of contributions, suggestions and general badassness
629
+ * Mike Perham (http://github.com/mperham) - Async Active Record adapter (uses Fibers and EventMachine)
630
+ * Aaron Stone (http://github.com/sodabrew) - additional client settings, local files, microsecond time, maintenance support
631
+ * Kouhei Ueno (https://github.com/nyaxt) - for the original work on Prepared Statements way back in 2012
632
+ * John Cant (http://github.com/johncant) - polishing and updating Prepared Statements support
633
+ * Justin Case (http://github.com/justincase) - polishing and updating Prepared Statements support and getting it merged
634
+ * Tamir Duberstein (http://github.com/tamird) - for help with timeouts and all around updates and cleanups