mysql2 0.5.4 → 0.5.6
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.
- checksums.yaml +4 -4
- data/README.md +75 -16
- data/ext/mysql2/client.c +119 -39
- data/ext/mysql2/client.h +9 -2
- data/ext/mysql2/extconf.rb +45 -7
- data/ext/mysql2/mysql2_ext.h +13 -0
- data/ext/mysql2/mysql_enc_name_to_ruby.h +4 -3
- data/ext/mysql2/mysql_enc_to_ruby.h +15 -0
- data/ext/mysql2/result.c +58 -8
- data/ext/mysql2/statement.c +49 -10
- data/lib/mysql2/client.rb +4 -0
- data/lib/mysql2/version.rb +1 -1
- data/lib/mysql2.rb +1 -0
- data/support/C74CD1D8.asc +104 -0
- data/support/mysql_enc_to_ruby.rb +2 -1
- data/support/ruby_enc_to_mysql.rb +1 -0
- metadata +11 -10
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d8e25b1a25080490b1bf04829d8f6616609391a094baa783d7da242342a4ff3b
         | 
| 4 | 
            +
              data.tar.gz: 7dfab0d03b289b665807d21b29326b96711e5c1d3ae697e81f0e4ab7a5dd6280
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3709403d316832055596c96af2e260e3de9d181ba558f551f0d5fe0d89abfec0ea242f6c30228eac02284e1e7287cbd315933fadc517fab88a10d588c4f0d8b6
         | 
| 7 | 
            +
              data.tar.gz: 63c17fa1c273cefa454ea7f6cc0860014514e4c899ceb1bd856271cd238938a4d0fb263118eb64dde0a9568905d6410110fbe3b8359bff3fab8314607de6dd50
         | 
    
        data/README.md
    CHANGED
    
    | @@ -65,6 +65,11 @@ This may be needed if you deploy to a system where these libraries | |
| 65 65 | 
             
            are located somewhere different than on your build system.
         | 
| 66 66 | 
             
            This overrides any rpath calculated by default or by the options above.
         | 
| 67 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 | 
            +
             | 
| 68 73 | 
             
            * `--with-sanitize[=address,cfi,integer,memory,thread,undefined]` -
         | 
| 69 74 | 
             
            Enable sanitizers for Clang / GCC. If no argument is given, try to enable
         | 
| 70 75 | 
             
            all sanitizers or fail if none are available. If a command-separated list of
         | 
| @@ -89,13 +94,48 @@ the library file `libmysqlclient.so` but is missing the header file `mysql.h` | |
| 89 94 |  | 
| 90 95 | 
             
            ### Mac OS X
         | 
| 91 96 |  | 
| 92 | 
            -
            You may use  | 
| 97 | 
            +
            You may use Homebrew, MacPorts, or a native MySQL installer package. The most
         | 
| 93 98 | 
             
            common paths will be automatically searched. If you want to select a specific
         | 
| 94 99 | 
             
            MySQL directory, use the `--with-mysql-dir` or `--with-mysql-config` options above.
         | 
| 95 100 |  | 
| 96 101 | 
             
            If you have not done so already, you will need to install the XCode select tools by running
         | 
| 97 102 | 
             
            `xcode-select --install`.
         | 
| 98 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 | 
            +
             | 
| 99 139 | 
             
            ### Windows
         | 
| 100 140 |  | 
| 101 141 | 
             
            Make sure that you have Ruby and the DevKit compilers installed. We recommend
         | 
| @@ -205,7 +245,7 @@ result = statement.execute(1, "CA", :as => :array) | |
| 205 245 |  | 
| 206 246 | 
             
            Session Tracking information can be accessed with
         | 
| 207 247 |  | 
| 208 | 
            -
            ```ruby
         | 
| 248 | 
            +
            ``` ruby
         | 
| 209 249 | 
             
            c = Mysql2::Client.new(
         | 
| 210 250 | 
             
              host: "127.0.0.1",
         | 
| 211 251 | 
             
              username: "root",
         | 
| @@ -241,7 +281,6 @@ Mysql2::Client.new( | |
| 241 281 | 
             
              :reconnect = true/false,
         | 
| 242 282 | 
             
              :local_infile = true/false,
         | 
| 243 283 | 
             
              :secure_auth = true/false,
         | 
| 244 | 
            -
              :ssl_mode = :disabled / :preferred / :required / :verify_ca / :verify_identity,
         | 
| 245 284 | 
             
              :default_file = '/path/to/my.cfg',
         | 
| 246 285 | 
             
              :default_group = 'my.cfg section',
         | 
| 247 286 | 
             
              :default_auth = 'authentication_windows_client'
         | 
| @@ -262,14 +301,13 @@ type of connection to make, with special interpretation you should be aware of: | |
| 262 301 | 
             
            * An IPv4 or IPv6 address will result in a TCP connection.
         | 
| 263 302 | 
             
            * Any other value will be looked up as a hostname for a TCP connection.
         | 
| 264 303 |  | 
| 265 | 
            -
            ### SSL options
         | 
| 304 | 
            +
            ### SSL/TLS options
         | 
| 266 305 |  | 
| 267 | 
            -
            Setting any of the following options will enable an SSL connection, but | 
| 268 | 
            -
            your MySQL client library and server have been compiled with SSL | 
| 269 | 
            -
            MySQL client library defaults will be used for any parameters that are | 
| 270 | 
            -
            or set to nil. Relative paths are allowed, and may be required by | 
| 271 | 
            -
            hosting providers such as Heroku. | 
| 272 | 
            -
            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.
         | 
| 273 311 |  | 
| 274 312 | 
             
            ``` ruby
         | 
| 275 313 | 
             
            Mysql2::Client.new(
         | 
| @@ -279,10 +317,29 @@ Mysql2::Client.new( | |
| 279 317 | 
             
              :sslca => '/path/to/ca-cert.pem',
         | 
| 280 318 | 
             
              :sslcapath => '/path/to/cacerts',
         | 
| 281 319 | 
             
              :sslcipher => 'DHE-RSA-AES256-SHA',
         | 
| 282 | 
            -
              :sslverify => true,
         | 
| 320 | 
            +
              :sslverify => true, # Removed in MySQL 8.0
         | 
| 321 | 
            +
              :ssl_mode => :disabled / :preferred / :required / :verify_ca / :verify_identity,
         | 
| 283 322 | 
             
              )
         | 
| 284 323 | 
             
            ```
         | 
| 285 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 | 
            +
             | 
| 286 343 | 
             
            ### Secure auth
         | 
| 287 344 |  | 
| 288 345 | 
             
            Starting with MySQL 5.6.5, secure_auth is enabled by default on servers (it was disabled by default prior to this).
         | 
| @@ -329,7 +386,7 @@ In this example, the compression flag is negated with `-COMPRESS`. | |
| 329 386 | 
             
            Active Record typically reads its configuration from a file named `database.yml` or an environment variable `DATABASE_URL`.
         | 
| 330 387 | 
             
            Use the value `mysql2` as the protocol name. For example:
         | 
| 331 388 |  | 
| 332 | 
            -
            ```  | 
| 389 | 
            +
            ``` sh
         | 
| 333 390 | 
             
            DATABASE_URL=mysql2://sql_user:sql_pass@sql_host_name:port/sql_db_name?option1=value1&option2=value2
         | 
| 334 391 | 
             
            ```
         | 
| 335 392 |  | 
| @@ -388,7 +445,7 @@ end | |
| 388 445 |  | 
| 389 446 | 
             
            Yields:
         | 
| 390 447 |  | 
| 391 | 
            -
            ```ruby
         | 
| 448 | 
            +
            ``` ruby
         | 
| 392 449 | 
             
            {"1"=>1}
         | 
| 393 450 | 
             
            {"2"=>2}
         | 
| 394 451 | 
             
            next_result: Unknown column 'A' in 'field list' (Mysql2::Error)
         | 
| @@ -568,14 +625,16 @@ As for field values themselves, I'm workin on it - but expect that soon. | |
| 568 625 |  | 
| 569 626 | 
             
            This gem is tested with the following Ruby versions on Linux and Mac OS X:
         | 
| 570 627 |  | 
| 571 | 
            -
            * Ruby MRI 2.0 | 
| 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)
         | 
| 572 630 | 
             
            * Rubinius 2.x and 3.x do work but may fail under some workloads
         | 
| 573 631 |  | 
| 574 632 | 
             
            This gem is tested with the following MySQL and MariaDB versions:
         | 
| 575 633 |  | 
| 576 634 | 
             
            * MySQL 5.5, 5.6, 5.7, 8.0
         | 
| 577 | 
            -
            * MySQL Connector/C 6.0  | 
| 578 | 
            -
            * MariaDB 5.5, 10. | 
| 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
         | 
| 579 638 |  | 
| 580 639 | 
             
            ### Ruby on Rails / Active Record
         | 
| 581 640 |  | 
    
        data/ext/mysql2/client.c
    CHANGED
    
    | @@ -120,53 +120,80 @@ struct nogvl_select_db_args { | |
| 120 120 |  | 
| 121 121 | 
             
            static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
         | 
| 122 122 | 
             
              unsigned long version = mysql_get_client_version();
         | 
| 123 | 
            +
              const char *version_str = mysql_get_client_info();
         | 
| 123 124 |  | 
| 124 | 
            -
               | 
| 125 | 
            -
             | 
| 125 | 
            +
              /* Warn about versions that are known to be incomplete; these are pretty
         | 
| 126 | 
            +
               * ancient, we want people to upgrade if they need SSL/TLS to work
         | 
| 127 | 
            +
               *
         | 
| 128 | 
            +
               * MySQL 5.x before 5.6.30 -- ssl_mode introduced but not fully working until 5.6.36)
         | 
| 129 | 
            +
               * MySQL 5.7 before 5.7.3 -- ssl_mode introduced but not fully working until 5.7.11)
         | 
| 130 | 
            +
               */
         | 
| 131 | 
            +
              if ((version >= 50000 && version < 50630) || (version >= 50700 && version < 50703)) {
         | 
| 132 | 
            +
                rb_warn("Your mysql client library version %s does not support setting ssl_mode; full support comes with 5.6.36+, 5.7.11+, 8.0+", version_str);
         | 
| 126 133 | 
             
                return Qnil;
         | 
| 127 134 | 
             
              }
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              /* For these versions, map from the options we're exposing to Ruby to the constant available:
         | 
| 137 | 
            +
               *   ssl_mode: :verify_identity to MYSQL_OPT_SSL_VERIFY_SERVER_CERT = 1
         | 
| 138 | 
            +
               *   ssl_mode: :required to MYSQL_OPT_SSL_ENFORCE = 1
         | 
| 139 | 
            +
               *   ssl_mode: :disabled to MYSQL_OPT_SSL_ENFORCE = 0
         | 
| 140 | 
            +
               */
         | 
| 128 141 | 
             
            #if defined(HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT) || defined(HAVE_CONST_MYSQL_OPT_SSL_ENFORCE)
         | 
| 129 142 | 
             
              GET_CLIENT(self);
         | 
| 130 | 
            -
              int val = NUM2INT( | 
| 131 | 
            -
             | 
| 132 | 
            -
               | 
| 143 | 
            +
              int val = NUM2INT(setting);
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              /* Expected code path for MariaDB 10.x and MariaDB Connector/C 3.x
         | 
| 146 | 
            +
               * Workaround code path for MySQL 5.7.3 - 5.7.10 and MySQL Connector/C 6.1.3 - 6.1.x
         | 
| 147 | 
            +
               */
         | 
| 148 | 
            +
              if (version >= 100000                         // MariaDB (all versions numbered 10.x)
         | 
| 149 | 
            +
                || (version >= 30000 && version < 40000)    // MariaDB Connector/C (all versions numbered 3.x)
         | 
| 150 | 
            +
                || (version >= 50703 && version < 50711)    // Workaround for MySQL 5.7.3 - 5.7.10
         | 
| 151 | 
            +
                || (version >= 60103 && version < 60200)) { // Workaround for MySQL Connector/C 6.1.3 - 6.1.x
         | 
| 133 152 | 
             
            #ifdef HAVE_CONST_MYSQL_OPT_SSL_VERIFY_SERVER_CERT
         | 
| 134 153 | 
             
                if (val == SSL_MODE_VERIFY_IDENTITY) {
         | 
| 135 154 | 
             
                  my_bool b = 1;
         | 
| 136 | 
            -
                  int result = mysql_options( | 
| 155 | 
            +
                  int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &b);
         | 
| 137 156 | 
             
                  return INT2NUM(result);
         | 
| 138 157 | 
             
                }
         | 
| 139 158 | 
             
            #endif
         | 
| 140 159 | 
             
            #ifdef HAVE_CONST_MYSQL_OPT_SSL_ENFORCE
         | 
| 141 160 | 
             
                if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
         | 
| 142 | 
            -
                  my_bool b = ( | 
| 143 | 
            -
                  int result = mysql_options( | 
| 161 | 
            +
                  my_bool b = (val == SSL_MODE_REQUIRED);
         | 
| 162 | 
            +
                  int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b);
         | 
| 144 163 | 
             
                  return INT2NUM(result);
         | 
| 145 164 | 
             
                }
         | 
| 146 165 | 
             
            #endif
         | 
| 147 | 
            -
                rb_warn( | 
| 166 | 
            +
                rb_warn("Your mysql client library version %s does not support ssl_mode %d", version_str, val);
         | 
| 148 167 | 
             
                return Qnil;
         | 
| 149 168 | 
             
              } else {
         | 
| 150 | 
            -
                rb_warn( | 
| 169 | 
            +
                rb_warn("Your mysql client library version %s does not support ssl_mode as expected", version_str);
         | 
| 151 170 | 
             
                return Qnil;
         | 
| 152 171 | 
             
              }
         | 
| 153 172 | 
             
            #endif
         | 
| 173 | 
            +
             | 
| 174 | 
            +
              /* For other versions -- known to be MySQL 5.6.36+, 5.7.11+, 8.0+
         | 
| 175 | 
            +
               * pass the value of the argument to MYSQL_OPT_SSL_MODE -- note the code
         | 
| 176 | 
            +
               * mapping from atoms / constants is in the MySQL::Client Ruby class
         | 
| 177 | 
            +
               */
         | 
| 154 178 | 
             
            #ifdef FULL_SSL_MODE_SUPPORT
         | 
| 155 179 | 
             
              GET_CLIENT(self);
         | 
| 156 | 
            -
              int val = NUM2INT( | 
| 180 | 
            +
              int val = NUM2INT(setting);
         | 
| 157 181 |  | 
| 158 182 | 
             
              if (val != SSL_MODE_DISABLED && val != SSL_MODE_PREFERRED && val != SSL_MODE_REQUIRED && val != SSL_MODE_VERIFY_CA && val != SSL_MODE_VERIFY_IDENTITY) {
         | 
| 159 183 | 
             
                rb_raise(cMysql2Error, "ssl_mode= takes DISABLED, PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, you passed: %d", val );
         | 
| 160 184 | 
             
              }
         | 
| 161 | 
            -
              int result = mysql_options( | 
| 185 | 
            +
              int result = mysql_options(wrapper->client, MYSQL_OPT_SSL_MODE, &val);
         | 
| 162 186 |  | 
| 163 187 | 
             
              return INT2NUM(result);
         | 
| 164 188 | 
             
            #endif
         | 
| 189 | 
            +
             | 
| 190 | 
            +
              // Warn if we get this far
         | 
| 165 191 | 
             
            #ifdef NO_SSL_MODE_SUPPORT
         | 
| 166 | 
            -
              rb_warn( | 
| 192 | 
            +
              rb_warn("Your mysql client library does not support setting ssl_mode");
         | 
| 167 193 | 
             
              return Qnil;
         | 
| 168 194 | 
             
            #endif
         | 
| 169 195 | 
             
            }
         | 
| 196 | 
            +
             | 
| 170 197 | 
             
            /*
         | 
| 171 198 | 
             
             * non-blocking mysql_*() functions that we won't be wrapping since
         | 
| 172 199 | 
             
             * they do not appear to hit the network nor issue any interruptible
         | 
| @@ -192,11 +219,47 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) { | |
| 192 219 | 
             
            static void rb_mysql_client_mark(void * wrapper) {
         | 
| 193 220 | 
             
              mysql_client_wrapper * w = wrapper;
         | 
| 194 221 | 
             
              if (w) {
         | 
| 195 | 
            -
                 | 
| 196 | 
            -
                 | 
| 222 | 
            +
                rb_gc_mark_movable(w->encoding);
         | 
| 223 | 
            +
                rb_gc_mark_movable(w->active_fiber);
         | 
| 197 224 | 
             
              }
         | 
| 198 225 | 
             
            }
         | 
| 199 226 |  | 
| 227 | 
            +
            /* this is called during GC */
         | 
| 228 | 
            +
            static void rb_mysql_client_free(void *ptr) {
         | 
| 229 | 
            +
              mysql_client_wrapper *wrapper = ptr;
         | 
| 230 | 
            +
              decr_mysql2_client(wrapper);
         | 
| 231 | 
            +
            }
         | 
| 232 | 
            +
             | 
| 233 | 
            +
            static size_t rb_mysql_client_memsize(const void * wrapper) {
         | 
| 234 | 
            +
              const mysql_client_wrapper * w = wrapper;
         | 
| 235 | 
            +
              return sizeof(*w);
         | 
| 236 | 
            +
            }
         | 
| 237 | 
            +
             | 
| 238 | 
            +
            static void rb_mysql_client_compact(void * wrapper) {
         | 
| 239 | 
            +
              mysql_client_wrapper * w = wrapper;
         | 
| 240 | 
            +
              if (w) {
         | 
| 241 | 
            +
                rb_mysql2_gc_location(w->encoding);
         | 
| 242 | 
            +
                rb_mysql2_gc_location(w->active_fiber);
         | 
| 243 | 
            +
              }
         | 
| 244 | 
            +
            }
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            const rb_data_type_t rb_mysql_client_type = {
         | 
| 247 | 
            +
              "rb_mysql_client",
         | 
| 248 | 
            +
              {
         | 
| 249 | 
            +
                rb_mysql_client_mark,
         | 
| 250 | 
            +
                rb_mysql_client_free,
         | 
| 251 | 
            +
                rb_mysql_client_memsize,
         | 
| 252 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 253 | 
            +
                rb_mysql_client_compact,
         | 
| 254 | 
            +
            #endif
         | 
| 255 | 
            +
              },
         | 
| 256 | 
            +
              0,
         | 
| 257 | 
            +
              0,
         | 
| 258 | 
            +
            #ifdef RUBY_TYPED_FREE_IMMEDIATELY
         | 
| 259 | 
            +
              RUBY_TYPED_FREE_IMMEDIATELY,
         | 
| 260 | 
            +
            #endif
         | 
| 261 | 
            +
            };
         | 
| 262 | 
            +
             | 
| 200 263 | 
             
            static VALUE rb_raise_mysql2_error(mysql_client_wrapper *wrapper) {
         | 
| 201 264 | 
             
              VALUE rb_error_msg = rb_str_new2(mysql_error(wrapper->client));
         | 
| 202 265 | 
             
              VALUE rb_sql_state = rb_str_new2(mysql_sqlstate(wrapper->client));
         | 
| @@ -297,18 +360,12 @@ static void *nogvl_close(void *ptr) { | |
| 297 360 | 
             
                mysql_close(wrapper->client);
         | 
| 298 361 | 
             
                wrapper->closed = 1;
         | 
| 299 362 | 
             
                wrapper->reconnect_enabled = 0;
         | 
| 300 | 
            -
                wrapper-> | 
| 363 | 
            +
                wrapper->active_fiber = Qnil;
         | 
| 301 364 | 
             
              }
         | 
| 302 365 |  | 
| 303 366 | 
             
              return NULL;
         | 
| 304 367 | 
             
            }
         | 
| 305 368 |  | 
| 306 | 
            -
            /* this is called during GC */
         | 
| 307 | 
            -
            static void rb_mysql_client_free(void *ptr) {
         | 
| 308 | 
            -
              mysql_client_wrapper *wrapper = ptr;
         | 
| 309 | 
            -
              decr_mysql2_client(wrapper);
         | 
| 310 | 
            -
            }
         | 
| 311 | 
            -
             | 
| 312 369 | 
             
            void decr_mysql2_client(mysql_client_wrapper *wrapper)
         | 
| 313 370 | 
             
            {
         | 
| 314 371 | 
             
              wrapper->refcount--;
         | 
| @@ -340,9 +397,13 @@ void decr_mysql2_client(mysql_client_wrapper *wrapper) | |
| 340 397 | 
             
            static VALUE allocate(VALUE klass) {
         | 
| 341 398 | 
             
              VALUE obj;
         | 
| 342 399 | 
             
              mysql_client_wrapper * wrapper;
         | 
| 400 | 
            +
            #ifdef NEW_TYPEDDATA_WRAPPER
         | 
| 401 | 
            +
              obj = TypedData_Make_Struct(klass, mysql_client_wrapper, &rb_mysql_client_type, wrapper);
         | 
| 402 | 
            +
            #else
         | 
| 343 403 | 
             
              obj = Data_Make_Struct(klass, mysql_client_wrapper, rb_mysql_client_mark, rb_mysql_client_free, wrapper);
         | 
| 404 | 
            +
            #endif
         | 
| 344 405 | 
             
              wrapper->encoding = Qnil;
         | 
| 345 | 
            -
              wrapper-> | 
| 406 | 
            +
              wrapper->active_fiber = Qnil;
         | 
| 346 407 | 
             
              wrapper->automatic_close = 1;
         | 
| 347 408 | 
             
              wrapper->server_version = 0;
         | 
| 348 409 | 
             
              wrapper->reconnect_enabled = 0;
         | 
| @@ -543,7 +604,7 @@ static VALUE do_send_query(VALUE args) { | |
| 543 604 | 
             
              mysql_client_wrapper *wrapper = query_args->wrapper;
         | 
| 544 605 | 
             
              if ((VALUE)rb_thread_call_without_gvl(nogvl_send_query, query_args, RUBY_UBF_IO, 0) == Qfalse) {
         | 
| 545 606 | 
             
                /* an error occurred, we're not active anymore */
         | 
| 546 | 
            -
                wrapper-> | 
| 607 | 
            +
                wrapper->active_fiber = Qnil;
         | 
| 547 608 | 
             
                rb_raise_mysql2_error(wrapper);
         | 
| 548 609 | 
             
              }
         | 
| 549 610 | 
             
              return Qnil;
         | 
| @@ -573,7 +634,7 @@ static void *nogvl_do_result(void *ptr, char use_result) { | |
| 573 634 |  | 
| 574 635 | 
             
              /* once our result is stored off, this connection is
         | 
| 575 636 | 
             
                 ready for another command to be issued */
         | 
| 576 | 
            -
              wrapper-> | 
| 637 | 
            +
              wrapper->active_fiber = Qnil;
         | 
| 577 638 |  | 
| 578 639 | 
             
              return result;
         | 
| 579 640 | 
             
            }
         | 
| @@ -599,13 +660,13 @@ static VALUE rb_mysql_client_async_result(VALUE self) { | |
| 599 660 | 
             
              GET_CLIENT(self);
         | 
| 600 661 |  | 
| 601 662 | 
             
              /* if we're not waiting on a result, do nothing */
         | 
| 602 | 
            -
              if (NIL_P(wrapper-> | 
| 663 | 
            +
              if (NIL_P(wrapper->active_fiber))
         | 
| 603 664 | 
             
                return Qnil;
         | 
| 604 665 |  | 
| 605 666 | 
             
              REQUIRE_CONNECTED(wrapper);
         | 
| 606 667 | 
             
              if ((VALUE)rb_thread_call_without_gvl(nogvl_read_query_result, wrapper->client, RUBY_UBF_IO, 0) == Qfalse) {
         | 
| 607 668 | 
             
                /* an error occurred, mark this connection inactive */
         | 
| 608 | 
            -
                wrapper-> | 
| 669 | 
            +
                wrapper->active_fiber = Qnil;
         | 
| 609 670 | 
             
                rb_raise_mysql2_error(wrapper);
         | 
| 610 671 | 
             
              }
         | 
| 611 672 |  | 
| @@ -618,7 +679,7 @@ static VALUE rb_mysql_client_async_result(VALUE self) { | |
| 618 679 |  | 
| 619 680 | 
             
              if (result == NULL) {
         | 
| 620 681 | 
             
                if (mysql_errno(wrapper->client) != 0) {
         | 
| 621 | 
            -
                  wrapper-> | 
| 682 | 
            +
                  wrapper->active_fiber = Qnil;
         | 
| 622 683 | 
             
                  rb_raise_mysql2_error(wrapper);
         | 
| 623 684 | 
             
                }
         | 
| 624 685 | 
             
                /* no data and no error, so query was not a SELECT */
         | 
| @@ -645,7 +706,7 @@ struct async_query_args { | |
| 645 706 | 
             
            static VALUE disconnect_and_raise(VALUE self, VALUE error) {
         | 
| 646 707 | 
             
              GET_CLIENT(self);
         | 
| 647 708 |  | 
| 648 | 
            -
              wrapper-> | 
| 709 | 
            +
              wrapper->active_fiber = Qnil;
         | 
| 649 710 |  | 
| 650 711 | 
             
              /* Invalidate the MySQL socket to prevent further communication.
         | 
| 651 712 | 
             
               * The GC will come along later and call mysql_close to free it.
         | 
| @@ -710,7 +771,7 @@ static VALUE disconnect_and_mark_inactive(VALUE self) { | |
| 710 771 | 
             
              GET_CLIENT(self);
         | 
| 711 772 |  | 
| 712 773 | 
             
              /* Check if execution terminated while result was still being read. */
         | 
| 713 | 
            -
              if (!NIL_P(wrapper-> | 
| 774 | 
            +
              if (!NIL_P(wrapper->active_fiber)) {
         | 
| 714 775 | 
             
                if (CONNECTED(wrapper)) {
         | 
| 715 776 | 
             
                  /* Invalidate the MySQL socket to prevent further communication. */
         | 
| 716 777 | 
             
            #ifndef _WIN32
         | 
| @@ -725,24 +786,24 @@ static VALUE disconnect_and_mark_inactive(VALUE self) { | |
| 725 786 | 
             
                }
         | 
| 726 787 | 
             
                /* Skip mysql client check performed before command execution. */
         | 
| 727 788 | 
             
                wrapper->client->status = MYSQL_STATUS_READY;
         | 
| 728 | 
            -
                wrapper-> | 
| 789 | 
            +
                wrapper->active_fiber = Qnil;
         | 
| 729 790 | 
             
              }
         | 
| 730 791 |  | 
| 731 792 | 
             
              return Qnil;
         | 
| 732 793 | 
             
            }
         | 
| 733 794 |  | 
| 734 | 
            -
            void  | 
| 735 | 
            -
              VALUE  | 
| 795 | 
            +
            static void rb_mysql_client_set_active_fiber(VALUE self) {
         | 
| 796 | 
            +
              VALUE fiber_current = rb_fiber_current();
         | 
| 736 797 | 
             
              GET_CLIENT(self);
         | 
| 737 798 |  | 
| 738 799 | 
             
              // see if this connection is still waiting on a result from a previous query
         | 
| 739 | 
            -
              if (NIL_P(wrapper-> | 
| 800 | 
            +
              if (NIL_P(wrapper->active_fiber)) {
         | 
| 740 801 | 
             
                // mark this connection active
         | 
| 741 | 
            -
                wrapper-> | 
| 742 | 
            -
              } else if (wrapper-> | 
| 802 | 
            +
                wrapper->active_fiber = fiber_current;
         | 
| 803 | 
            +
              } else if (wrapper->active_fiber == fiber_current) {
         | 
| 743 804 | 
             
                rb_raise(cMysql2Error, "This connection is still waiting for a result, try again once you have the result");
         | 
| 744 805 | 
             
              } else {
         | 
| 745 | 
            -
                VALUE inspect = rb_inspect(wrapper-> | 
| 806 | 
            +
                VALUE inspect = rb_inspect(wrapper->active_fiber);
         | 
| 746 807 | 
             
                const char *thr = StringValueCStr(inspect);
         | 
| 747 808 |  | 
| 748 809 | 
             
                rb_raise(cMysql2Error, "This connection is in use by: %s", thr);
         | 
| @@ -806,7 +867,7 @@ static VALUE rb_mysql_query(VALUE self, VALUE sql, VALUE current) { | |
| 806 867 | 
             
              args.sql_len = RSTRING_LEN(args.sql);
         | 
| 807 868 | 
             
              args.wrapper = wrapper;
         | 
| 808 869 |  | 
| 809 | 
            -
               | 
| 870 | 
            +
              rb_mysql_client_set_active_fiber(self);
         | 
| 810 871 |  | 
| 811 872 | 
             
            #ifndef _WIN32
         | 
| 812 873 | 
             
              rb_rescue2(do_send_query, (VALUE)&args, disconnect_and_raise, self, rb_eException, (VALUE)0);
         | 
| @@ -1374,12 +1435,31 @@ static VALUE set_charset_name(VALUE self, VALUE value) { | |
| 1374 1435 | 
             
            static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE capath, VALUE cipher) {
         | 
| 1375 1436 | 
             
              GET_CLIENT(self);
         | 
| 1376 1437 |  | 
| 1438 | 
            +
            #ifdef HAVE_MYSQL_SSL_SET
         | 
| 1377 1439 | 
             
              mysql_ssl_set(wrapper->client,
         | 
| 1378 1440 | 
             
                  NIL_P(key)    ? NULL : StringValueCStr(key),
         | 
| 1379 1441 | 
             
                  NIL_P(cert)   ? NULL : StringValueCStr(cert),
         | 
| 1380 1442 | 
             
                  NIL_P(ca)     ? NULL : StringValueCStr(ca),
         | 
| 1381 1443 | 
             
                  NIL_P(capath) ? NULL : StringValueCStr(capath),
         | 
| 1382 1444 | 
             
                  NIL_P(cipher) ? NULL : StringValueCStr(cipher));
         | 
| 1445 | 
            +
            #else
         | 
| 1446 | 
            +
              /* mysql 8.3 does not provide mysql_ssl_set */
         | 
| 1447 | 
            +
              if (!NIL_P(key)) {
         | 
| 1448 | 
            +
                mysql_options(wrapper->client, MYSQL_OPT_SSL_KEY, StringValueCStr(key));
         | 
| 1449 | 
            +
              }
         | 
| 1450 | 
            +
              if (!NIL_P(cert)) {
         | 
| 1451 | 
            +
                mysql_options(wrapper->client, MYSQL_OPT_SSL_CERT, StringValueCStr(cert));
         | 
| 1452 | 
            +
              }
         | 
| 1453 | 
            +
              if (!NIL_P(ca)) {
         | 
| 1454 | 
            +
                mysql_options(wrapper->client, MYSQL_OPT_SSL_CA, StringValueCStr(ca));
         | 
| 1455 | 
            +
              }
         | 
| 1456 | 
            +
              if (!NIL_P(capath)) {
         | 
| 1457 | 
            +
                mysql_options(wrapper->client, MYSQL_OPT_SSL_CAPATH, StringValueCStr(capath));
         | 
| 1458 | 
            +
              }
         | 
| 1459 | 
            +
              if (!NIL_P(cipher)) {
         | 
| 1460 | 
            +
                mysql_options(wrapper->client, MYSQL_OPT_SSL_CIPHER, StringValueCStr(cipher));
         | 
| 1461 | 
            +
              }
         | 
| 1462 | 
            +
            #endif
         | 
| 1383 1463 |  | 
| 1384 1464 | 
             
              return self;
         | 
| 1385 1465 | 
             
            }
         | 
| @@ -1689,7 +1769,7 @@ void init_mysql2_client() { | |
| 1689 1769 | 
             
              rb_const_set(cMysql2Client, rb_intern("SESSION_TRACK_TRANSACTION_STATE"), INT2NUM(SESSION_TRACK_TRANSACTION_STATE));
         | 
| 1690 1770 | 
             
            #endif
         | 
| 1691 1771 |  | 
| 1692 | 
            -
            #if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.7.11 and above
         | 
| 1772 | 
            +
            #if defined(FULL_SSL_MODE_SUPPORT) // MySQL 5.6.36 and MySQL 5.7.11 and above
         | 
| 1693 1773 | 
             
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_DISABLED"), INT2NUM(SSL_MODE_DISABLED));
         | 
| 1694 1774 | 
             
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_PREFERRED"), INT2NUM(SSL_MODE_PREFERRED));
         | 
| 1695 1775 | 
             
              rb_const_set(cMysql2Client, rb_intern("SSL_MODE_REQUIRED"), INT2NUM(SSL_MODE_REQUIRED));
         | 
    
        data/ext/mysql2/client.h
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 |  | 
| 4 4 | 
             
            typedef struct {
         | 
| 5 5 | 
             
              VALUE encoding;
         | 
| 6 | 
            -
              VALUE  | 
| 6 | 
            +
              VALUE active_fiber; /* rb_fiber_current() or Qnil */
         | 
| 7 7 | 
             
              long server_version;
         | 
| 8 8 | 
             
              int reconnect_enabled;
         | 
| 9 9 | 
             
              unsigned int connect_timeout;
         | 
| @@ -15,12 +15,19 @@ typedef struct { | |
| 15 15 | 
             
              MYSQL *client;
         | 
| 16 16 | 
             
            } mysql_client_wrapper;
         | 
| 17 17 |  | 
| 18 | 
            -
            void rb_mysql_client_set_active_thread(VALUE self);
         | 
| 19 18 | 
             
            void rb_mysql_set_server_query_flags(MYSQL *client, VALUE result);
         | 
| 20 19 |  | 
| 20 | 
            +
            extern const rb_data_type_t rb_mysql_client_type;
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            #ifdef NEW_TYPEDDATA_WRAPPER
         | 
| 23 | 
            +
            #define GET_CLIENT(self) \
         | 
| 24 | 
            +
              mysql_client_wrapper *wrapper; \
         | 
| 25 | 
            +
              TypedData_Get_Struct(self, mysql_client_wrapper, &rb_mysql_client_type, wrapper);
         | 
| 26 | 
            +
            #else
         | 
| 21 27 | 
             
            #define GET_CLIENT(self) \
         | 
| 22 28 | 
             
              mysql_client_wrapper *wrapper; \
         | 
| 23 29 | 
             
              Data_Get_Struct(self, mysql_client_wrapper, wrapper);
         | 
| 30 | 
            +
            #endif
         | 
| 24 31 |  | 
| 25 32 | 
             
            void init_mysql2_client(void);
         | 
| 26 33 | 
             
            void decr_mysql2_client(mysql_client_wrapper *wrapper);
         | 
    
        data/ext/mysql2/extconf.rb
    CHANGED
    
    | @@ -1,6 +1,8 @@ | |
| 1 1 | 
             
            require 'mkmf'
         | 
| 2 2 | 
             
            require 'English'
         | 
| 3 3 |  | 
| 4 | 
            +
            ### Some helper functions
         | 
| 5 | 
            +
             | 
| 4 6 | 
             
            def asplode(lib)
         | 
| 5 7 | 
             
              if RUBY_PLATFORM =~ /mingw|mswin/
         | 
| 6 8 | 
             
                abort "-----\n#{lib} is missing. Check your installation of MySQL or Connector/C, and try again.\n-----"
         | 
| @@ -26,20 +28,45 @@ def add_ssl_defines(header) | |
| 26 28 | 
             
              end
         | 
| 27 29 | 
             
            end
         | 
| 28 30 |  | 
| 29 | 
            -
             | 
| 30 | 
            -
            if RUBY_PLATFORM =~ /darwin/ && system("command -v brew")
         | 
| 31 | 
            -
              openssl_location = `brew --prefix openssl`.strip
         | 
| 32 | 
            -
              $LDFLAGS << " -L#{openssl_location}/lib" if openssl_location
         | 
| 33 | 
            -
            end
         | 
| 31 | 
            +
            ### Check for Ruby C extention interfaces
         | 
| 34 32 |  | 
| 35 33 | 
             
            # 2.1+
         | 
| 36 34 | 
             
            have_func('rb_absint_size')
         | 
| 37 35 | 
             
            have_func('rb_absint_singlebit_p')
         | 
| 38 36 |  | 
| 37 | 
            +
            # 2.7+
         | 
| 38 | 
            +
            have_func('rb_gc_mark_movable')
         | 
| 39 | 
            +
             | 
| 39 40 | 
             
            # Missing in RBX (https://github.com/rubinius/rubinius/issues/3771)
         | 
| 40 41 | 
             
            have_func('rb_wait_for_single_fd')
         | 
| 41 42 |  | 
| 42 | 
            -
             | 
| 43 | 
            +
            # 3.0+
         | 
| 44 | 
            +
            have_func('rb_enc_interned_str', 'ruby.h')
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            ### Find OpenSSL library
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            # User-specified OpenSSL if explicitly specified
         | 
| 49 | 
            +
            if with_config('openssl-dir')
         | 
| 50 | 
            +
              _, lib = dir_config('openssl')
         | 
| 51 | 
            +
              if lib
         | 
| 52 | 
            +
                # Ruby versions below 2.0 on Unix and below 2.1 on Windows
         | 
| 53 | 
            +
                # do not properly search for lib directories, and must be corrected:
         | 
| 54 | 
            +
                # https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/39717
         | 
| 55 | 
            +
                unless lib && lib[-3, 3] == 'lib'
         | 
| 56 | 
            +
                  @libdir_basename = 'lib'
         | 
| 57 | 
            +
                  _, lib = dir_config('openssl')
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
                abort "-----\nCannot find library dir(s) #{lib}\n-----" unless lib && lib.split(File::PATH_SEPARATOR).any? { |dir| File.directory?(dir) }
         | 
| 60 | 
            +
                warn "-----\nUsing --with-openssl-dir=#{File.dirname lib}\n-----"
         | 
| 61 | 
            +
                $LDFLAGS << " -L#{lib}"
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            # Homebrew OpenSSL on MacOS
         | 
| 64 | 
            +
            elsif RUBY_PLATFORM =~ /darwin/ && system('command -v brew')
         | 
| 65 | 
            +
              openssl_location = `brew --prefix openssl`.strip
         | 
| 66 | 
            +
              $LDFLAGS << " -L#{openssl_location}/lib" if openssl_location
         | 
| 67 | 
            +
            end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            ### Find MySQL client library
         | 
| 43 70 |  | 
| 44 71 | 
             
            # borrowed from mysqlplus
         | 
| 45 72 | 
             
            # http://github.com/oldmoe/mysqlplus/blob/master/ext/extconf.rb
         | 
| @@ -48,6 +75,7 @@ dirs = ENV.fetch('PATH').split(File::PATH_SEPARATOR) + %w[ | |
| 48 75 | 
             
              /opt/local
         | 
| 49 76 | 
             
              /opt/local/mysql
         | 
| 50 77 | 
             
              /opt/local/lib/mysql5*
         | 
| 78 | 
            +
              /opt/homebrew/opt/mysql*
         | 
| 51 79 | 
             
              /usr
         | 
| 52 80 | 
             
              /usr/mysql
         | 
| 53 81 | 
             
              /usr/local
         | 
| @@ -136,10 +164,16 @@ have_const('MYSQL_OPTION_MULTI_STATEMENTS_OFF', mysql_h) | |
| 136 164 | 
             
            # to retain compatibility with the typedef in earlier MySQLs.
         | 
| 137 165 | 
             
            have_type('my_bool', mysql_h)
         | 
| 138 166 |  | 
| 167 | 
            +
            # detect mysql functions
         | 
| 168 | 
            +
            have_func('mysql_ssl_set', mysql_h)
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            ### Compiler flags to help catch errors
         | 
| 171 | 
            +
             | 
| 139 172 | 
             
            # This is our wishlist. We use whichever flags work on the host.
         | 
| 140 173 | 
             
            # -Wall and -Wextra are included by default.
         | 
| 141 174 | 
             
            wishlist = [
         | 
| 142 175 | 
             
              '-Weverything',
         | 
| 176 | 
            +
              '-Wno-compound-token-split-by-macro', # Fixed in Ruby 2.7+ at https://bugs.ruby-lang.org/issues/17865
         | 
| 143 177 | 
             
              '-Wno-bad-function-cast', # rb_thread_call_without_gvl returns void * that we cast to VALUE
         | 
| 144 178 | 
             
              '-Wno-conditional-uninitialized', # false positive in client.c
         | 
| 145 179 | 
             
              '-Wno-covered-switch-default', # result.c -- enum_field_types (when fully covered, e.g. mysql 5.5)
         | 
| @@ -164,6 +198,8 @@ end | |
| 164 198 |  | 
| 165 199 | 
             
            $CFLAGS << ' ' << usable_flags.join(' ')
         | 
| 166 200 |  | 
| 201 | 
            +
            ### Sanitizers to help with debugging -- many are available on both Clang/LLVM and GCC
         | 
| 202 | 
            +
             | 
| 167 203 | 
             
            enabled_sanitizers = disabled_sanitizers = []
         | 
| 168 204 | 
             
            # Specify a comma-separated list of sanitizers, or try them all by default
         | 
| 169 205 | 
             
            sanitizers = with_config('sanitize')
         | 
| @@ -181,7 +217,7 @@ when String | |
| 181 217 | 
             
              end
         | 
| 182 218 | 
             
            end
         | 
| 183 219 |  | 
| 184 | 
            -
            unless disabled_sanitizers.empty?
         | 
| 220 | 
            +
            unless disabled_sanitizers.empty? # rubocop:disable Style/IfUnlessModifier
         | 
| 185 221 | 
             
              abort "-----\nCould not enable requested sanitizers: #{disabled_sanitizers.join(',')}\n-----"
         | 
| 186 222 | 
             
            end
         | 
| 187 223 |  | 
| @@ -198,6 +234,8 @@ unless enabled_sanitizers.empty? | |
| 198 234 | 
             
              $CFLAGS << ' -g -fno-omit-frame-pointer'
         | 
| 199 235 | 
             
            end
         | 
| 200 236 |  | 
| 237 | 
            +
            ### Find MySQL Client on Windows, set RPATH to find the library at runtime
         | 
| 238 | 
            +
             | 
| 201 239 | 
             
            if RUBY_PLATFORM =~ /mswin|mingw/ && !defined?(RubyInstaller)
         | 
| 202 240 | 
             
              # Build libmysql.a interface link library
         | 
| 203 241 | 
             
              require 'rake'
         | 
    
        data/ext/mysql2/mysql2_ext.h
    CHANGED
    
    | @@ -36,6 +36,19 @@ void Init_mysql2(void); | |
| 36 36 | 
             
            typedef bool my_bool;
         | 
| 37 37 | 
             
            #endif
         | 
| 38 38 |  | 
| 39 | 
            +
            // ruby 2.7+
         | 
| 40 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 41 | 
            +
            #define rb_mysql2_gc_location(ptr) ptr = rb_gc_location(ptr)
         | 
| 42 | 
            +
            #else
         | 
| 43 | 
            +
            #define rb_gc_mark_movable(ptr) rb_gc_mark(ptr)
         | 
| 44 | 
            +
            #define rb_mysql2_gc_location(ptr)
         | 
| 45 | 
            +
            #endif
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            // ruby 2.2+
         | 
| 48 | 
            +
            #ifdef TypedData_Make_Struct
         | 
| 49 | 
            +
            #define NEW_TYPEDDATA_WRAPPER 1
         | 
| 50 | 
            +
            #endif
         | 
| 51 | 
            +
             | 
| 39 52 | 
             
            #include <client.h>
         | 
| 40 53 | 
             
            #include <statement.h>
         | 
| 41 54 | 
             
            #include <result.h>
         | 
| @@ -51,7 +51,7 @@ mysql2_mysql_enc_name_to_rb_hash (str, len) | |
| 51 51 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
         | 
| 52 52 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
         | 
| 53 53 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 15,  5,
         | 
| 54 | 
            -
                   0,  | 
| 54 | 
            +
                   0, 30,  5, 25, 40, 10, 20, 50, 74, 74,
         | 
| 55 55 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
         | 
| 56 56 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
         | 
| 57 57 | 
             
                  74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
         | 
| @@ -89,7 +89,7 @@ mysql2_mysql_enc_name_to_rb (str, len) | |
| 89 89 | 
             
            {
         | 
| 90 90 | 
             
              enum
         | 
| 91 91 | 
             
                {
         | 
| 92 | 
            -
                  TOTAL_KEYWORDS =  | 
| 92 | 
            +
                  TOTAL_KEYWORDS = 42,
         | 
| 93 93 | 
             
                  MIN_WORD_LENGTH = 3,
         | 
| 94 94 | 
             
                  MAX_WORD_LENGTH = 8,
         | 
| 95 95 | 
             
                  MIN_HASH_VALUE = 3,
         | 
| @@ -133,7 +133,8 @@ mysql2_mysql_enc_name_to_rb (str, len) | |
| 133 133 | 
             
                  {"big5", "Big5"},
         | 
| 134 134 | 
             
                  {"euckr", "EUC-KR"},
         | 
| 135 135 | 
             
                  {"latin2", "ISO-8859-2"},
         | 
| 136 | 
            -
                  {"" | 
| 136 | 
            +
                  {"utf8mb3", "UTF-8"},
         | 
| 137 | 
            +
                  {""},
         | 
| 137 138 | 
             
                  {"dec8", NULL},
         | 
| 138 139 | 
             
                  {"cp850", "CP850"},
         | 
| 139 140 | 
             
                  {"latin1", "ISO-8859-1"},
         | 
| @@ -306,5 +306,20 @@ static const char *mysql2_mysql_enc_to_rb[] = { | |
| 306 306 | 
             
              "UTF-8",
         | 
| 307 307 | 
             
              "UTF-8",
         | 
| 308 308 | 
             
              "UTF-8",
         | 
| 309 | 
            +
              "UTF-8",
         | 
| 310 | 
            +
              "UTF-8",
         | 
| 311 | 
            +
              "UTF-8",
         | 
| 312 | 
            +
              "UTF-8",
         | 
| 313 | 
            +
              "UTF-8",
         | 
| 314 | 
            +
              "UTF-8",
         | 
| 315 | 
            +
              "UTF-8",
         | 
| 316 | 
            +
              "UTF-8",
         | 
| 317 | 
            +
              "UTF-8",
         | 
| 318 | 
            +
              "UTF-8",
         | 
| 319 | 
            +
              "UTF-8",
         | 
| 320 | 
            +
              "UTF-8",
         | 
| 321 | 
            +
              "UTF-8",
         | 
| 322 | 
            +
              "UTF-8",
         | 
| 323 | 
            +
              "UTF-8",
         | 
| 309 324 | 
             
              "UTF-8"
         | 
| 310 325 | 
             
            };
         | 
    
        data/ext/mysql2/result.c
    CHANGED
    
    | @@ -31,9 +31,13 @@ static rb_encoding *binaryEncoding; | |
| 31 31 | 
             
            #define MYSQL_TYPE_JSON 245
         | 
| 32 32 | 
             
            #endif
         | 
| 33 33 |  | 
| 34 | 
            +
            #ifndef NEW_TYPEDDATA_WRAPPER
         | 
| 35 | 
            +
            #define TypedData_Get_Struct(obj, type, ignore, sval) Data_Get_Struct(obj, type, sval)
         | 
| 36 | 
            +
            #endif
         | 
| 37 | 
            +
             | 
| 34 38 | 
             
            #define GET_RESULT(self) \
         | 
| 35 39 | 
             
              mysql2_result_wrapper *wrapper; \
         | 
| 36 | 
            -
               | 
| 40 | 
            +
              TypedData_Get_Struct(self, mysql2_result_wrapper, &rb_mysql_result_type, wrapper);
         | 
| 37 41 |  | 
| 38 42 | 
             
            typedef struct {
         | 
| 39 43 | 
             
              int symbolizeKeys;
         | 
| @@ -61,11 +65,11 @@ static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone, | |
| 61 65 | 
             
            static void rb_mysql_result_mark(void * wrapper) {
         | 
| 62 66 | 
             
              mysql2_result_wrapper * w = wrapper;
         | 
| 63 67 | 
             
              if (w) {
         | 
| 64 | 
            -
                 | 
| 65 | 
            -
                 | 
| 66 | 
            -
                 | 
| 67 | 
            -
                 | 
| 68 | 
            -
                 | 
| 68 | 
            +
                rb_gc_mark_movable(w->fields);
         | 
| 69 | 
            +
                rb_gc_mark_movable(w->rows);
         | 
| 70 | 
            +
                rb_gc_mark_movable(w->encoding);
         | 
| 71 | 
            +
                rb_gc_mark_movable(w->client);
         | 
| 72 | 
            +
                rb_gc_mark_movable(w->statement);
         | 
| 69 73 | 
             
              }
         | 
| 70 74 | 
             
            }
         | 
| 71 75 |  | 
| @@ -127,6 +131,48 @@ static void rb_mysql_result_free(void *ptr) { | |
| 127 131 | 
             
              xfree(wrapper);
         | 
| 128 132 | 
             
            }
         | 
| 129 133 |  | 
| 134 | 
            +
            static size_t rb_mysql_result_memsize(const void * wrapper) {
         | 
| 135 | 
            +
              const mysql2_result_wrapper * w = wrapper;
         | 
| 136 | 
            +
              size_t memsize = sizeof(*w);
         | 
| 137 | 
            +
              if (w->stmt_wrapper) {
         | 
| 138 | 
            +
                memsize += sizeof(*w->stmt_wrapper);
         | 
| 139 | 
            +
              }
         | 
| 140 | 
            +
              if (w->client_wrapper) {
         | 
| 141 | 
            +
                memsize += sizeof(*w->client_wrapper);
         | 
| 142 | 
            +
              }
         | 
| 143 | 
            +
              return memsize;
         | 
| 144 | 
            +
            }
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 147 | 
            +
            static void rb_mysql_result_compact(void * wrapper) {
         | 
| 148 | 
            +
              mysql2_result_wrapper * w = wrapper;
         | 
| 149 | 
            +
              if (w) {
         | 
| 150 | 
            +
                rb_mysql2_gc_location(w->fields);
         | 
| 151 | 
            +
                rb_mysql2_gc_location(w->rows);
         | 
| 152 | 
            +
                rb_mysql2_gc_location(w->encoding);
         | 
| 153 | 
            +
                rb_mysql2_gc_location(w->client);
         | 
| 154 | 
            +
                rb_mysql2_gc_location(w->statement);
         | 
| 155 | 
            +
              }
         | 
| 156 | 
            +
            }
         | 
| 157 | 
            +
            #endif
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            static const rb_data_type_t rb_mysql_result_type = {
         | 
| 160 | 
            +
              "rb_mysql_result",
         | 
| 161 | 
            +
              {
         | 
| 162 | 
            +
                rb_mysql_result_mark,
         | 
| 163 | 
            +
                rb_mysql_result_free,
         | 
| 164 | 
            +
                rb_mysql_result_memsize,
         | 
| 165 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 166 | 
            +
                rb_mysql_result_compact,
         | 
| 167 | 
            +
            #endif
         | 
| 168 | 
            +
              },
         | 
| 169 | 
            +
              0,
         | 
| 170 | 
            +
              0,
         | 
| 171 | 
            +
            #ifdef RUBY_TYPED_FREE_IMMEDIATELY
         | 
| 172 | 
            +
              RUBY_TYPED_FREE_IMMEDIATELY,
         | 
| 173 | 
            +
            #endif
         | 
| 174 | 
            +
            };
         | 
| 175 | 
            +
             | 
| 130 176 | 
             
            static VALUE rb_mysql_result_free_(VALUE self) {
         | 
| 131 177 | 
             
              GET_RESULT(self);
         | 
| 132 178 | 
             
              rb_mysql_result_free_result(wrapper);
         | 
| @@ -365,7 +411,7 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e | |
| 365 411 | 
             
                int enc_index;
         | 
| 366 412 |  | 
| 367 413 | 
             
                enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
         | 
| 368 | 
            -
             | 
| 414 | 
            +
             | 
| 369 415 | 
             
                if (enc_name != NULL) {
         | 
| 370 416 | 
             
                  /* use the field encoding we were able to match */
         | 
| 371 417 | 
             
                  enc_index = rb_enc_find_index(enc_name);
         | 
| @@ -1129,7 +1175,11 @@ VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_ | |
| 1129 1175 | 
             
              VALUE obj;
         | 
| 1130 1176 | 
             
              mysql2_result_wrapper * wrapper;
         | 
| 1131 1177 |  | 
| 1178 | 
            +
            #ifdef NEW_TYPEDDATA_WRAPPER
         | 
| 1179 | 
            +
              obj = TypedData_Make_Struct(cMysql2Result, mysql2_result_wrapper, &rb_mysql_result_type, wrapper);
         | 
| 1180 | 
            +
            #else
         | 
| 1132 1181 | 
             
              obj = Data_Make_Struct(cMysql2Result, mysql2_result_wrapper, rb_mysql_result_mark, rb_mysql_result_free, wrapper);
         | 
| 1182 | 
            +
            #endif
         | 
| 1133 1183 | 
             
              wrapper->numberOfFields = 0;
         | 
| 1134 1184 | 
             
              wrapper->numberOfRows = 0;
         | 
| 1135 1185 | 
             
              wrapper->lastRowProcessed = 0;
         | 
| @@ -1176,7 +1226,7 @@ void init_mysql2_result() { | |
| 1176 1226 | 
             
              cMysql2Result = rb_define_class_under(mMysql2, "Result", rb_cObject);
         | 
| 1177 1227 | 
             
              rb_undef_alloc_func(cMysql2Result);
         | 
| 1178 1228 | 
             
              rb_global_variable(&cMysql2Result);
         | 
| 1179 | 
            -
             | 
| 1229 | 
            +
             | 
| 1180 1230 | 
             
              rb_define_method(cMysql2Result, "each", rb_mysql_result_each, -1);
         | 
| 1181 1231 | 
             
              rb_define_method(cMysql2Result, "fields", rb_mysql_result_fetch_fields, 0);
         | 
| 1182 1232 | 
             
              rb_define_method(cMysql2Result, "field_types", rb_mysql_result_fetch_field_types, 0);
         | 
    
        data/ext/mysql2/statement.c
    CHANGED
    
    | @@ -6,9 +6,13 @@ static VALUE sym_stream, intern_new_with_args, intern_each, intern_to_s, intern_ | |
| 6 6 | 
             
            static VALUE intern_sec_fraction, intern_usec, intern_sec, intern_min, intern_hour, intern_day, intern_month, intern_year,
         | 
| 7 7 | 
             
              intern_query_options;
         | 
| 8 8 |  | 
| 9 | 
            +
            #ifndef NEW_TYPEDDATA_WRAPPER
         | 
| 10 | 
            +
            #define TypedData_Get_Struct(obj, type, ignore, sval) Data_Get_Struct(obj, type, sval)
         | 
| 11 | 
            +
            #endif
         | 
| 12 | 
            +
             | 
| 9 13 | 
             
            #define GET_STATEMENT(self) \
         | 
| 10 14 | 
             
              mysql_stmt_wrapper *stmt_wrapper; \
         | 
| 11 | 
            -
               | 
| 15 | 
            +
              TypedData_Get_Struct(self, mysql_stmt_wrapper, &rb_mysql_statement_type, stmt_wrapper); \
         | 
| 12 16 | 
             
              if (!stmt_wrapper->stmt) { rb_raise(cMysql2Error, "Invalid statement handle"); } \
         | 
| 13 17 | 
             
              if (stmt_wrapper->closed) { rb_raise(cMysql2Error, "Statement handle already closed"); }
         | 
| 14 18 |  | 
| @@ -16,9 +20,45 @@ static void rb_mysql_stmt_mark(void * ptr) { | |
| 16 20 | 
             
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 17 21 | 
             
              if (!stmt_wrapper) return;
         | 
| 18 22 |  | 
| 19 | 
            -
               | 
| 23 | 
            +
              rb_gc_mark_movable(stmt_wrapper->client);
         | 
| 24 | 
            +
            }
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            static void rb_mysql_stmt_free(void *ptr) {
         | 
| 27 | 
            +
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 28 | 
            +
              decr_mysql2_stmt(stmt_wrapper);
         | 
| 29 | 
            +
            }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            static size_t rb_mysql_stmt_memsize(const void * ptr) {
         | 
| 32 | 
            +
              const mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 33 | 
            +
              return sizeof(*stmt_wrapper);
         | 
| 20 34 | 
             
            }
         | 
| 21 35 |  | 
| 36 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 37 | 
            +
            static void rb_mysql_stmt_compact(void * ptr) {
         | 
| 38 | 
            +
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 39 | 
            +
              if (!stmt_wrapper) return;
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              rb_mysql2_gc_location(stmt_wrapper->client);
         | 
| 42 | 
            +
            }
         | 
| 43 | 
            +
            #endif
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            static const rb_data_type_t rb_mysql_statement_type = {
         | 
| 46 | 
            +
              "rb_mysql_statement",
         | 
| 47 | 
            +
              {
         | 
| 48 | 
            +
                rb_mysql_stmt_mark,
         | 
| 49 | 
            +
                rb_mysql_stmt_free,
         | 
| 50 | 
            +
                rb_mysql_stmt_memsize,
         | 
| 51 | 
            +
            #ifdef HAVE_RB_GC_MARK_MOVABLE
         | 
| 52 | 
            +
                rb_mysql_stmt_compact,
         | 
| 53 | 
            +
            #endif
         | 
| 54 | 
            +
              },
         | 
| 55 | 
            +
              0,
         | 
| 56 | 
            +
              0,
         | 
| 57 | 
            +
            #ifdef RUBY_TYPED_FREE_IMMEDIATELY
         | 
| 58 | 
            +
              RUBY_TYPED_FREE_IMMEDIATELY,
         | 
| 59 | 
            +
            #endif
         | 
| 60 | 
            +
            };
         | 
| 61 | 
            +
             | 
| 22 62 | 
             
            static void *nogvl_stmt_close(void *ptr) {
         | 
| 23 63 | 
             
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 24 64 | 
             
              if (stmt_wrapper->stmt) {
         | 
| @@ -28,11 +68,6 @@ static void *nogvl_stmt_close(void *ptr) { | |
| 28 68 | 
             
              return NULL;
         | 
| 29 69 | 
             
            }
         | 
| 30 70 |  | 
| 31 | 
            -
            static void rb_mysql_stmt_free(void *ptr) {
         | 
| 32 | 
            -
              mysql_stmt_wrapper *stmt_wrapper = ptr;
         | 
| 33 | 
            -
              decr_mysql2_stmt(stmt_wrapper);
         | 
| 34 | 
            -
            }
         | 
| 35 | 
            -
             | 
| 36 71 | 
             
            void decr_mysql2_stmt(mysql_stmt_wrapper *stmt_wrapper) {
         | 
| 37 72 | 
             
              stmt_wrapper->refcount--;
         | 
| 38 73 |  | 
| @@ -96,7 +131,11 @@ VALUE rb_mysql_stmt_new(VALUE rb_client, VALUE sql) { | |
| 96 131 |  | 
| 97 132 | 
             
              Check_Type(sql, T_STRING);
         | 
| 98 133 |  | 
| 134 | 
            +
            #ifdef NEW_TYPEDDATA_WRAPPER
         | 
| 135 | 
            +
              rb_stmt = TypedData_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, &rb_mysql_statement_type, stmt_wrapper);
         | 
| 136 | 
            +
            #else
         | 
| 99 137 | 
             
              rb_stmt = Data_Make_Struct(cMysql2Statement, mysql_stmt_wrapper, rb_mysql_stmt_mark, rb_mysql_stmt_free, stmt_wrapper);
         | 
| 138 | 
            +
            #endif
         | 
| 100 139 | 
             
              {
         | 
| 101 140 | 
             
                stmt_wrapper->client = rb_client;
         | 
| 102 141 | 
             
                stmt_wrapper->refcount = 1;
         | 
| @@ -448,7 +487,7 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) { | |
| 448 487 | 
             
              if (metadata == NULL) {
         | 
| 449 488 | 
             
                if (mysql_stmt_errno(stmt) != 0) {
         | 
| 450 489 | 
             
                  // either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
         | 
| 451 | 
            -
                  wrapper-> | 
| 490 | 
            +
                  wrapper->active_fiber = Qnil;
         | 
| 452 491 | 
             
                  rb_raise_mysql2_stmt_error(stmt_wrapper);
         | 
| 453 492 | 
             
                }
         | 
| 454 493 | 
             
                // no data and no error, so query was not a SELECT
         | 
| @@ -461,7 +500,7 @@ static VALUE rb_mysql_stmt_execute(int argc, VALUE *argv, VALUE self) { | |
| 461 500 | 
             
                  mysql_free_result(metadata);
         | 
| 462 501 | 
             
                  rb_raise_mysql2_stmt_error(stmt_wrapper);
         | 
| 463 502 | 
             
                }
         | 
| 464 | 
            -
                wrapper-> | 
| 503 | 
            +
                wrapper->active_fiber = Qnil;
         | 
| 465 504 | 
             
              }
         | 
| 466 505 |  | 
| 467 506 | 
             
              resultObj = rb_mysql_result_to_obj(stmt_wrapper->client, wrapper->encoding, current, metadata, self);
         | 
| @@ -502,7 +541,7 @@ static VALUE rb_mysql_stmt_fields(VALUE self) { | |
| 502 541 | 
             
              if (metadata == NULL) {
         | 
| 503 542 | 
             
                if (mysql_stmt_errno(stmt) != 0) {
         | 
| 504 543 | 
             
                  // either CR_OUT_OF_MEMORY or CR_UNKNOWN_ERROR. both fatal.
         | 
| 505 | 
            -
                  wrapper-> | 
| 544 | 
            +
                  wrapper->active_fiber = Qnil;
         | 
| 506 545 | 
             
                  rb_raise_mysql2_stmt_error(stmt_wrapper);
         | 
| 507 546 | 
             
                }
         | 
| 508 547 | 
             
                // no data and no error, so query was not a SELECT
         | 
    
        data/lib/mysql2/client.rb
    CHANGED
    
    | @@ -20,6 +20,7 @@ module Mysql2 | |
| 20 20 |  | 
| 21 21 | 
             
                def initialize(opts = {})
         | 
| 22 22 | 
             
                  raise Mysql2::Error, "Options parameter must be a Hash" unless opts.is_a? Hash
         | 
| 23 | 
            +
             | 
| 23 24 | 
             
                  opts = Mysql2::Util.key_hash_as_symbols(opts)
         | 
| 24 25 | 
             
                  @read_timeout = nil
         | 
| 25 26 | 
             
                  @query_options = self.class.default_query_options.dup
         | 
| @@ -33,6 +34,7 @@ module Mysql2 | |
| 33 34 | 
             
                  # TODO: stricter validation rather than silent massaging
         | 
| 34 35 | 
             
                  %i[reconnect connect_timeout local_infile read_timeout write_timeout default_file default_group secure_auth init_command automatic_close enable_cleartext_plugin default_auth].each do |key|
         | 
| 35 36 | 
             
                    next unless opts.key?(key)
         | 
| 37 | 
            +
             | 
| 36 38 | 
             
                    case key
         | 
| 37 39 | 
             
                    when :reconnect, :local_infile, :secure_auth, :automatic_close, :enable_cleartext_plugin
         | 
| 38 40 | 
             
                      send(:"#{key}=", !!opts[key]) # rubocop:disable Style/DoubleNegation
         | 
| @@ -136,6 +138,7 @@ module Mysql2 | |
| 136 138 | 
             
                # and performance_schema.session_account_connect_attrs
         | 
| 137 139 | 
             
                def parse_connect_attrs(conn_attrs)
         | 
| 138 140 | 
             
                  return {} if Mysql2::Client::CONNECT_ATTRS.zero?
         | 
| 141 | 
            +
             | 
| 139 142 | 
             
                  conn_attrs ||= {}
         | 
| 140 143 | 
             
                  conn_attrs[:program_name] ||= $PROGRAM_NAME
         | 
| 141 144 | 
             
                  conn_attrs.each_with_object({}) do |(key, value), hash|
         | 
| @@ -152,6 +155,7 @@ module Mysql2 | |
| 152 155 | 
             
                def query_info
         | 
| 153 156 | 
             
                  info = query_info_string
         | 
| 154 157 | 
             
                  return {} unless info
         | 
| 158 | 
            +
             | 
| 155 159 | 
             
                  info_hash = {}
         | 
| 156 160 | 
             
                  info.split.each_slice(2) { |s| info_hash[s[0].downcase.delete(':').to_sym] = s[1].to_i }
         | 
| 157 161 | 
             
                  info_hash
         | 
    
        data/lib/mysql2/version.rb
    CHANGED
    
    
    
        data/lib/mysql2.rb
    CHANGED
    
    
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            -----BEGIN PGP PUBLIC KEY BLOCK-----
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            xsFNBFb8EKsBEADwGmleOSVThrbCyCVUdCreMTKpmD5p5aPz/0jc66050MAb71Hv
         | 
| 4 | 
            +
            TVcfuMqHYO8O66qXLpEdqZpuk4D+rw1oKyC+d8uPD2PSHRqBXnR0Qf+LVTZvtO92
         | 
| 5 | 
            +
            3R7pYnC2x6V6iVGpKQYFP8cwh2B1qgIa+9y/N8cQIqfD+0ghyiUjjTYek3YFBnqa
         | 
| 6 | 
            +
            L/2h2V0Mt0DkBrDK80LqEY10PAFDfJjINAW9XNHZzi2KqUx5w1z8rItokXV6fYE5
         | 
| 7 | 
            +
            ItyGMR6WVajJg5D4VCiZd0ymuQP2bGkrRbl6FH5vofVSkahKMJeHs2lbvMvNyS3c
         | 
| 8 | 
            +
            n8vxoBvbbcwSAV1gvB1uzXXxv0kdkFZjhU1Tss4+Dak8qeEmIrC5qYycLxIdVEhT
         | 
| 9 | 
            +
            Z8N8+P7Dll+QGOZKu9+OzhQ+byzpLFhUHKys53eXo/HrfWtw3DdP21yyb5P3QcgF
         | 
| 10 | 
            +
            scxfZHzZtFNUL6XaVnauZM2lqquUW+lMNdKKGCBJ6co4QxjocsxfISyarcFj6ZR0
         | 
| 11 | 
            +
            5Hf6VU3Y7AyuFZdL0SQWPv9BSu/swBOimrSiiVHbtE49Nx1x/d1wn1peYl07WRUv
         | 
| 12 | 
            +
            C10eF36ZoqEuSGmDz59mWlwB3daIYAsAAiBwgcmN7aSB8XD4ZPUVSEZvwSm/IwuS
         | 
| 13 | 
            +
            Rkpde+kIhTLjyv5bRGqU2P/Mi56dB4VFmMJaF26CiRXatxhXOAIAF9dXCwARAQAB
         | 
| 14 | 
            +
            zS1NYXJpYURCIFNpZ25pbmcgS2V5IDxzaWduaW5nLWtleUBtYXJpYWRiLm9yZz7C
         | 
| 15 | 
            +
            wXgEEwEIACIFAlb8EKsCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPFl
         | 
| 16 | 
            +
            byTHTNHYJZ0P/2Z2RURRkSTHLKZ/GqSvPReReeB7AI+ZrDapkpG/26xp1Yw1isCO
         | 
| 17 | 
            +
            y99pvQ7hjTFhdZQ7xSRUiT/e27wJxR7s4G/ck5VOVjuJzGnByNLmwMjdN1ONIO9P
         | 
| 18 | 
            +
            hQAs2iF3uoIbVTxzXof2F8C0WSbKgEWbtqlCWlaapDpN8jKAWdsQsNMdXcdpJ2os
         | 
| 19 | 
            +
            WiacQRxLREBGjVRkAiqdjYkegQ4BZ0GtPULKjZWCUNkaat51b7O7V19nSy/T7MM7
         | 
| 20 | 
            +
            n+kqYQLMIHCF8LGd3QQsNppRnolWVRzXMdtR2+9iI21qv6gtHcMiAg6QcKA7halL
         | 
| 21 | 
            +
            kCdIS2nWR8g7nZeZjq5XhckeNGrGX/3w/m/lwczYjMUer+qs2ww5expZJ7qhtSta
         | 
| 22 | 
            +
            lE3EtL/l7zE4RlknqwDZ0IXtxCNPu2UovCzZmdZm8UWfMSKk/3VgL8HgzYRr8fo0
         | 
| 23 | 
            +
            yj0XkckJ7snXvuhoviW2tjm46PyHPWRKgW4iEzUrB+hiXpy3ikt4rLRg/iMqKjyf
         | 
| 24 | 
            +
            mvcE/VdmFVtsfbfRVvlaWiIWCndRTVBkAaTu8DwrGyugQsbjEcK+4E25/SaKIJIw
         | 
| 25 | 
            +
            qfxpyBVhru21ypgEMAw1Y8KC7KntB7jzpFotE4wpv1jZKUZuy71ofr7g3/2O+7nW
         | 
| 26 | 
            +
            LrR1mncbuT6yXo316r56dfKzOxQJBnYFwTjXfa65yBArjQBUCPNYOKr0wkYEEhEI
         | 
| 27 | 
            +
            AAYFAlb8JFYACgkQy8sIKhu5Q9snYACgh3id41CYTHELOQ/ymj4tiuFt1lcAn3JU
         | 
| 28 | 
            +
            9wH3pihM9ISvoeuGnwwHhcKnwsFcBBIBCAAGBQJW/CSEAAoJEJFxGJmV5Fqe11cP
         | 
| 29 | 
            +
            /A3QhvqleuRaXoS5apIY3lrDL79Wo0bkydM3u2Ft9EqVVG5zZvlmWaXbw5wkPhza
         | 
| 30 | 
            +
            7YUjrD7ylaE754lHI48jJp3KY7RosClY/Kuk56GJI/SoMKx4v518pAboZ4hjY9MY
         | 
| 31 | 
            +
            gmiAuZEYx5Ibv1pj0+hkzRI78+f6+d5QTQ6y/35ZjSSJcBgCMAr/JRsmOkHu6cY6
         | 
| 32 | 
            +
            qOpq4g8mvRAX5ivRm4UxE2gnxZyd2LjY2/S2kCZvHWVaZuiTD0EU1jYPoOo6fhc8
         | 
| 33 | 
            +
            zjs5FWS56C1vp7aFOGBvsH3lwYAYi1K2S+/B4nqpitYJz/T0zFzzyYe7ZG77DXKD
         | 
| 34 | 
            +
            /XajD22IzRGKjoeVPFBx+2V0YCCpWZkqkfZ2Dt3QVW//QIpVsOJnmaqolDg1sxoa
         | 
| 35 | 
            +
            BEYBtCtovU0wh1pXWwfn7IgjIkPNl0AU8mW8Ll91WF+Lss/oMrUJMKVDenTJ6/ZO
         | 
| 36 | 
            +
            06c+JFlP7dS3YGMsifwgy5abA4Xy4GWpAsyEM68mqsJUc7ZANZcQAKr6+DryzSfI
         | 
| 37 | 
            +
            Olsn3kJzOtb/c3JhVmblEO6XzdfZJK/axPOp3mF1oEBoJ56fGwO2usgVwQDyLt3J
         | 
| 38 | 
            +
            iluJrCvMSBL9KtBZWrTZH5t3rTMN0NUALy4Etd6Y8V94i8c5NixMDyjRU7aKJAAw
         | 
| 39 | 
            +
            tUvxLd12dqtaXsuvGyzLbR4EDT/Q5DfLC1DZWpgtUtCVwsFcBBIBCAAGBQJW/CS2
         | 
| 40 | 
            +
            AAoJEEHdwLQNpW8iMUoP/AjFKyZ+inQTI2jJJBBtrLjxaxZSG5ggCovowWn8NWv6
         | 
| 41 | 
            +
            bQBm2VurYVKhvY1xUyxoLY8KN+MvoeTdpB3u7z+M6x+CdfoTGqWQ2yapOC0eEJBF
         | 
| 42 | 
            +
            O+GFho2WE0msiO0IaVJrzdFTPE0EYR2BHziLu0DDSZADe1WYEqkkrZsCNgi6EMng
         | 
| 43 | 
            +
            mX2h+DK2GlC3W2tY9sc63DsgzjcMBO9uYmpHj6nizsIrETqouVNUCLT0t8iETa25
         | 
| 44 | 
            +
            Mehq/I92I70Qfebv7R4eMrs+tWXKyPU0OjV+8b8saZsv1xn98UkeXwYx4JI04OTw
         | 
| 45 | 
            +
            nBeJG8yPrGDBO5iucmtaCvwGQ3c76qBivrA8eFz3azRxQYWWiFrkElTg+C/E83JQ
         | 
| 46 | 
            +
            WgqPvPZkI5UHvBwBqcoIXG15AJoXA/ZWIB8nPKWKaV5KDnY3DBuA4rh5Mhy3xwcC
         | 
| 47 | 
            +
            /22E/CmZMXjUUvDnlPgXCYAYU0FBbGk7JpSYawtNfdAN2XBRPq5sDKLLxftx7D8u
         | 
| 48 | 
            +
            ESJXXAlPxoRh7x1ArdGM+EowlJJ0xpINBaT0Z/Hk0jxNIFEak796/WeGqewdOIki
         | 
| 49 | 
            +
            dAs4tppUfzosla5K+qXfWwmhcKmpwA4oynE8wIaoXptoi8+rxaw4N6wAXlSrVxeC
         | 
| 50 | 
            +
            VTnb7+UY/BT2Wx6IQ10C9jrsj6XIffMvngIinCD9Czvadmr7BEIxKt1LP+gGA8Zg
         | 
| 51 | 
            +
            wsFcBBIBCgAGBQJYE6oDAAoJEL7YRJ/O6NqIJ24P+QFNa2O+Q1rLKrQiuPw4Q73o
         | 
| 52 | 
            +
            7/blUpFNudZfeCDpDbUgJ01u1RHnWOyLcyknartAosFDJIpgcXY5I8jsBIO5IZPR
         | 
| 53 | 
            +
            C/UKxZB3RYOhj49bySD9RNapHyq+Y56j9JUoz6tkKFBd+6g85Ej8d924xM1UnRCS
         | 
| 54 | 
            +
            9cfI9W0fSunbCi2CXLbXFF7V+m3Ou1SVYGIAxpMn4RXyYfuqeB5wROR2GA5Ef6T3
         | 
| 55 | 
            +
            S5byh1dRSEgnrBToENtp5n7Jwsc9pDofjtaUkO854l45IqFarGjCHZwtNRKd2lcK
         | 
| 56 | 
            +
            FMnd1jS0nfGkUbn3qNJam1qaGWx4gXaT845VsYYVTbxtkKi+qPUIoOyYx4NEm6fC
         | 
| 57 | 
            +
            ZywH72oP+fmUT/fbfSHa5j137dRqokkR6RFjnEMBl6WHwgqqUqeIT6t9uV6WWzX9
         | 
| 58 | 
            +
            lNroZFAFL/de7H31iIRuZcm38DUZOfjVf9glweu4yFvuJ7cQtyQydFQJV4LGDT/C
         | 
| 59 | 
            +
            8e9TWrV1/gWMyMGQlZsRWa+h+FfFUccQtfSdXpvSxtXfop+fVQmJgUUl92jh4K9j
         | 
| 60 | 
            +
            c9a6rIp5v1Q1yEgs2iS50/V/NMSmEcE1XMOxFt9fX9T+XmKAWZ8L25lpILsHT3mB
         | 
| 61 | 
            +
            VWrpHdbawUaiBp9elxhn6tFiTFR7qA7dlUyWrI+MMlINwSZ2AAXvmA2IajH/UIlh
         | 
| 62 | 
            +
            xotxmSNiZYIQ6UbD3fk4wsFzBBABCgAdFiEEmy/52H2krRdju+d2+GQcuhDvLUgF
         | 
| 63 | 
            +
            Ally44wACgkQ+GQcuhDvLUgkjQ//c3mBxfJm6yLAJD4s4OgsPv4pcp/EKmPcdztm
         | 
| 64 | 
            +
            W0/glwopUZmq9oNo3VMMCGtusrQgpACzfUlesu9NWlPCB3olZkeGugygo0zuQBKs
         | 
| 65 | 
            +
            55eG7bPzMLyfSqLKyogYocaGc4lpf4lbvlvxy37YGVrGpwT9i8t2REtM6iPKDcMM
         | 
| 66 | 
            +
            sgVtNlqFdq3Fs2Haqt0m1EksX6/GSIrjK4LZEcPklrGPvUS3S+qkwuaGE/jXxncE
         | 
| 67 | 
            +
            4jFQR9SYH6AHr6Vkt1CG9Dgpr+Ph0I9n0JRknBYoUZ1q51WdF946NplXkCskdzWG
         | 
| 68 | 
            +
            RHgMUCz3ZehF1FzpKgfO9Zd0YZsmivV/g6frUw/TayP9gxKPt7z2Lsxzyh8X7cg6
         | 
| 69 | 
            +
            TAvdG9JbG0PyPJT1TZ8qpjP/PtqPclHsHQQIbGSDFWzRM5znhS+5sgyw8FWInjw8
         | 
| 70 | 
            +
            JjxoOWMa50464EfGeb2jZfwtRimJAJLWEf/JnvO779nXf5YbvUZgfXaX7k/cvCVk
         | 
| 71 | 
            +
            U8M7oC7x8o6F0P2Lh6FgonklKEeIRtZBUNZ0Lk9OShVqlU9/v16MHq/Eyu/Mbs0D
         | 
| 72 | 
            +
            en3vYgiYxOBR8czD1Wh4vsKiGfOzQ6oWti/DCURV+iTYhJc7mSWM6STzUFr0nCnF
         | 
| 73 | 
            +
            x6W0j/zH6ZgiFAGOyIXW2DwfjFvYRcBL1RWAEKsiFwYrNV+MDonjKXjpVB1Ra90o
         | 
| 74 | 
            +
            lLrZXAXCwHMEEgEKAB0WIQRMRw//78TT3Fl3hlXOGj3V48lPSQUCXAAgOgAKCRDO
         | 
| 75 | 
            +
            Gj3V48lPSQxAB/43qoWteVZEiN3JW4FnHg+S60TnHSP69FKV+363XYKDa23pNpv4
         | 
| 76 | 
            +
            tiJumo9Kvb4UoDft766/URHm5RKyPtrxy+wqotamrkGJUTtP2a68h7C31VX+pf6i
         | 
| 77 | 
            +
            iQKmxRQz4zmW0pA5X01+AgpvcDH++Fv5NLBpnjqPdTh5b0gvr89E0zMNldNYOZu1
         | 
| 78 | 
            +
            0H/mukrnGlFDu/osBuy+XJtP2MeasazVMLvjKs+hr//E+iLI9DZOwFBK6AX5gkkI
         | 
| 79 | 
            +
            UEHkSeb4//AHwvanUMin9un9+F9iR+qDuDEKxuevYzM0owuoVcK5pAsRnRQJlnHW
         | 
| 80 | 
            +
            /0BQ6FtNGpmljhvUk8a/l3xFf3z/uJG5vVKVzsFNBFb8EKsBEADDfCMsu2U1CdJh
         | 
| 81 | 
            +
            r4xp6z4J89/tMnpCQASC8DQhtZ6bWG/ksyKt2DnDQ050XBEng+7epzHWA2UgT0li
         | 
| 82 | 
            +
            Y05zZmFs1X7QeZr16B7JANq6fnHOdZB0ThS7JEYbProkMxcqAFLAZJCpZT534Gpz
         | 
| 83 | 
            +
            W7qHwzjV+d13IziCHdi6+DD5eavYzBqY8QzjlOXbmIlY7dJUCwXTECUfirc6kH86
         | 
| 84 | 
            +
            CS8fXZTke4QYZ55VnrOomB4QGqP371kwBETnhlhi74+pvi3jW05Z5x1tVMwuugyz
         | 
| 85 | 
            +
            zkseZp1VYmJq5SHNFZ/pnAQLE9gUDTb6UWcPBwQh9Sw+7ahSK74lJKYm3wktyvZh
         | 
| 86 | 
            +
            zAxbNyzs1M56yeFP6uFwJTBfNByyMAa6TGUhNkxlLcYjxKbVmoAnKCVM8t41TlLv
         | 
| 87 | 
            +
            /a0ki8iQxqvphVLufksR9IpN6d3F15j6GeyVtxBEv04iv4vbuKthWytb+gjX4bI8
         | 
| 88 | 
            +
            CAo9jGHevmtdiw/SbeKx2YBM1MF6eua37rFMooOBj4X7VfQCyS+crNsOQn8nJGah
         | 
| 89 | 
            +
            YbzUDCCgnX+pqN9iZvXisMS79wVyD5DyISFDvT/5jY7IXxPibxr10P/8lfW1d72u
         | 
| 90 | 
            +
            xyI2UiZKZpyHCt4k47yMq4KQGLGuhxJ6q6O3bi2aXRuz8bLqTBLca9dmx9wZFvRh
         | 
| 91 | 
            +
            6jS/SKEg7eFcY0xbb6RVIv1UwGDYfQARAQABwsFfBBgBCAAJBQJW/BCrAhsMAAoJ
         | 
| 92 | 
            +
            EPFlbyTHTNHYEBIQAJhFTh1u34Q+5bnfiM2dAdCr6T6w4Y1v9ePiIYdSImeseJS2
         | 
| 93 | 
            +
            yRglpLcMjW0uEA9KXiRtC/Nm/ClnqYJzCKeIaweHqH6dIgJKaXZFt1Uaia7X9tDD
         | 
| 94 | 
            +
            wqALGu97irUrrV1Kh9IkM0J29Vid5amakrdS4mwt2uEISSnCi7pfVoEro+S7tYQ9
         | 
| 95 | 
            +
            iH6APVIwqWvcaty3cANdwKWfUQZ6a9IQ08xqzaMhMp2VzhVrWkq3B0j2aRoZR7BN
         | 
| 96 | 
            +
            LH2I7Z0giIM8ARjZs99aTRL+SfMEQ3sUxNLb3KWP/n1lSFbrk4HGzqUBBfczESlN
         | 
| 97 | 
            +
            c0970C6znK0H0HD11/3BTkMuPqww+Tzex4dpMQllMEKZ3wEyd9v6ba+nj/P1FHSE
         | 
| 98 | 
            +
            y/VN6IXzd82s1lYOonKTdmXAIROcHnb0QUzwsd/mhB3jKhEDOV2ZcBTD3yHv8m7C
         | 
| 99 | 
            +
            9G9y4hV+7yQlnPlSg3DjBp3SS5r+sOObCIy2Ad32upoXkilWa9g7GZSuhY9kyKqe
         | 
| 100 | 
            +
            Eba1lgXXaQykEeqx0pexkWavNnb9JaPrAZHDjUGcXrREmjEyXyElRoD4CrWXySe4
         | 
| 101 | 
            +
            6jCuNhVVlkLGo7osefynXa/+PNjQjURtx8en7M9A1FkQuRAxE8KIZgZzYxkGl5o5
         | 
| 102 | 
            +
            POSFCA4JUoRPDcrl/sI3fuq2dIOE/BJ2r8dV+LddiR+iukhXRwJXH8RVVEUS
         | 
| 103 | 
            +
            =mCOI
         | 
| 104 | 
            +
            -----END PGP PUBLIC KEY BLOCK-----
         | 
| @@ -33,6 +33,7 @@ mysql_to_rb = { | |
| 33 33 | 
             
              "macroman" => "macRoman",
         | 
| 34 34 | 
             
              "cp852"    => "CP852",
         | 
| 35 35 | 
             
              "latin7"   => "ISO-8859-13",
         | 
| 36 | 
            +
              "utf8mb3"  => "UTF-8",
         | 
| 36 37 | 
             
              "utf8mb4"  => "UTF-8",
         | 
| 37 38 | 
             
              "cp1251"   => "Windows-1251",
         | 
| 38 39 | 
             
              "utf16"    => "UTF-16",
         | 
| @@ -55,7 +56,7 @@ encodings_with_nil = Array.new(encodings.size) | |
| 55 56 | 
             
            collations.each do |collation|
         | 
| 56 57 | 
             
              mysql_col_idx = collation[2].to_i
         | 
| 57 58 | 
             
              rb_enc = mysql_to_rb.fetch(collation[1]) do |mysql_enc|
         | 
| 58 | 
            -
                 | 
| 59 | 
            +
                warn "WARNING: Missing mapping for collation \"#{collation[0]}\" with encoding \"#{mysql_enc}\" and id #{mysql_col_idx}, assuming NULL"
         | 
| 59 60 | 
             
                "NULL"
         | 
| 60 61 | 
             
              end
         | 
| 61 62 | 
             
              encodings[mysql_col_idx - 1] = [mysql_col_idx, rb_enc]
         | 
    
        metadata
    CHANGED
    
    | @@ -1,17 +1,17 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: mysql2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.5. | 
| 4 | 
            +
              version: 0.5.6
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Brian Lopez
         | 
| 8 8 | 
             
            - Aaron Stone
         | 
| 9 | 
            -
            autorequire: | 
| 9 | 
            +
            autorequire:
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date:  | 
| 12 | 
            +
            date: 2024-02-08 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies: []
         | 
| 14 | 
            -
            description: | 
| 14 | 
            +
            description:
         | 
| 15 15 | 
             
            email:
         | 
| 16 16 | 
             
            - seniorlopez@gmail.com
         | 
| 17 17 | 
             
            - aaron@serendipity.cx
         | 
| @@ -48,6 +48,7 @@ files: | |
| 48 48 | 
             
            - lib/mysql2/version.rb
         | 
| 49 49 | 
             
            - support/3A79BD29.asc
         | 
| 50 50 | 
             
            - support/5072E1F5.asc
         | 
| 51 | 
            +
            - support/C74CD1D8.asc
         | 
| 51 52 | 
             
            - support/libmysql.def
         | 
| 52 53 | 
             
            - support/mysql_enc_to_ruby.rb
         | 
| 53 54 | 
             
            - support/ruby_enc_to_mysql.rb
         | 
| @@ -56,12 +57,12 @@ licenses: | |
| 56 57 | 
             
            - MIT
         | 
| 57 58 | 
             
            metadata:
         | 
| 58 59 | 
             
              bug_tracker_uri: https://github.com/brianmario/mysql2/issues
         | 
| 59 | 
            -
              changelog_uri: https://github.com/brianmario/mysql2/releases/tag/0.5. | 
| 60 | 
            -
              documentation_uri: https://www.rubydoc.info/gems/mysql2/0.5. | 
| 60 | 
            +
              changelog_uri: https://github.com/brianmario/mysql2/releases/tag/0.5.6
         | 
| 61 | 
            +
              documentation_uri: https://www.rubydoc.info/gems/mysql2/0.5.6
         | 
| 61 62 | 
             
              homepage_uri: https://github.com/brianmario/mysql2
         | 
| 62 | 
            -
              source_code_uri: https://github.com/brianmario/mysql2/tree/0.5. | 
| 63 | 
            +
              source_code_uri: https://github.com/brianmario/mysql2/tree/0.5.6
         | 
| 63 64 | 
             
              msys2_mingw_dependencies: libmariadbclient
         | 
| 64 | 
            -
            post_install_message: | 
| 65 | 
            +
            post_install_message:
         | 
| 65 66 | 
             
            rdoc_options:
         | 
| 66 67 | 
             
            - "--charset=UTF-8"
         | 
| 67 68 | 
             
            require_paths:
         | 
| @@ -77,8 +78,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 77 78 | 
             
                - !ruby/object:Gem::Version
         | 
| 78 79 | 
             
                  version: '0'
         | 
| 79 80 | 
             
            requirements: []
         | 
| 80 | 
            -
            rubygems_version: 3.0. | 
| 81 | 
            -
            signing_key: | 
| 81 | 
            +
            rubygems_version: 3.6.0.dev
         | 
| 82 | 
            +
            signing_key:
         | 
| 82 83 | 
             
            specification_version: 4
         | 
| 83 84 | 
             
            summary: A simple, fast Mysql library for Ruby, binding to libmysql
         | 
| 84 85 | 
             
            test_files: []
         |