mysql2 0.5.2 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +145 -44
  3. data/ext/mysql2/client.c +236 -58
  4. data/ext/mysql2/client.h +9 -2
  5. data/ext/mysql2/extconf.rb +62 -7
  6. data/ext/mysql2/mysql2_ext.c +6 -1
  7. data/ext/mysql2/mysql2_ext.h +13 -0
  8. data/ext/mysql2/mysql_enc_name_to_ruby.h +60 -55
  9. data/ext/mysql2/mysql_enc_to_ruby.h +71 -5
  10. data/ext/mysql2/result.c +287 -22
  11. data/ext/mysql2/result.h +1 -0
  12. data/ext/mysql2/statement.c +63 -14
  13. data/lib/mysql2/client.rb +24 -3
  14. data/lib/mysql2/error.rb +4 -3
  15. data/lib/mysql2/statement.rb +1 -3
  16. data/lib/mysql2/version.rb +1 -1
  17. data/lib/mysql2.rb +8 -3
  18. data/support/3A79BD29.asc +49 -0
  19. data/support/5072E1F5.asc +5 -5
  20. data/support/C74CD1D8.asc +104 -0
  21. data/support/mysql_enc_to_ruby.rb +7 -1
  22. data/support/ruby_enc_to_mysql.rb +3 -0
  23. metadata +15 -59
  24. data/examples/eventmachine.rb +0 -19
  25. data/examples/threaded.rb +0 -16
  26. data/spec/configuration.yml.example +0 -11
  27. data/spec/em/em_spec.rb +0 -135
  28. data/spec/my.cnf.example +0 -9
  29. data/spec/mysql2/client_spec.rb +0 -1072
  30. data/spec/mysql2/error_spec.rb +0 -78
  31. data/spec/mysql2/result_spec.rb +0 -485
  32. data/spec/mysql2/statement_spec.rb +0 -712
  33. data/spec/rcov.opts +0 -3
  34. data/spec/spec_helper.rb +0 -112
  35. data/spec/ssl/ca-cert.pem +0 -17
  36. data/spec/ssl/ca-key.pem +0 -27
  37. data/spec/ssl/ca.cnf +0 -22
  38. data/spec/ssl/cert.cnf +0 -22
  39. data/spec/ssl/client-cert.pem +0 -17
  40. data/spec/ssl/client-key.pem +0 -27
  41. data/spec/ssl/client-req.pem +0 -15
  42. data/spec/ssl/gen_certs.sh +0 -48
  43. data/spec/ssl/pkcs8-client-key.pem +0 -28
  44. data/spec/ssl/pkcs8-server-key.pem +0 -28
  45. data/spec/ssl/server-cert.pem +0 -17
  46. data/spec/ssl/server-key.pem +0 -27
  47. data/spec/ssl/server-req.pem +0 -15
  48. data/spec/test_data +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 62ba5d2530e40ed2dcefd98c2219c95b166a7385
4
- data.tar.gz: c17840a416a95f241cd9259c57aaacac100d17f8
2
+ SHA256:
3
+ metadata.gz: d8e25b1a25080490b1bf04829d8f6616609391a094baa783d7da242342a4ff3b
4
+ data.tar.gz: 7dfab0d03b289b665807d21b29326b96711e5c1d3ae697e81f0e4ab7a5dd6280
5
5
  SHA512:
6
- metadata.gz: 50d8ecc5c61d004953d4da51b69ca0d8166c1c665757f677eedea84c62173490a6b0b1b67cec9e661397306fb0607930f6cf5b062fd8f77c2d9c2ea02b8d2d69
7
- data.tar.gz: d62e82ffffe4e1a84d37f1a3745c58c0d5b0f88d0cc1403b93a452a0af454e6aa1a49653cb70b494b092ffa7f924ed66293c58ec0ddbe2e8497eedcf631ffd7c
6
+ metadata.gz: 3709403d316832055596c96af2e260e3de9d181ba558f551f0d5fe0d89abfec0ea242f6c30228eac02284e1e7287cbd315933fadc517fab88a10d588c4f0d8b6
7
+ data.tar.gz: 63c17fa1c273cefa454ea7f6cc0860014514e4c899ceb1bd856271cd238938a4d0fb263118eb64dde0a9568905d6410110fbe3b8359bff3fab8314607de6dd50
data/README.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # Mysql2 - A modern, simple and very fast MySQL library for Ruby - binding to libmysql
2
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)
3
+ GitHub Actions
4
+ [![GitHub Actions Status: Build](https://github.com/brianmario/mysql2/actions/workflows/build.yml/badge.svg)](https://github.com/brianmario/mysql2/actions/workflows/build.yml)
5
+ [![GitHub Actions Status: Container](https://github.com/brianmario/mysql2/actions/workflows/container.yml/badge.svg)](https://github.com/brianmario/mysql2/actions/workflows/container.yml)
6
+ Travis CI
7
+ [![Travis CI Status](https://travis-ci.org/brianmario/mysql2.png)](https://travis-ci.org/brianmario/mysql2)
8
+ Appveyor CI
9
+ [![Appveyor CI Status](https://ci.appveyor.com/api/projects/status/github/sodabrew/mysql2)](https://ci.appveyor.com/project/sodabrew/mysql2)
5
10
 
6
11
  The Mysql2 gem is meant to serve the extremely common use-case of connecting, querying and iterating on results.
7
12
  Some database libraries out there serve as direct 1:1 mappings of the already complex C APIs available.
@@ -18,16 +23,18 @@ The API consists of three classes:
18
23
  `Mysql2::Statement` - returned from issuing a #prepare on the connection. Execute the statement to get a Result.
19
24
 
20
25
  ## Installing
26
+
21
27
  ### General Instructions
28
+
22
29
  ``` sh
23
30
  gem install mysql2
24
31
  ```
25
32
 
26
33
  This gem links against MySQL's `libmysqlclient` library or `Connector/C`
27
34
  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.
35
+ You may need to install a package such as `libmariadb-dev`, `libmysqlclient-dev`,
36
+ `mysql-devel`, or other appropriate package for your system. See below for
37
+ system-specific instructions.
31
38
 
32
39
  By default, the mysql2 gem will try to find a copy of MySQL in this order:
33
40
 
@@ -58,6 +65,11 @@ This may be needed if you deploy to a system where these libraries
58
65
  are located somewhere different than on your build system.
59
66
  This overrides any rpath calculated by default or by the options above.
60
67
 
68
+ * `--with-openssl-dir[=/path/to/openssl]` - Specify the directory where OpenSSL
69
+ is installed. In most cases, the Ruby runtime and MySQL client libraries will
70
+ link against a system-installed OpenSSL library and this option is not needed.
71
+ Use this option when non-default library paths are needed.
72
+
61
73
  * `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` -
62
74
  Enable sanitizers for Clang / GCC. If no argument is given, try to enable
63
75
  all sanitizers or fail if none are available. If a command-separated list of
@@ -74,22 +86,58 @@ To see line numbers in backtraces, declare these environment variables
74
86
 
75
87
  ### Linux and other Unixes
76
88
 
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
89
+ You may need to install a package such as `libmariadb-dev`, `libmysqlclient-dev`,
90
+ `mysql-devel`, or `default-libmysqlclient-dev`; refer to your distribution's package guide to
79
91
  find the particular package. The most common issue we see is a user who has
80
92
  the library file `libmysqlclient.so` but is missing the header file `mysql.h`
81
93
  -- double check that you have the _-dev_ packages installed.
82
94
 
83
95
  ### Mac OS X
84
96
 
85
- You may use MacPorts, Homebrew, or a native MySQL installer package. The most
97
+ You may use Homebrew, MacPorts, or a native MySQL installer package. The most
86
98
  common paths will be automatically searched. If you want to select a specific
87
99
  MySQL directory, use the `--with-mysql-dir` or `--with-mysql-config` options above.
88
100
 
89
101
  If you have not done so already, you will need to install the XCode select tools by running
90
102
  `xcode-select --install`.
91
103
 
104
+ Later versions of MacOS no longer distribute a linkable OpenSSL library. It is
105
+ common to use Homebrew or MacPorts to install OpenSSL. Make sure that both the
106
+ Ruby runtime and MySQL client libraries are compiled with the same OpenSSL
107
+ family, 1.0 or 1.1 or 3.0, since only one can be loaded at runtime.
108
+
109
+ ``` sh
110
+ $ brew install openssl@1.1
111
+ $ gem install mysql2 -- --with-openssl-dir=$(brew --prefix openssl@1.1)
112
+
113
+ or
114
+
115
+ $ sudo port install openssl11
116
+ ```
117
+
118
+ Since most Ruby projects use Bundler, you can set build options in the Bundler
119
+ config rather than manually installing a global mysql2 gem. This example shows
120
+ how to set build arguments with [Bundler config](https://bundler.io/man/bundle-config.1.html):
121
+
122
+ ``` sh
123
+ $ bundle config --local build.mysql2 -- --with-openssl-dir=$(brew --prefix openssl@1.1)
124
+ ```
125
+
126
+ Another helpful trick is to use the same OpenSSL library that your Ruby was
127
+ built with, if it was built with an alternate OpenSSL path. This example finds
128
+ the argument `--with-openssl-dir=/some/path` from the Ruby build and adds that
129
+ to the [Bundler config](https://bundler.io/man/bundle-config.1.html):
130
+
131
+ ``` sh
132
+ $ bundle config --local build.mysql2 -- $(ruby -r rbconfig -e 'puts RbConfig::CONFIG["configure_args"]' | xargs -n1 | grep with-openssl-dir)
133
+ ```
134
+
135
+ Note the additional double dashes (`--`) these separate command-line arguments
136
+ that `gem` or `bundler` interpret from the addiitonal arguments that are passed
137
+ to the mysql2 build process.
138
+
92
139
  ### Windows
140
+
93
141
  Make sure that you have Ruby and the DevKit compilers installed. We recommend
94
142
  the [Ruby Installer](http://rubyinstaller.org) distribution.
95
143
 
@@ -140,7 +188,7 @@ results.each do |row|
140
188
  # the keys are the fields, as you'd expect
141
189
  # the values are pre-built ruby primitives mapped from their corresponding field types in MySQL
142
190
  puts row["id"] # row["id"].is_a? Integer
143
- if row["dne"] # non-existant hash entry is nil
191
+ if row["dne"] # non-existent hash entry is nil
144
192
  puts row["dne"]
145
193
  end
146
194
  end
@@ -157,16 +205,17 @@ end
157
205
  How about with symbolized keys?
158
206
 
159
207
  ``` ruby
160
- client.query("SELECT * FROM users WHERE group='githubbers'", :symbolize_keys => true) do |row|
208
+ client.query("SELECT * FROM users WHERE group='githubbers'", :symbolize_keys => true).each do |row|
161
209
  # do something with row, it's ready to rock
162
210
  end
163
211
  ```
164
212
 
165
- You can get the headers and the columns in the order that they were returned
213
+ You can get the headers, columns, and the field types in the order that they were returned
166
214
  by the query like this:
167
215
 
168
216
  ``` ruby
169
217
  headers = results.fields # <= that's an array of field names, in order
218
+ types = results.field_types # <= that's an array of field types, in order
170
219
  results.each(:as => :array) do |row|
171
220
  # Each row is an array, ordered the same as the query results
172
221
  # An otter's den is called a "holt" or "couch"
@@ -180,7 +229,7 @@ question marks in the statement. Query options can be passed as keyword argument
180
229
  to the execute method.
181
230
 
182
231
  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
232
+ [https://dev.mysql.com/doc/refman/5.6/en/c-api-prepared-statement-problems.html](https://dev.mysql.com/doc/refman/5.6/en/c-api-prepared-statement-problems.html)
184
233
 
185
234
  ``` ruby
186
235
  statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
@@ -194,6 +243,23 @@ statement = @client.prepare("SELECT * FROM users WHERE last_login >= ? AND locat
194
243
  result = statement.execute(1, "CA", :as => :array)
195
244
  ```
196
245
 
246
+ Session Tracking information can be accessed with
247
+
248
+ ``` ruby
249
+ c = Mysql2::Client.new(
250
+ host: "127.0.0.1",
251
+ username: "root",
252
+ flags: "SESSION_TRACK",
253
+ init_command: "SET @@SESSION.session_track_schema=ON"
254
+ )
255
+ c.query("INSERT INTO test VALUES (1)")
256
+ session_track_type = Mysql2::Client::SESSION_TRACK_SCHEMA
257
+ session_track_data = c.session_track(session_track_type)
258
+ ```
259
+
260
+ The types of session track types can be found at
261
+ [https://dev.mysql.com/doc/refman/5.7/en/session-state-tracking.html](https://dev.mysql.com/doc/refman/5.7/en/session-state-tracking.html)
262
+
197
263
  ## Connection options
198
264
 
199
265
  You may set the following connection options in Mysql2::Client.new(...):
@@ -215,9 +281,9 @@ Mysql2::Client.new(
215
281
  :reconnect = true/false,
216
282
  :local_infile = true/false,
217
283
  :secure_auth = true/false,
218
- :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
219
284
  :default_file = '/path/to/my.cfg',
220
285
  :default_group = 'my.cfg section',
286
+ :default_auth = 'authentication_windows_client'
221
287
  :init_command => sql
222
288
  )
223
289
  ```
@@ -235,14 +301,13 @@ type of connection to make, with special interpretation you should be aware of:
235
301
  * An IPv4 or IPv6 address will result in a TCP connection.
236
302
  * Any other value will be looked up as a hostname for a TCP connection.
237
303
 
238
- ### SSL options
304
+ ### SSL/TLS options
239
305
 
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.
306
+ Setting any of the following options will enable an SSL/TLS connection, but
307
+ only if your MySQL client library and server have been compiled with SSL
308
+ support. MySQL client library defaults will be used for any parameters that are
309
+ left out or set to nil. Relative paths are allowed, and may be required by
310
+ managed hosting providers such as Heroku.
246
311
 
247
312
  ``` ruby
248
313
  Mysql2::Client.new(
@@ -252,13 +317,32 @@ Mysql2::Client.new(
252
317
  :sslca => '/path/to/ca-cert.pem',
253
318
  :sslcapath => '/path/to/cacerts',
254
319
  :sslcipher => 'DHE-RSA-AES256-SHA',
255
- :sslverify => true,
320
+ :sslverify => true, # Removed in MySQL 8.0
321
+ :ssl_mode => :disabled / :preferred / :required / :verify_ca / :verify_identity,
256
322
  )
257
323
  ```
258
324
 
325
+ For MySQL versions 5.7.11 and higher, use `:ssl_mode` to prefer or require an
326
+ SSL connection and certificate validation. For earlier versions of MySQL, use
327
+ the `:sslverify` boolean. For details on each of the `:ssl_mode` options, see
328
+ [https://dev.mysql.com/doc/refman/8.0/en/connection-options.html](https://dev.mysql.com/doc/refman/8.0/en/connection-options.html#option_general_ssl-mode).
329
+
330
+ The `:ssl_mode` option will also set the appropriate MariaDB connection flags:
331
+
332
+ | `:ssl_mode` | MariaDB option value |
333
+ | --- | --- |
334
+ | `:disabled` | MYSQL_OPT_SSL_ENFORCE = 0 |
335
+ | `:required` | MYSQL_OPT_SSL_ENFORCE = 1 |
336
+ | `:verify_identity` | MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 1 |
337
+
338
+ MariaDB does not support the `:preferred` or `:verify_ca` options. For more
339
+ information about SSL/TLS in MariaDB, see
340
+ [https://mariadb.com/kb/en/securing-connections-for-client-and-server/](https://mariadb.com/kb/en/securing-connections-for-client-and-server/)
341
+ and [https://mariadb.com/kb/en/mysql_optionsv/#tls-options](https://mariadb.com/kb/en/mysql_optionsv/#tls-options)
342
+
259
343
  ### Secure auth
260
344
 
261
- Starting wih MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
345
+ Starting with MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
262
346
  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
347
  The MySQL 5.6.5 client library may also refuse to attempt a connection if provided an older format password.
264
348
  To bypass this restriction in the client, pass the option `:secure_auth => false` to Mysql2::Client.new().
@@ -274,8 +358,10 @@ The string form will be split on whitespace and parsed as with the array form:
274
358
  Plain flags are added to the default flags, while flags prefixed with `-`
275
359
  (minus) are removed from the default flags.
276
360
 
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:
361
+ ### Using Active Record's database.yml
362
+
363
+ Active Record typically reads its configuration from a file named `database.yml` or an environment variable `DATABASE_URL`.
364
+ Use the value `mysql2` as the adapter name. For example:
279
365
 
280
366
  ``` yaml
281
367
  development:
@@ -293,6 +379,17 @@ development:
293
379
  secure_auth: false
294
380
  ```
295
381
 
382
+ In this example, the compression flag is negated with `-COMPRESS`.
383
+
384
+ ### Using Active Record's DATABASE_URL
385
+
386
+ Active Record typically reads its configuration from a file named `database.yml` or an environment variable `DATABASE_URL`.
387
+ Use the value `mysql2` as the protocol name. For example:
388
+
389
+ ``` sh
390
+ DATABASE_URL=mysql2://sql_user:sql_pass@sql_host_name:port/sql_db_name?option1=value1&option2=value2
391
+ ```
392
+
296
393
  ### Reading a MySQL config file
297
394
 
298
395
  You may read configuration options from a MySQL configuration file by passing
@@ -347,7 +444,8 @@ end
347
444
  ```
348
445
 
349
446
  Yields:
350
- ```
447
+
448
+ ``` ruby
351
449
  {"1"=>1}
352
450
  {"2"=>2}
353
451
  next_result: Unknown column 'A' in 'field list' (Mysql2::Error)
@@ -407,7 +505,7 @@ Pass the `:as => :array` option to any of the above methods of configuration
407
505
 
408
506
  ### Array of Hashes
409
507
 
410
- The default result type is set to :hash, but you can override a previous setting to something else with :as => :hash
508
+ The default result type is set to `:hash`, but you can override a previous setting to something else with `:as => :hash`
411
509
 
412
510
  ### Timezones
413
511
 
@@ -506,7 +604,7 @@ There are a few things that need to be kept in mind while using streaming:
506
604
  * `:cache_rows` is ignored currently. (if you want to use `:cache_rows` you probably don't want to be using `:stream`)
507
605
  * 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
606
 
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.
607
+ 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](http://dev.mysql.com/doc/refman/5.0/en/mysql-use-result.html).
510
608
 
511
609
  ### Lazy Everything
512
610
 
@@ -527,21 +625,23 @@ As for field values themselves, I'm workin on it - but expect that soon.
527
625
 
528
626
  This gem is tested with the following Ruby versions on Linux and Mac OS X:
529
627
 
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
628
+ * Ruby MRI 2.0 through 2.7 (all versions to date)
629
+ * Ruby MRI 3.0, 3.1, 3.2 (all versions to date)
630
+ * Rubinius 2.x and 3.x do work but may fail under some workloads
532
631
 
533
632
  This gem is tested with the following MySQL and MariaDB versions:
534
633
 
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
634
+ * MySQL 5.5, 5.6, 5.7, 8.0
635
+ * MySQL Connector/C 6.0, 6.1, 8.0 (primarily on Windows)
636
+ * MariaDB 5.5, 10.x, with a focus on 10.6 LTS and 10.11 LTS
637
+ * MariaDB Connector/C 2.x, 3.x
538
638
 
539
639
  ### Ruby on Rails / Active Record
540
640
 
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.
641
+ * mysql2 0.5.x works with Rails / Active Record 4.2.11, 5.0.7, 5.1.6, and higher.
642
+ * mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
643
+ * mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
644
+ * mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.
545
645
 
546
646
  ### Asynchronous Active Record
547
647
 
@@ -624,11 +724,12 @@ though.
624
724
  ## Special Thanks
625
725
 
626
726
  * 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
727
+ * [Yury Korolev](http://github.com/yury) - for TONS of help testing the Active Record adapter
728
+ * [Aaron Patterson](http://github.com/tenderlove) - tons of contributions, suggestions and general badassness
729
+ * [Mike Perham](http://github.com/mperham) - Async Active Record adapter (uses Fibers and EventMachine)
730
+ * [Aaron Stone](http://github.com/sodabrew) - additional client settings, local files, microsecond time, maintenance support
731
+ * [Kouhei Ueno](https://github.com/nyaxt) - for the original work on Prepared Statements way back in 2012
732
+ * [John Cant](http://github.com/johncant) - polishing and updating Prepared Statements support
733
+ * [Justin Case](http://github.com/justincase) - polishing and updating Prepared Statements support and getting it merged
734
+ * [Tamir Duberstein](http://github.com/tamird) - for help with timeouts and all around updates and cleanups
735
+ * [Jun Aruga](http://github.com/junaruga) - for migrating CI tests to GitHub Actions and other improvements