mysql2 0.2.18 → 0.2.19b1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rbenv-version +1 -0
- data/Gemfile.lock +61 -0
- data/README.md +70 -4
- data/ext/mysql2/client.c +320 -61
- data/ext/mysql2/client.h +5 -3
- data/ext/mysql2/extconf.rb +6 -5
- data/ext/mysql2/result.c +91 -40
- data/ext/mysql2/result.h +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -13
- data/lib/mysql2.rb +18 -3
- data/lib/mysql2/client.rb +39 -12
- data/lib/mysql2/em.rb +13 -3
- data/lib/mysql2/version.rb +1 -1
- data/spec/configuration.yml.example +11 -0
- data/spec/em/em_fiber_spec.rb +2 -2
- data/spec/em/em_spec.rb +68 -7
- data/spec/mysql2/client_spec.rb +114 -12
- data/spec/mysql2/error_spec.rb +2 -2
- data/spec/mysql2/result_spec.rb +57 -5
- data/spec/spec_helper.rb +3 -1
- data/tasks/rspec.rake +11 -1
- metadata +149 -149
data/ext/mysql2/client.h
CHANGED
@@ -33,10 +33,12 @@ void init_mysql2_client();
|
|
33
33
|
|
34
34
|
typedef struct {
|
35
35
|
VALUE encoding;
|
36
|
-
|
36
|
+
VALUE active_thread; /* rb_thread_current() or Qnil */
|
37
37
|
int reconnect_enabled;
|
38
|
-
int
|
38
|
+
int active;
|
39
|
+
int connected;
|
40
|
+
int initialized;
|
39
41
|
MYSQL *client;
|
40
42
|
} mysql_client_wrapper;
|
41
43
|
|
42
|
-
#endif
|
44
|
+
#endif
|
data/ext/mysql2/extconf.rb
CHANGED
@@ -17,6 +17,7 @@ dirs = ENV['PATH'].split(File::PATH_SEPARATOR) + %w[
|
|
17
17
|
/opt/local/mysql
|
18
18
|
/opt/local/lib/mysql5
|
19
19
|
/usr
|
20
|
+
/usr/mysql
|
20
21
|
/usr/local
|
21
22
|
/usr/local/mysql
|
22
23
|
/usr/local/mysql-*
|
@@ -61,13 +62,13 @@ end
|
|
61
62
|
asplode h unless have_header h
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
+
# GCC specific flags
|
66
|
+
if RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
|
65
67
|
$CFLAGS << ' -Wall -funroll-loops'
|
66
|
-
end
|
67
|
-
# $CFLAGS << ' -O0 -ggdb3 -Wextra'
|
68
68
|
|
69
|
-
if hard_mysql_path = $libs[%r{-L(/[^ ]+)}, 1]
|
70
|
-
|
69
|
+
if hard_mysql_path = $libs[%r{-L(/[^ ]+)}, 1]
|
70
|
+
$LDFLAGS << " -Wl,-rpath,#{hard_mysql_path}"
|
71
|
+
end
|
71
72
|
end
|
72
73
|
|
73
74
|
create_makefile('mysql2/mysql2')
|
data/ext/mysql2/result.c
CHANGED
@@ -55,7 +55,7 @@ static VALUE intern_encoding_from_charset;
|
|
55
55
|
static ID intern_new, intern_utc, intern_local, intern_encoding_from_charset_code,
|
56
56
|
intern_localtime, intern_local_offset, intern_civil, intern_new_offset;
|
57
57
|
static VALUE sym_symbolize_keys, sym_as, sym_array, sym_database_timezone, sym_application_timezone,
|
58
|
-
sym_local, sym_utc, sym_cast_booleans, sym_cache_rows, sym_cast;
|
58
|
+
sym_local, sym_utc, sym_cast_booleans, sym_cache_rows, sym_cast, sym_stream;
|
59
59
|
static ID intern_merge;
|
60
60
|
|
61
61
|
static void rb_mysql_result_mark(void * wrapper) {
|
@@ -163,11 +163,10 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
|
|
163
163
|
#endif
|
164
164
|
|
165
165
|
|
166
|
-
static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool, int cast) {
|
166
|
+
static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezone, int symbolizeKeys, int asArray, int castBool, int cast, MYSQL_FIELD * fields) {
|
167
167
|
VALUE rowVal;
|
168
168
|
mysql2_result_wrapper * wrapper;
|
169
169
|
MYSQL_ROW row;
|
170
|
-
MYSQL_FIELD * fields = NULL;
|
171
170
|
unsigned int i = 0;
|
172
171
|
unsigned long * fieldLengths;
|
173
172
|
void * ptr;
|
@@ -193,7 +192,6 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
|
193
192
|
} else {
|
194
193
|
rowVal = rb_hash_new();
|
195
194
|
}
|
196
|
-
fields = mysql_fetch_fields(wrapper->result);
|
197
195
|
fieldLengths = mysql_fetch_lengths(wrapper->result);
|
198
196
|
if (wrapper->fields == Qnil) {
|
199
197
|
wrapper->numberOfFields = mysql_num_fields(wrapper->result);
|
@@ -225,7 +223,7 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
|
225
223
|
break;
|
226
224
|
case MYSQL_TYPE_TINY: // TINYINT field
|
227
225
|
if (castBool && fields[i].length == 1) {
|
228
|
-
val = *row[i]
|
226
|
+
val = *row[i] != '0' ? Qtrue : Qfalse;
|
229
227
|
break;
|
230
228
|
}
|
231
229
|
case MYSQL_TYPE_SHORT: // SMALLINT field
|
@@ -237,7 +235,9 @@ static VALUE rb_mysql_result_fetch_row(VALUE self, ID db_timezone, ID app_timezo
|
|
237
235
|
break;
|
238
236
|
case MYSQL_TYPE_DECIMAL: // DECIMAL or NUMERIC field
|
239
237
|
case MYSQL_TYPE_NEWDECIMAL: // Precision math DECIMAL or NUMERIC field (MySQL 5.0.3 and up)
|
240
|
-
if (
|
238
|
+
if (fields[i].decimals == 0) {
|
239
|
+
val = rb_cstr2inum(row[i], 10);
|
240
|
+
} else if (strtod(row[i], NULL) == 0.000000){
|
241
241
|
val = rb_funcall(cBigDecimal, intern_new, 1, opt_decimal_zero);
|
242
242
|
}else{
|
243
243
|
val = rb_funcall(cBigDecimal, intern_new, 1, rb_str_new(row[i], fieldLengths[i]));
|
@@ -392,7 +392,8 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
392
392
|
ID db_timezone, app_timezone, dbTz, appTz;
|
393
393
|
mysql2_result_wrapper * wrapper;
|
394
394
|
unsigned long i;
|
395
|
-
int symbolizeKeys = 0, asArray = 0, castBool = 0, cacheRows = 1, cast = 1;
|
395
|
+
int symbolizeKeys = 0, asArray = 0, castBool = 0, cacheRows = 1, cast = 1, streaming = 0;
|
396
|
+
MYSQL_FIELD * fields = NULL;
|
396
397
|
|
397
398
|
GetMysql2Result(self, wrapper);
|
398
399
|
|
@@ -423,6 +424,14 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
423
424
|
cast = 0;
|
424
425
|
}
|
425
426
|
|
427
|
+
if(rb_hash_aref(opts, sym_stream) == Qtrue) {
|
428
|
+
streaming = 1;
|
429
|
+
}
|
430
|
+
|
431
|
+
if(streaming && cacheRows) {
|
432
|
+
rb_warn("cacheRows is ignored if streaming is true");
|
433
|
+
}
|
434
|
+
|
426
435
|
dbTz = rb_hash_aref(opts, sym_database_timezone);
|
427
436
|
if (dbTz == sym_local) {
|
428
437
|
db_timezone = intern_local;
|
@@ -445,49 +454,82 @@ static VALUE rb_mysql_result_each(int argc, VALUE * argv, VALUE self) {
|
|
445
454
|
}
|
446
455
|
|
447
456
|
if (wrapper->lastRowProcessed == 0) {
|
448
|
-
|
449
|
-
|
457
|
+
if(streaming) {
|
458
|
+
// We can't get number of rows if we're streaming,
|
459
|
+
// until we've finished fetching all rows
|
460
|
+
wrapper->numberOfRows = 0;
|
450
461
|
wrapper->rows = rb_ary_new();
|
451
|
-
|
462
|
+
} else {
|
463
|
+
wrapper->numberOfRows = mysql_num_rows(wrapper->result);
|
464
|
+
if (wrapper->numberOfRows == 0) {
|
465
|
+
wrapper->rows = rb_ary_new();
|
466
|
+
return wrapper->rows;
|
467
|
+
}
|
468
|
+
wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
|
452
469
|
}
|
453
|
-
wrapper->rows = rb_ary_new2(wrapper->numberOfRows);
|
454
470
|
}
|
455
471
|
|
456
|
-
if (
|
457
|
-
|
458
|
-
// internal array. Lets hand that over to the user since it's ready to go
|
459
|
-
for (i = 0; i < wrapper->numberOfRows; i++) {
|
460
|
-
rb_yield(rb_ary_entry(wrapper->rows, i));
|
461
|
-
}
|
462
|
-
} else {
|
463
|
-
unsigned long rowsProcessed = 0;
|
464
|
-
rowsProcessed = RARRAY_LEN(wrapper->rows);
|
465
|
-
for (i = 0; i < wrapper->numberOfRows; i++) {
|
472
|
+
if (streaming) {
|
473
|
+
if(!wrapper->streamingComplete) {
|
466
474
|
VALUE row;
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
475
|
+
|
476
|
+
fields = mysql_fetch_fields(wrapper->result);
|
477
|
+
|
478
|
+
do {
|
479
|
+
row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool, cast, fields);
|
480
|
+
|
481
|
+
if (block != Qnil && row != Qnil) {
|
482
|
+
rb_yield(row);
|
483
|
+
wrapper->lastRowProcessed++;
|
473
484
|
}
|
474
|
-
|
485
|
+
} while(row != Qnil);
|
486
|
+
|
487
|
+
rb_mysql_result_free_result(wrapper);
|
488
|
+
|
489
|
+
wrapper->numberOfRows = wrapper->lastRowProcessed;
|
490
|
+
wrapper->streamingComplete = 1;
|
491
|
+
} else {
|
492
|
+
rb_raise(cMysql2Error, "You have already fetched all the rows for this query and streaming is true. (to reiterate you must requery).");
|
493
|
+
}
|
494
|
+
} else {
|
495
|
+
if (cacheRows && wrapper->lastRowProcessed == wrapper->numberOfRows) {
|
496
|
+
// we've already read the entire dataset from the C result into our
|
497
|
+
// internal array. Lets hand that over to the user since it's ready to go
|
498
|
+
for (i = 0; i < wrapper->numberOfRows; i++) {
|
499
|
+
rb_yield(rb_ary_entry(wrapper->rows, i));
|
475
500
|
}
|
501
|
+
} else {
|
502
|
+
unsigned long rowsProcessed = 0;
|
503
|
+
rowsProcessed = RARRAY_LEN(wrapper->rows);
|
504
|
+
fields = mysql_fetch_fields(wrapper->result);
|
505
|
+
|
506
|
+
for (i = 0; i < wrapper->numberOfRows; i++) {
|
507
|
+
VALUE row;
|
508
|
+
if (cacheRows && i < rowsProcessed) {
|
509
|
+
row = rb_ary_entry(wrapper->rows, i);
|
510
|
+
} else {
|
511
|
+
row = rb_mysql_result_fetch_row(self, db_timezone, app_timezone, symbolizeKeys, asArray, castBool, cast, fields);
|
512
|
+
if (cacheRows) {
|
513
|
+
rb_ary_store(wrapper->rows, i, row);
|
514
|
+
}
|
515
|
+
wrapper->lastRowProcessed++;
|
516
|
+
}
|
476
517
|
|
477
|
-
|
518
|
+
if (row == Qnil) {
|
519
|
+
// we don't need the mysql C dataset around anymore, peace it
|
520
|
+
rb_mysql_result_free_result(wrapper);
|
521
|
+
return Qnil;
|
522
|
+
}
|
523
|
+
|
524
|
+
if (block != Qnil) {
|
525
|
+
rb_yield(row);
|
526
|
+
}
|
527
|
+
}
|
528
|
+
if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
|
478
529
|
// we don't need the mysql C dataset around anymore, peace it
|
479
530
|
rb_mysql_result_free_result(wrapper);
|
480
|
-
return Qnil;
|
481
|
-
}
|
482
|
-
|
483
|
-
if (block != Qnil) {
|
484
|
-
rb_yield(row);
|
485
531
|
}
|
486
532
|
}
|
487
|
-
if (wrapper->lastRowProcessed == wrapper->numberOfRows) {
|
488
|
-
// we don't need the mysql C dataset around anymore, peace it
|
489
|
-
rb_mysql_result_free_result(wrapper);
|
490
|
-
}
|
491
533
|
}
|
492
534
|
|
493
535
|
return wrapper->rows;
|
@@ -497,8 +539,15 @@ static VALUE rb_mysql_result_count(VALUE self) {
|
|
497
539
|
mysql2_result_wrapper *wrapper;
|
498
540
|
|
499
541
|
GetMysql2Result(self, wrapper);
|
500
|
-
|
501
|
-
|
542
|
+
if(wrapper->resultFreed) {
|
543
|
+
if (wrapper->streamingComplete){
|
544
|
+
return LONG2NUM(wrapper->numberOfRows);
|
545
|
+
} else {
|
546
|
+
return LONG2NUM(RARRAY_LEN(wrapper->rows));
|
547
|
+
}
|
548
|
+
} else {
|
549
|
+
return INT2FIX(mysql_num_rows(wrapper->result));
|
550
|
+
}
|
502
551
|
}
|
503
552
|
|
504
553
|
/* Mysql2::Result */
|
@@ -514,6 +563,7 @@ VALUE rb_mysql_result_to_obj(MYSQL_RES * r) {
|
|
514
563
|
wrapper->fields = Qnil;
|
515
564
|
wrapper->rows = Qnil;
|
516
565
|
wrapper->encoding = Qnil;
|
566
|
+
wrapper->streamingComplete = 0;
|
517
567
|
rb_obj_call_init(obj, 0, NULL);
|
518
568
|
return obj;
|
519
569
|
}
|
@@ -551,6 +601,7 @@ void init_mysql2_result() {
|
|
551
601
|
sym_application_timezone = ID2SYM(rb_intern("application_timezone"));
|
552
602
|
sym_cache_rows = ID2SYM(rb_intern("cache_rows"));
|
553
603
|
sym_cast = ID2SYM(rb_intern("cast"));
|
604
|
+
sym_stream = ID2SYM(rb_intern("stream"));
|
554
605
|
|
555
606
|
opt_decimal_zero = rb_str_new2("0.0");
|
556
607
|
rb_global_variable(&opt_decimal_zero); //never GC
|
data/ext/mysql2/result.h
CHANGED
@@ -314,13 +314,13 @@ module ActiveRecord
|
|
314
314
|
end
|
315
315
|
|
316
316
|
def add_limit_offset!(sql, options)
|
317
|
-
limit, offset = options
|
317
|
+
limit, offset = options.fetch(:limit, 18446744073709551615), options[:offset]
|
318
318
|
if limit && offset
|
319
319
|
sql << " LIMIT #{offset.to_i}, #{sanitize_limit(limit)}"
|
320
320
|
elsif limit
|
321
321
|
sql << " LIMIT #{sanitize_limit(limit)}"
|
322
322
|
elsif offset
|
323
|
-
sql << " OFFSET #{offset.to_i}"
|
323
|
+
sql << " LIMIT #{sanitize_limit(limit)} OFFSET #{offset.to_i}"
|
324
324
|
end
|
325
325
|
sql
|
326
326
|
end
|
@@ -378,14 +378,32 @@ module ActiveRecord
|
|
378
378
|
show_variable 'collation_database'
|
379
379
|
end
|
380
380
|
|
381
|
-
def tables(name = nil)
|
381
|
+
def tables(name = nil, database = nil)
|
382
382
|
tables = []
|
383
|
-
|
383
|
+
|
384
|
+
sql = "SHOW TABLES "
|
385
|
+
sql << "IN #{quote_table_name(database)} " if database
|
386
|
+
|
387
|
+
execute(sql, 'SCHEMA').each do |field|
|
384
388
|
tables << field.first
|
385
389
|
end
|
386
390
|
tables
|
387
391
|
end
|
388
392
|
|
393
|
+
def table_exists?(name)
|
394
|
+
return true if super
|
395
|
+
|
396
|
+
name = name.to_s
|
397
|
+
schema, table = name.split('.', 2)
|
398
|
+
|
399
|
+
unless table # A table was provided without a schema
|
400
|
+
table = schema
|
401
|
+
schema = nil
|
402
|
+
end
|
403
|
+
|
404
|
+
tables(nil, schema).include? table
|
405
|
+
end
|
406
|
+
|
389
407
|
def drop_table(table_name, options = {})
|
390
408
|
super(table_name, options)
|
391
409
|
end
|
@@ -480,15 +498,26 @@ module ActiveRecord
|
|
480
498
|
|
481
499
|
# Maps logical Rails types to MySQL-specific data types.
|
482
500
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
501
|
+
case type.to_s
|
502
|
+
when 'integer'
|
503
|
+
case limit
|
504
|
+
when 1; 'tinyint'
|
505
|
+
when 2; 'smallint'
|
506
|
+
when 3; 'mediumint'
|
507
|
+
when nil, 4, 11; 'int(11)' # compatibility with MySQL default
|
508
|
+
when 5..8; 'bigint'
|
509
|
+
else raise(ActiveRecordError, "No integer type has byte size #{limit}")
|
510
|
+
end
|
511
|
+
when 'text'
|
512
|
+
case limit
|
513
|
+
when 0..0xff; 'tinytext'
|
514
|
+
when nil, 0x100..0xffff; 'text'
|
515
|
+
when 0x10000..0xffffff; 'mediumtext'
|
516
|
+
when 0x1000000..0xffffffff; 'longtext'
|
517
|
+
else raise(ActiveRecordError, "No text type has character length #{limit}")
|
518
|
+
end
|
519
|
+
else
|
520
|
+
super
|
492
521
|
end
|
493
522
|
end
|
494
523
|
|
data/lib/mysql2.rb
CHANGED
@@ -16,6 +16,21 @@ module Mysql2
|
|
16
16
|
end
|
17
17
|
|
18
18
|
if defined?(ActiveRecord::VERSION::STRING) && ActiveRecord::VERSION::STRING >= "3.1"
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
warn "============= WARNING FROM mysql2 ============="
|
20
|
+
warn "This version of mysql2 (#{Mysql2::VERSION}) isn't compatible with Rails 3.1 as the ActiveRecord adapter was pulled into Rails itself."
|
21
|
+
warn "Please use the 0.3.x (or greater) releases if you plan on using it in Rails >= 3.1.x"
|
22
|
+
warn "============= END WARNING FROM mysql2 ============="
|
23
|
+
end
|
24
|
+
|
25
|
+
# For holding utility methods
|
26
|
+
module Mysql2::Util
|
27
|
+
|
28
|
+
#
|
29
|
+
# Rekey a string-keyed hash with equivalent symbols.
|
30
|
+
#
|
31
|
+
def self.key_hash_as_symbols(hash)
|
32
|
+
return nil unless hash
|
33
|
+
Hash[hash.map { |k,v| [k.to_sym, v] }]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/lib/mysql2/client.rb
CHANGED
@@ -14,31 +14,36 @@ module Mysql2
|
|
14
14
|
}
|
15
15
|
|
16
16
|
def initialize(opts = {})
|
17
|
+
opts = Mysql2::Util.key_hash_as_symbols( opts )
|
17
18
|
@query_options = @@default_query_options.dup
|
18
19
|
@query_options.merge! opts
|
19
20
|
|
20
|
-
|
21
|
+
initialize_ext
|
21
22
|
|
22
|
-
|
23
|
+
# Set MySQL connection options (each one is a call to mysql_options())
|
24
|
+
[:reconnect, :connect_timeout, :local_infile, :read_timeout].each do |key|
|
23
25
|
next unless opts.key?(key)
|
24
26
|
send(:"#{key}=", opts[key])
|
25
27
|
end
|
28
|
+
|
26
29
|
# force the encoding to utf8
|
27
30
|
self.charset_name = opts[:encoding] || 'utf8'
|
28
31
|
|
29
|
-
@read_timeout = opts[:read_timeout]
|
30
|
-
if @read_timeout and @read_timeout < 0
|
31
|
-
raise Mysql2::Error, "read_timeout must be a positive integer, you passed #{@read_timeout}"
|
32
|
-
end
|
33
|
-
|
34
32
|
ssl_set(*opts.values_at(:sslkey, :sslcert, :sslca, :sslcapath, :sslcipher))
|
33
|
+
|
34
|
+
if [:user,:pass,:hostname,:dbname,:db,:sock].any?{|k| @query_options.has_key?(k) }
|
35
|
+
warn "============= WARNING FROM mysql2 ============="
|
36
|
+
warn "The options :user, :pass, :hostname, :dbname, :db, and :sock will be deprecated at some point in the future."
|
37
|
+
warn "Instead, please use :username, :password, :host, 'localhost', :port, :database, :socket, :flags for the options."
|
38
|
+
warn "============= END WARNING FROM mysql2 ========="
|
39
|
+
end
|
35
40
|
|
36
|
-
user = opts[:username]
|
37
|
-
pass = opts[:password]
|
38
|
-
host = opts[:host] || 'localhost'
|
41
|
+
user = opts[:username] || opts[:user]
|
42
|
+
pass = opts[:password] || opts[:pass]
|
43
|
+
host = opts[:host] || opts[:hostname] || 'localhost'
|
39
44
|
port = opts[:port] || 3306
|
40
|
-
database = opts[:database]
|
41
|
-
socket = opts[:socket]
|
45
|
+
database = opts[:database] || opts[:dbname] || opts[:db]
|
46
|
+
socket = opts[:socket] || opts[:sock]
|
42
47
|
flags = opts[:flags] ? opts[:flags] | @query_options[:connect_flags] : @query_options[:connect_flags]
|
43
48
|
|
44
49
|
connect user, pass, host, port, database, socket, flags
|
@@ -87,6 +92,7 @@ module Mysql2
|
|
87
92
|
"ucs2" => Encoding::UTF_16BE,
|
88
93
|
"ujis" => Encoding::EucJP_ms,
|
89
94
|
"utf8" => Encoding::UTF_8,
|
95
|
+
"utf8mb4" => Encoding::UTF_8,
|
90
96
|
}
|
91
97
|
|
92
98
|
MYSQL_CHARSET_MAP = {
|
@@ -134,6 +140,8 @@ module Mysql2
|
|
134
140
|
42 => {:name => "latin7", :collation => "latin7_general_cs"},
|
135
141
|
43 => {:name => "macce", :collation => "macce_bin"},
|
136
142
|
44 => {:name => "cp1250", :collation => "cp1250_croatian_ci"},
|
143
|
+
45 => {:name => "utf8mb4", :collation => "utf8mb4_general_ci"},
|
144
|
+
46 => {:name => "utf8mb4", :collation => "utf8mb4_bin"},
|
137
145
|
47 => {:name => "latin1", :collation => "latin1_bin"},
|
138
146
|
48 => {:name => "latin1", :collation => "latin1_general_ci"},
|
139
147
|
49 => {:name => "latin1", :collation => "latin1_general_cs"},
|
@@ -218,6 +226,25 @@ module Mysql2
|
|
218
226
|
208 => {:name => "utf8", :collation => "utf8_persian_ci"},
|
219
227
|
209 => {:name => "utf8", :collation => "utf8_esperanto_ci"},
|
220
228
|
210 => {:name => "utf8", :collation => "utf8_hungarian_ci"},
|
229
|
+
224 => {:name => "utf8mb4", :collation => "utf8mb4_unicode_ci"},
|
230
|
+
225 => {:name => "utf8mb4", :collation => "utf8mb4_icelandic_ci"},
|
231
|
+
226 => {:name => "utf8mb4", :collation => "utf8mb4_latvian_ci"},
|
232
|
+
227 => {:name => "utf8mb4", :collation => "utf8mb4_romanian_ci"},
|
233
|
+
228 => {:name => "utf8mb4", :collation => "utf8mb4_slovenian_ci"},
|
234
|
+
229 => {:name => "utf8mb4", :collation => "utf8mb4_polish_ci"},
|
235
|
+
230 => {:name => "utf8mb4", :collation => "utf8mb4_estonian_ci"},
|
236
|
+
231 => {:name => "utf8mb4", :collation => "utf8mb4_spanish_ci"},
|
237
|
+
232 => {:name => "utf8mb4", :collation => "utf8mb4_swedish_ci"},
|
238
|
+
233 => {:name => "utf8mb4", :collation => "utf8mb4_turkish_ci"},
|
239
|
+
234 => {:name => "utf8mb4", :collation => "utf8mb4_czech_ci"},
|
240
|
+
235 => {:name => "utf8mb4", :collation => "utf8mb4_danish_ci"},
|
241
|
+
236 => {:name => "utf8mb4", :collation => "utf8mb4_lithuanian_ci"},
|
242
|
+
237 => {:name => "utf8mb4", :collation => "utf8mb4_slovak_ci"},
|
243
|
+
238 => {:name => "utf8mb4", :collation => "utf8mb4_spanish2_ci"},
|
244
|
+
239 => {:name => "utf8mb4", :collation => "utf8mb4_roman_ci"},
|
245
|
+
240 => {:name => "utf8mb4", :collation => "utf8mb4_persian_ci"},
|
246
|
+
241 => {:name => "utf8mb4", :collation => "utf8mb4_esperanto_ci"},
|
247
|
+
242 => {:name => "utf8mb4", :collation => "utf8mb4_hungarian_ci"},
|
221
248
|
254 => {:name => "utf8", :collation => "utf8_general_cs"}
|
222
249
|
}
|
223
250
|
|