diff --git a/ext/mysql2/client.c b/ext/mysql2/client.c index 85dfc65a8..dfad1b237 100644 --- a/ext/mysql2/client.c +++ b/ext/mysql2/client.c @@ -1221,6 +1221,7 @@ static VALUE initialize_ext(VALUE self) { } void init_mysql2_client() { +#ifdef _WIN32 /* verify the libmysql we're about to use was the version we were built against https://github.com/luislavena/mysql-gem/commit/a600a9c459597da0712f70f43736e24b484f8a99 */ int i; @@ -1238,6 +1239,7 @@ void init_mysql2_client() { return; } } +#endif /* Initializing mysql library, so different threads could call Client.new */ /* without race condition in the library */ @@ -1307,6 +1309,10 @@ void init_mysql2_client() { #ifdef CLIENT_LONG_PASSWORD rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"), LONG2NUM(CLIENT_LONG_PASSWORD)); +#else + /* HACK because MariaDB 10.2 no longer defines this constant, + * but we're using it in our default connection flags. */ + rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"), INT2NUM(0)); #endif #ifdef CLIENT_FOUND_ROWS diff --git a/ext/mysql2/extconf.rb b/ext/mysql2/extconf.rb index 9895f5999..eabe7aa02 100644 --- a/ext/mysql2/extconf.rb +++ b/ext/mysql2/extconf.rb @@ -29,7 +29,7 @@ def asplode lib /usr/local/lib/mysql5 ].map{|dir| "#{dir}/bin" } -GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5}" +GLOB = "{#{dirs.join(',')}}/{mysql_config,mysql_config5,mariadb_config}" # If the user has provided a --with-mysql-dir argument, we must respect it or fail. inc, lib = dir_config('mysql') diff --git a/ext/mysql2/mysql_enc_name_to_ruby.h b/ext/mysql2/mysql_enc_name_to_ruby.h index 36f66fbe4..d532ebd89 100644 --- a/ext/mysql2/mysql_enc_name_to_ruby.h +++ b/ext/mysql2/mysql_enc_name_to_ruby.h @@ -1,5 +1,5 @@ -/* C code produced by gperf version 3.0.3 */ -/* Command-line: gperf */ +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: /usr/bin/gperf */ /* Computed positions: -k'1,3,$' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -26,11 +26,11 @@ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ -error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif struct mysql2_mysql_enc_name_to_rb_map { const char *name; const char *rb_name; }; -/* maximum key range = 66, duplicates = 0 */ +/* maximum key range = 71, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -40,60 +40,50 @@ inline #endif #endif static unsigned int -mysql2_mysql_enc_name_to_rb_hash (str, len) - register const char *str; - register unsigned int len; +mysql2_mysql_enc_name_to_rb_hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 40, 5, - 0, 69, 0, 40, 25, 20, 10, 55, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 35, 5, 0, - 10, 0, 20, 0, 5, 5, 69, 0, 10, 15, - 0, 0, 69, 69, 25, 5, 5, 0, 69, 30, - 69, 0, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, - 69, 69, 69, 69, 69, 69 + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 15, 5, + 0, 30, 5, 25, 40, 10, 20, 50, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 40, 5, 0, + 15, 10, 0, 0, 0, 5, 74, 0, 25, 5, + 0, 5, 74, 74, 20, 5, 5, 0, 74, 45, + 74, 0, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74 }; return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]]; } -#ifdef __GNUC__ -__inline -#ifdef __GNUC_STDC_INLINE__ -__attribute__ ((__gnu_inline__)) -#endif -#endif const struct mysql2_mysql_enc_name_to_rb_map * -mysql2_mysql_enc_name_to_rb (str, len) - register const char *str; - register unsigned int len; +mysql2_mysql_enc_name_to_rb (register const char *str, register size_t len) { enum { - TOTAL_KEYWORDS = 39, + TOTAL_KEYWORDS = 42, MIN_WORD_LENGTH = 3, MAX_WORD_LENGTH = 8, MIN_HASH_VALUE = 3, - MAX_HASH_VALUE = 68 + MAX_HASH_VALUE = 73 }; static const struct mysql2_mysql_enc_name_to_rb_map wordlist[] = @@ -101,62 +91,67 @@ mysql2_mysql_enc_name_to_rb (str, len) {""}, {""}, {""}, {"gbk", "GBK"}, {""}, - {"greek", "ISO-8859-7"}, + {"utf32", "UTF-32"}, {"gb2312", "GB2312"}, {"keybcs2", NULL}, {""}, {"ucs2", "UTF-16BE"}, {"koi8u", "KOI8-R"}, {"binary", "ASCII-8BIT"}, - {"eucjpms", "eucJP-ms"}, - {""}, + {"utf8mb4", "UTF-8"}, + {"macroman", "macRoman"}, {"ujis", "eucJP-ms"}, - {"cp852", "CP852"}, + {"greek", "ISO-8859-7"}, {"cp1251", "Windows-1251"}, - {"geostd8", NULL}, + {"utf16le", "UTF-16LE"}, {""}, {"sjis", "Shift_JIS"}, {"macce", "macCentEuro"}, + {"cp1257", "Windows-1257"}, + {"eucjpms", "eucJP-ms"}, + {""}, + {"utf8", "UTF-8"}, + {"cp852", "CP852"}, + {"cp1250", "Windows-1250"}, + {"gb18030", "GB18030"}, + {""}, + {"swe7", NULL}, + {"koi8r", "KOI8-R"}, + {"tis620", "TIS-620"}, + {"geostd8", NULL}, + {""}, + {"big5", "Big5"}, + {"euckr", "EUC-KR"}, {"latin2", "ISO-8859-2"}, + {"utf8mb3", "UTF-8"}, {""}, - {"macroman", "macRoman"}, {"dec8", NULL}, - {"utf32", "UTF-32"}, + {"cp850", "CP850"}, {"latin1", "UTF-8"}, - {"utf8mb4", "UTF-8"}, + {""}, {"hp8", NULL}, - {"swe7", NULL}, - {"euckr", "EUC-KR"}, - {"cp1257", "Windows-1257"}, - {""}, {""}, - {"utf8", "UTF-8"}, - {"koi8r", "KOI8-R"}, - {"cp1256", "Windows-1256"}, - {""}, {""}, {""}, - {"cp866", "IBM866"}, + {""}, + {"utf16", "UTF-16"}, {"latin7", "ISO-8859-13"}, {""}, {""}, {""}, {"ascii", "US-ASCII"}, - {"hebrew", "ISO-8859-8"}, - {""}, {""}, - {"big5", "Big5"}, - {"utf16", "UTF-16"}, - {"cp1250", "Windows-1250"}, - {""}, {""}, {""}, - {"cp850", "CP850"}, - {"tis620", "TIS-620"}, + {"cp1256", "Windows-1256"}, {""}, {""}, {""}, {"cp932", "Windows-31J"}, + {"hebrew", "ISO-8859-8"}, + {""}, {""}, {""}, {""}, {"latin5", "ISO-8859-9"}, - {""}, {""}, {""}, {""}, {""}, {""}, + {""}, {""}, {""}, + {"cp866", "IBM866"}, + {""}, {""}, {""}, {""}, {""}, {""}, {""}, {"armscii8", NULL} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { - register int key = mysql2_mysql_enc_name_to_rb_hash (str, len); + register unsigned int key = mysql2_mysql_enc_name_to_rb_hash (str, len); - if (key <= MAX_HASH_VALUE && key >= 0) + if (key <= MAX_HASH_VALUE) { register const char *s = wordlist[key].name; diff --git a/ext/mysql2/mysql_enc_to_ruby.h b/ext/mysql2/mysql_enc_to_ruby.h index 1eb13cec0..dbb78b035 100644 --- a/ext/mysql2/mysql_enc_to_ruby.h +++ b/ext/mysql2/mysql_enc_to_ruby.h @@ -54,13 +54,13 @@ const char *mysql2_mysql_enc_to_rb[] = { "macRoman", "UTF-16", "UTF-16", - NULL, + "UTF-16LE", "Windows-1256", "Windows-1257", "Windows-1257", "UTF-32", "UTF-32", - NULL, + "UTF-16LE", "ASCII-8BIT", NULL, "US-ASCII", @@ -74,7 +74,7 @@ const char *mysql2_mysql_enc_to_rb[] = { NULL, "KOI8-R", "KOI8-R", - NULL, + "UTF-8", "ISO-8859-2", "ISO-8859-9", "ISO-8859-13", @@ -119,10 +119,10 @@ const char *mysql2_mysql_enc_to_rb[] = { "UTF-16", "UTF-16", "UTF-16", - NULL, - NULL, - NULL, - NULL, + "UTF-16", + "UTF-16", + "UTF-16", + "UTF-16", NULL, NULL, NULL, @@ -146,6 +146,10 @@ const char *mysql2_mysql_enc_to_rb[] = { "UTF-16BE", "UTF-16BE", "UTF-16BE", + "UTF-16BE", + "UTF-16BE", + "UTF-16BE", + "UTF-16BE", NULL, NULL, NULL, @@ -153,11 +157,11 @@ const char *mysql2_mysql_enc_to_rb[] = { NULL, NULL, NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + "UTF-16BE", + "UTF-32", + "UTF-32", + "UTF-32", + "UTF-32", "UTF-32", "UTF-32", "UTF-32", @@ -186,6 +190,33 @@ const char *mysql2_mysql_enc_to_rb[] = { NULL, NULL, NULL, + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + NULL, + NULL, + NULL, NULL, NULL, NULL, @@ -210,18 +241,67 @@ const char *mysql2_mysql_enc_to_rb[] = { "UTF-8", "UTF-8", "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "GB18030", + "GB18030", + "GB18030", NULL, NULL, NULL, NULL, + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", NULL, + "UTF-8", + "UTF-8", + "UTF-8", NULL, + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", + "UTF-8", NULL, + "UTF-8", + "UTF-8", + "UTF-8", NULL, + "UTF-8", NULL, NULL, - NULL, - NULL, + "UTF-8", "UTF-8", "UTF-8", "UTF-8", @@ -244,3 +324,4 @@ const char *mysql2_mysql_enc_to_rb[] = { "UTF-8" }; +#define CHARSETNR_SIZE (sizeof(mysql2_mysql_enc_to_rb)/sizeof(mysql2_mysql_enc_to_rb[0])) diff --git a/ext/mysql2/result.c b/ext/mysql2/result.c index 5b8a5b162..52d95b2ef 100644 --- a/ext/mysql2/result.c +++ b/ext/mysql2/result.c @@ -158,7 +158,7 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e const char *enc_name; int enc_index; - enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1]; + enc_name = (field.charsetnr-1 < CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL; if (enc_name != NULL) { /* use the field encoding we were able to match */ enc_index = rb_enc_find_index(enc_name); @@ -297,7 +297,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo break; } msec = msec_char_to_uint(msec_char, sizeof(msec_char)); - val = rb_funcall(rb_cTime, db_timezone, 6, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec)); + val = rb_funcall(rb_cTime, db_timezone, 7, opt_time_year, opt_time_month, opt_time_month, UINT2NUM(hour), UINT2NUM(min), UINT2NUM(sec), UINT2NUM(msec)); if (!NIL_P(app_timezone)) { if (app_timezone == intern_local) { val = rb_funcall(val, intern_localtime, 0); diff --git a/support/mysql_enc_to_ruby.rb b/support/mysql_enc_to_ruby.rb index 8228d5776..b700b6282 100644 --- a/support/mysql_enc_to_ruby.rb +++ b/support/mysql_enc_to_ruby.rb @@ -33,6 +33,7 @@ "macroman" => "macRoman", "cp852" => "CP852", "latin7" => "ISO-8859-13", + "utf8mb3" => "UTF-8", "utf8mb4" => "UTF-8", "cp1251" => "Windows-1251", "utf16" => "UTF-16", @@ -42,7 +43,9 @@ "binary" => "ASCII-8BIT", "geostd8" => "NULL", "cp932" => "Windows-31J", - "eucjpms" => "eucJP-ms" + "eucjpms" => "eucJP-ms", + "utf16le" => "UTF-16LE", + "gb18030" => "GB18030", } client = Mysql2::Client.new(:username => user, :password => pass, :host => host, :port => port.to_i) @@ -52,8 +55,11 @@ collations.each do |collation| mysql_col_idx = collation[2].to_i - rb_enc = mysql_to_rb[collation[1]] - encodings[mysql_col_idx-1] = [mysql_col_idx, rb_enc] + rb_enc = mysql_to_rb.fetch(collation[1]) do |mysql_enc| + warn "WARNING: Missing mapping for collation \"#{collation[0]}\" with encoding \"#{mysql_enc}\" and id #{mysql_col_idx}, assuming NULL" + "NULL" + end + encodings[mysql_col_idx - 1] = [mysql_col_idx, rb_enc] end encodings.each_with_index do |encoding, idx| @@ -65,10 +71,10 @@ end encodings_with_nil = encodings_with_nil.map do |encoding| - name = "NULL" - - if !encoding.nil? && encoding[1] != "NULL" - name = "\"#{encoding[1]}\"" + name = if encoding.nil? || encoding[1] == 'NULL' + 'NULL' + else + "\"#{encoding[1]}\"" end " #{name}" diff --git a/support/ruby_enc_to_mysql.rb b/support/ruby_enc_to_mysql.rb index 856bc0e76..4106604c4 100644 --- a/support/ruby_enc_to_mysql.rb +++ b/support/ruby_enc_to_mysql.rb @@ -28,6 +28,7 @@ "macroman" => "macRoman", "cp852" => "CP852", "latin7" => "ISO-8859-13", + "utf8mb3" => "UTF-8", "utf8mb4" => "UTF-8", "cp1251" => "Windows-1251", "utf16" => "UTF-16", @@ -37,10 +38,12 @@ "binary" => "ASCII-8BIT", "geostd8" => nil, "cp932" => "Windows-31J", - "eucjpms" => "eucJP-ms" + "eucjpms" => "eucJP-ms", + "utf16le" => "UTF-16LE", + "gb18030" => "GB18030", } -puts <<-header +puts <<-HEADER %readonly-tables %enum %define lookup-function-name mysql2_mysql_enc_name_to_rb @@ -48,13 +51,13 @@ %struct-type struct mysql2_mysql_enc_name_to_rb_map { const char *name; const char *rb_name; } %% -header +HEADER mysql_to_rb.each do |mysql, ruby| - if ruby.nil? - name = "NULL" + name = if ruby.nil? + "NULL" else - name = "\"#{ruby}\"" + "\"#{ruby}\"" end puts "#{mysql}, #{name}"