Skip to content

Commit 68092a2

Browse files
authored
Merge pull request #2 from skytap/merge-from-brianmario-2
Merge remote-tracking branch 'brianmario/master'
2 parents c505ea5 + 8399968 commit 68092a2

17 files changed

+200
-66
lines changed

.rubocop.yml

-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ Layout/CaseIndentation:
1515
Layout/IndentHash:
1616
EnforcedStyle: consistent
1717

18-
Layout/IndentHeredoc:
19-
EnforcedStyle: powerpack
20-
2118
Lint/EndAlignment:
2219
EnforcedStyleAlignWith: variable
2320

.rubocop_todo.yml

+10-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,23 @@
66
# Note that changes in the inspected code, or installation of new
77
# versions of RuboCop, may require this file to be generated again.
88

9+
# Offense count: 3
10+
# Cop supports --auto-correct.
11+
# Configuration parameters: EnforcedStyle, SupportedStyles.
12+
# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent
13+
Layout/IndentHeredoc:
14+
Exclude:
15+
- 'support/ruby_enc_to_mysql.rb'
16+
- 'tasks/compile.rake'
17+
918
# Offense count: 2
1019
Metrics/AbcSize:
1120
Max: 90
1221

1322
# Offense count: 31
1423
# Configuration parameters: CountComments, ExcludedMethods.
1524
Metrics/BlockLength:
16-
Max: 825
25+
Max: 850
1726

1827
# Offense count: 1
1928
# Configuration parameters: CountBlocks.

.travis.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ bundler_args: --without benchmarks development
55
# Pin Rubygems to a working version. Sometimes it breaks upstream. Update now and then.
66
before_install:
77
- gem --version
8-
- gem update --system 2.7.3
8+
- gem update --system 2.7.6 --quiet
99
- gem update bundler
1010
- gem --version
1111
- bash .travis_setup.sh
@@ -18,6 +18,7 @@ addons:
1818
- mysql-client-core-5.6
1919
- mysql-client-5.6
2020
rvm:
21+
- 2.6
2122
- 2.5
2223
- 2.4
2324
- 2.3
@@ -45,6 +46,12 @@ matrix:
4546
mariadb: 10.2
4647
hosts:
4748
- mysql2gem.example.com
49+
- rvm: 2.4
50+
env: DB=mariadb10.3
51+
addons:
52+
mariadb: 10.3
53+
hosts:
54+
- mysql2gem.example.com
4855
- rvm: 2.4
4956
env: DB=mysql55
5057
addons:

.travis_mysql55.sh

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ set -eux
55
apt-get purge -qq '^mysql*' '^libmysql*'
66
rm -fr /etc/mysql
77
rm -fr /var/lib/mysql
8+
apt-get update -qq
89
apt-get install -qq mysql-server-5.5 mysql-client-core-5.5 mysql-client-5.5 libmysqlclient-dev

README.md

+12-7
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,11 @@ To see line numbers in backtraces, declare these environment variables
7474

7575
### Linux and other Unixes
7676

77-
You may need to install a package such as `libmysqlclient-dev` or `mysql-devel`;
78-
refer to your distribution's package guide to find the particular package.
79-
The most common issue we see is a user who has the library file `libmysqlclient.so` but is
80-
missing the header file `mysql.h` -- double check that you have the _-dev_ packages installed.
77+
You may need to install a package such as `libmysqlclient-dev`, `mysql-devel`,
78+
or `default-libmysqlclient-dev`; refer to your distribution's package guide to
79+
find the particular package. The most common issue we see is a user who has
80+
the library file `libmysqlclient.so` but is missing the header file `mysql.h`
81+
-- double check that you have the _-dev_ packages installed.
8182

8283
### Mac OS X
8384

@@ -138,7 +139,7 @@ results.each do |row|
138139
# conveniently, row is a hash
139140
# the keys are the fields, as you'd expect
140141
# the values are pre-built ruby primitives mapped from their corresponding field types in MySQL
141-
puts row["id"] # row["id"].class == Fixnum
142+
puts row["id"] # row["id"].is_a? Integer
142143
if row["dne"] # non-existant hash entry is nil
143144
puts row["dne"]
144145
end
@@ -178,6 +179,9 @@ Pass your arguments to the execute method in the same number and order as the
178179
question marks in the statement. Query options can be passed as keyword arguments
179180
to the execute method.
180181

182+
Be sure to read about the known limitations of prepared statements at
183+
https://dev.mysql.com/doc/refman/5.6/en/c-api-prepared-statement-problems.html
184+
181185
``` ruby
182186
statement = @client.prepare("SELECT * FROM users WHERE login_count = ?")
183187
result1 = statement.execute(1)
@@ -523,17 +527,18 @@ As for field values themselves, I'm workin on it - but expect that soon.
523527

524528
This gem is tested with the following Ruby versions on Linux and Mac OS X:
525529

526-
* Ruby MRI 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x
530+
* Ruby MRI 2.0.0, 2.1.x, 2.2.x, 2.3.x, 2.4.x, 2.5.x, 2.6.x
527531
* Rubinius 2.x and 3.x do work but may fail under some workloads
528532

529533
This gem is tested with the following MySQL and MariaDB versions:
530534

531535
* MySQL 5.5, 5.6, 5.7, 8.0
532536
* MySQL Connector/C 6.0 and 6.1 (primarily on Windows)
533-
* MariaDB 5.5, 10.0, 10.1, 10.2
537+
* MariaDB 5.5, 10.0, 10.1, 10.2, 10.3
534538

535539
### Ruby on Rails / Active Record
536540

541+
* mysql2 0.5.x works with Rails / Active Record 5.0.7, 5.1.6, and higher.
537542
* mysql2 0.4.x works with Rails / Active Record 4.2.5 - 5.0 and higher.
538543
* mysql2 0.3.x works with Rails / Active Record 3.1, 3.2, 4.x, 5.0.
539544
* mysql2 0.2.x works with Rails / Active Record 2.3 - 3.0.

ext/mysql2/client.c

+31-3
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ static VALUE rb_set_ssl_mode_option(VALUE self, VALUE setting) {
114114
int val = NUM2INT( setting );
115115
if (version >= 50703 && version < 50711) {
116116
if (val == SSL_MODE_DISABLED || val == SSL_MODE_REQUIRED) {
117-
bool b = ( val == SSL_MODE_REQUIRED );
117+
my_bool b = ( val == SSL_MODE_REQUIRED );
118118
int result = mysql_options( wrapper->client, MYSQL_OPT_SSL_ENFORCE, &b );
119119
return INT2NUM(result);
120120
} else {
@@ -526,7 +526,7 @@ static VALUE do_send_query(void *args) {
526526
*/
527527
static void *nogvl_read_query_result(void *ptr) {
528528
MYSQL * client = ptr;
529-
bool res = mysql_read_query_result(client);
529+
my_bool res = mysql_read_query_result(client);
530530

531531
return (void *)(res == 0 ? Qtrue : Qfalse);
532532
}
@@ -846,7 +846,7 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
846846
const void *retval = NULL;
847847
unsigned int intval = 0;
848848
const char * charval = NULL;
849-
bool boolval;
849+
my_bool boolval;
850850

851851
GET_CLIENT(self);
852852

@@ -1098,6 +1098,23 @@ static VALUE rb_mysql_client_ping(VALUE self) {
10981098
}
10991099
}
11001100

1101+
/* call-seq:
1102+
* client.set_server_option(value)
1103+
*
1104+
* Enables or disables an option for the connection.
1105+
* Read https://dev.mysql.com/doc/refman/5.7/en/mysql-set-server-option.html
1106+
* for more information.
1107+
*/
1108+
static VALUE rb_mysql_client_set_server_option(VALUE self, VALUE value) {
1109+
GET_CLIENT(self);
1110+
1111+
if (mysql_set_server_option(wrapper->client, NUM2INT(value)) == 0) {
1112+
return Qtrue;
1113+
} else {
1114+
return Qfalse;
1115+
}
1116+
}
1117+
11011118
/* call-seq:
11021119
* client.more_results?
11031120
*
@@ -1399,6 +1416,7 @@ void init_mysql2_client() {
13991416
rb_define_method(cMysql2Client, "thread_id", rb_mysql_client_thread_id, 0);
14001417
rb_define_method(cMysql2Client, "ping", rb_mysql_client_ping, 0);
14011418
rb_define_method(cMysql2Client, "select_db", rb_mysql_client_select_db, 1);
1419+
rb_define_method(cMysql2Client, "set_server_option", rb_mysql_client_set_server_option, 1);
14021420
rb_define_method(cMysql2Client, "more_results?", rb_mysql_client_more_results, 0);
14031421
rb_define_method(cMysql2Client, "next_result", rb_mysql_client_next_result, 0);
14041422
rb_define_method(cMysql2Client, "store_result", rb_mysql_client_store_result, 0);
@@ -1528,6 +1546,16 @@ void init_mysql2_client() {
15281546
rb_const_set(cMysql2Client, rb_intern("SECURE_CONNECTION"), LONG2NUM(0));
15291547
#endif
15301548

1549+
#ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_ON
1550+
rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_ON"),
1551+
LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_ON));
1552+
#endif
1553+
1554+
#ifdef HAVE_CONST_MYSQL_OPTION_MULTI_STATEMENTS_OFF
1555+
rb_const_set(cMysql2Client, rb_intern("OPTION_MULTI_STATEMENTS_OFF"),
1556+
LONG2NUM(MYSQL_OPTION_MULTI_STATEMENTS_OFF));
1557+
#endif
1558+
15311559
#ifdef CLIENT_MULTI_STATEMENTS
15321560
rb_const_set(cMysql2Client, rb_intern("MULTI_STATEMENTS"),
15331561
LONG2NUM(CLIENT_MULTI_STATEMENTS));

ext/mysql2/extconf.rb

+8
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ def add_ssl_defines(header)
6363
abort "-----\nCannot find library dir(s) #{lib}\n-----" unless lib && lib.split(File::PATH_SEPARATOR).any? { |dir| File.directory?(dir) }
6464
warn "-----\nUsing --with-mysql-dir=#{File.dirname inc}\n-----"
6565
rpath_dir = lib
66+
have_library('mysqlclient')
6667
elsif (mc = (with_config('mysql-config') || Dir[GLOB].first))
6768
# If the user has provided a --with-mysql-config argument, we must respect it or fail.
6869
# If the user gave --with-mysql-config with no argument means we should try to find it.
@@ -105,11 +106,18 @@ def add_ssl_defines(header)
105106
add_ssl_defines(mysql_h)
106107
have_struct_member('MYSQL', 'net.vio', mysql_h)
107108
have_struct_member('MYSQL', 'net.pvio', mysql_h)
109+
108110
# These constants are actually enums, so they cannot be detected by #ifdef in C code.
109111
have_const('MYSQL_ENABLE_CLEARTEXT_PLUGIN', mysql_h)
110112
have_const('SERVER_QUERY_NO_GOOD_INDEX_USED', mysql_h)
111113
have_const('SERVER_QUERY_NO_INDEX_USED', mysql_h)
112114
have_const('SERVER_QUERY_WAS_SLOW', mysql_h)
115+
have_const('MYSQL_OPTION_MULTI_STATEMENTS_ON', mysql_h)
116+
have_const('MYSQL_OPTION_MULTI_STATEMENTS_OFF', mysql_h)
117+
118+
# my_bool is replaced by C99 bool in MySQL 8.0, but we want
119+
# to retain compatibility with the typedef in earlier MySQLs.
120+
have_type('my_bool', mysql_h)
113121

114122
# This is our wishlist. We use whichever flags work on the host.
115123
# -Wall and -Wextra are included by default.

ext/mysql2/mysql2_ext.h

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ void Init_mysql2(void);
2828
#define RB_MYSQL_UNUSED
2929
#endif
3030

31+
/* MySQL 8.0 replaces my_bool with C99 bool. Earlier versions of MySQL had
32+
* a typedef to char. Gem users reported failures on big endian systems when
33+
* using C99 bool types with older MySQLs due to mismatched behavior. */
34+
#ifndef HAVE_TYPE_MY_BOOL
35+
#include <stdbool.h>
36+
typedef bool my_bool;
37+
#endif
38+
3139
#include <client.h>
3240
#include <statement.h>
3341
#include <result.h>

ext/mysql2/mysql_enc_to_ruby.h

+10
Original file line numberDiff line numberDiff line change
@@ -245,5 +245,15 @@ static const char *mysql2_mysql_enc_to_rb[] = {
245245
"UTF-8",
246246
"UTF-8",
247247
"UTF-8",
248+
"UTF-8",
249+
NULL,
250+
NULL,
251+
NULL,
252+
NULL,
253+
NULL,
254+
NULL,
255+
NULL,
248256
"UTF-8"
249257
};
258+
259+
#define CHARSETNR_SIZE (sizeof(mysql2_mysql_enc_to_rb)/sizeof(mysql2_mysql_enc_to_rb[0]))

ext/mysql2/result.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
179179
const char *enc_name;
180180
int enc_index;
181181

182-
enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
182+
enc_name = (field.charsetnr-1 < CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
183+
183184
if (enc_name != NULL) {
184185
/* use the field encoding we were able to match */
185186
enc_index = rb_enc_find_index(enc_name);
@@ -218,8 +219,8 @@ static void rb_mysql_result_alloc_result_buffers(VALUE self, MYSQL_FIELD *fields
218219
if (wrapper->result_buffers != NULL) return;
219220

220221
wrapper->result_buffers = xcalloc(wrapper->numberOfFields, sizeof(MYSQL_BIND));
221-
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(bool));
222-
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(bool));
222+
wrapper->is_null = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
223+
wrapper->error = xcalloc(wrapper->numberOfFields, sizeof(my_bool));
223224
wrapper->length = xcalloc(wrapper->numberOfFields, sizeof(unsigned long));
224225

225226
for (i = 0; i < wrapper->numberOfFields; i++) {

ext/mysql2/result.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#ifndef MYSQL2_RESULT_H
22
#define MYSQL2_RESULT_H
3-
#include <stdbool.h>
43

54
void init_mysql2_result(void);
65
VALUE rb_mysql_result_to_obj(VALUE client, VALUE encoding, VALUE options, MYSQL_RES *r, VALUE statement);
@@ -22,8 +21,8 @@ typedef struct {
2221
mysql_client_wrapper *client_wrapper;
2322
/* statement result bind buffers */
2423
MYSQL_BIND *result_buffers;
25-
bool *is_null;
26-
bool *error;
24+
my_bool *is_null;
25+
my_bool *error;
2726
unsigned long *length;
2827
} mysql2_result_wrapper;
2928

0 commit comments

Comments
 (0)