mysql2-replication 1.0.4 → 1.0.5
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/ext/mysql2-replication/mysql2_replication.c +170 -65
- data/lib/mysql2-replication/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86bbdf34e4db1d1d3379cdb75056fb9df7c4ef011362ac9356ff7bc3ff0113cd
|
4
|
+
data.tar.gz: c7b5dc5ad8fa263375deba6613466a1576fca8bfad288b967e6cbc1101e459c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74a50bc506b77572906cb977c9523bd3bcf00fcf038e12b53bb33cd6e409a1e85d680ca66ca3ce7c8d546102a3c4bbce704bce33fbea19aa3a9cb6c8cf4a08c2
|
7
|
+
data.tar.gz: 0a102c99217563a81df6d419ff11e94008bb59ad9bebd1e32bb05187d07033aecb65958ac238d8e6d3574346041523c93a64177d6d30109ab8a1805a757a185a
|
@@ -22,7 +22,9 @@ void Init_mysql2_replication(void);
|
|
22
22
|
|
23
23
|
static VALUE rb_cDate;
|
24
24
|
|
25
|
-
static VALUE
|
25
|
+
static VALUE rb_eMysql2Error;
|
26
|
+
|
27
|
+
static VALUE rb_eMysql2ReplicationError;
|
26
28
|
|
27
29
|
static VALUE rb_cMysql2ReplicationEvent;
|
28
30
|
static VALUE rb_cMysql2ReplicationRotateEvent;
|
@@ -336,6 +338,37 @@ rbm2_metadata_parse(enum enum_field_types *column_type,
|
|
336
338
|
}
|
337
339
|
}
|
338
340
|
|
341
|
+
static inline VALUE
|
342
|
+
rbm2_column_parse_variable_size_uint(VALUE rb_column,
|
343
|
+
const uint8_t **row_data)
|
344
|
+
{
|
345
|
+
VALUE rb_size = rb_hash_aref(rb_column, rb_id2sym(rb_intern("size")));
|
346
|
+
uint32_t size = NUM2UINT(rb_size);
|
347
|
+
VALUE rb_value = RUBY_Qnil;
|
348
|
+
switch (size) {
|
349
|
+
case 1:
|
350
|
+
rb_value = USHORT2NUM(rbm2_read_uint8(*row_data));
|
351
|
+
break;
|
352
|
+
case 2:
|
353
|
+
rb_value = USHORT2NUM(rbm2_read_uint16(*row_data));
|
354
|
+
break;
|
355
|
+
case 3:
|
356
|
+
rb_value = UINT2NUM(rbm2_read_uint24(*row_data));
|
357
|
+
break;
|
358
|
+
case 4:
|
359
|
+
rb_value = UINT2NUM(rbm2_read_uint32(*row_data));
|
360
|
+
break;
|
361
|
+
default:
|
362
|
+
rb_raise(rb_eNotImpError,
|
363
|
+
"unsupported size for variable size uint: %u: %+" PRIsVALUE,
|
364
|
+
size,
|
365
|
+
rb_column);
|
366
|
+
break;
|
367
|
+
}
|
368
|
+
(*row_data) += size;
|
369
|
+
return rb_value;
|
370
|
+
}
|
371
|
+
|
339
372
|
static inline VALUE
|
340
373
|
rbm2_column_parse_variable_length_string(VALUE rb_column,
|
341
374
|
const uint8_t **row_data)
|
@@ -409,8 +442,9 @@ rbm2_column_parse_blob(VALUE rb_column,
|
|
409
442
|
break;
|
410
443
|
default:
|
411
444
|
rb_raise(rb_eNotImpError,
|
412
|
-
"unsupported length size for blob: %u",
|
413
|
-
length_size
|
445
|
+
"unsupported length size for blob: %u: %+" PRIsVALUE,
|
446
|
+
length_size,
|
447
|
+
rb_column);
|
414
448
|
break;
|
415
449
|
}
|
416
450
|
return rb_value;
|
@@ -426,8 +460,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
426
460
|
switch (type) {
|
427
461
|
case MYSQL_TYPE_DECIMAL:
|
428
462
|
rb_raise(rb_eNotImpError,
|
429
|
-
"decimal type isn't implemented yet: %+" PRIsVALUE,
|
430
|
-
rb_type
|
463
|
+
"decimal type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
|
464
|
+
rb_type,
|
465
|
+
rb_column);
|
431
466
|
break;
|
432
467
|
case MYSQL_TYPE_TINY:
|
433
468
|
rb_value = RB_CHR2FIX(*(*row_data));
|
@@ -476,12 +511,21 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
476
511
|
M: 4bit
|
477
512
|
D: 5bit
|
478
513
|
*/
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
514
|
+
if (raw_date == 0) {
|
515
|
+
rb_value = rb_funcall(rb_cDate,
|
516
|
+
rb_intern("new"),
|
517
|
+
3,
|
518
|
+
RB_UINT2NUM(0),
|
519
|
+
RB_UINT2NUM(1),
|
520
|
+
RB_UINT2NUM(1));
|
521
|
+
} else {
|
522
|
+
rb_value = rb_funcall(rb_cDate,
|
523
|
+
rb_intern("new"),
|
524
|
+
3,
|
525
|
+
RB_UINT2NUM((raw_date >> 9)),
|
526
|
+
RB_UINT2NUM((raw_date >> 5) & ((1 << 4) - 1)),
|
527
|
+
RB_UINT2NUM((raw_date & ((1 << 5) - 1))));
|
528
|
+
}
|
485
529
|
(*row_data) += 3;
|
486
530
|
}
|
487
531
|
break;
|
@@ -502,15 +546,22 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
502
546
|
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_datetime */
|
503
547
|
uint64_t raw_time = rbm2_read_uint64(*row_data);
|
504
548
|
/* YYYYMMDDHHMMSS */
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
549
|
+
if (raw_time == 0) {
|
550
|
+
rb_value = rb_funcall(rb_cTime,
|
551
|
+
rb_intern("utc"),
|
552
|
+
1,
|
553
|
+
RB_UINT2NUM(0));
|
554
|
+
} else {
|
555
|
+
rb_value = rb_funcall(rb_cTime,
|
556
|
+
rb_intern("utc"),
|
557
|
+
6,
|
558
|
+
RB_UINT2NUM((raw_time / 10000000000)),
|
559
|
+
RB_UINT2NUM((raw_time % 10000000000) / 100000000),
|
560
|
+
RB_UINT2NUM((raw_time % 100000000) / 1000000),
|
561
|
+
RB_UINT2NUM((raw_time % 1000000) / 10000),
|
562
|
+
RB_UINT2NUM((raw_time % 10000) / 100),
|
563
|
+
RB_UINT2NUM((raw_time % 100)));
|
564
|
+
}
|
514
565
|
(*row_data) += 8;
|
515
566
|
}
|
516
567
|
break;
|
@@ -520,8 +571,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
520
571
|
break;
|
521
572
|
case MYSQL_TYPE_NEWDATE:
|
522
573
|
rb_raise(rb_eNotImpError,
|
523
|
-
"newdate type isn't implemented yet: %+" PRIsVALUE,
|
524
|
-
rb_type
|
574
|
+
"newdate type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
|
575
|
+
rb_type,
|
576
|
+
rb_column);
|
525
577
|
break;
|
526
578
|
case MYSQL_TYPE_VARCHAR:
|
527
579
|
rb_value = rbm2_column_parse_variable_length_string(rb_column, row_data);
|
@@ -550,9 +602,11 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
550
602
|
break;
|
551
603
|
default :
|
552
604
|
rb_raise(rb_eNotImpError,
|
553
|
-
"%d bit type isn't implemented yet: %+" PRIsVALUE
|
605
|
+
"%d bit type isn't implemented yet: %+" PRIsVALUE
|
606
|
+
": %+" PRIsVALUE,
|
554
607
|
bits,
|
555
|
-
rb_type
|
608
|
+
rb_type,
|
609
|
+
rb_column);
|
556
610
|
break;
|
557
611
|
}
|
558
612
|
}
|
@@ -646,8 +700,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
646
700
|
break;
|
647
701
|
case MYSQL_TYPE_TIME2:
|
648
702
|
rb_raise(rb_eNotImpError,
|
649
|
-
"time2 type isn't implemented yet: %+" PRIsVALUE,
|
650
|
-
rb_type
|
703
|
+
"time2 type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
|
704
|
+
rb_type,
|
705
|
+
rb_column);
|
651
706
|
break;
|
652
707
|
case MYSQL_TYPE_JSON:
|
653
708
|
rb_value = rbm2_column_parse_blob(rb_column, row_data);
|
@@ -683,16 +738,15 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
683
738
|
break;
|
684
739
|
case MYSQL_TYPE_ENUM:
|
685
740
|
case MYSQL_TYPE_SET:
|
686
|
-
|
687
|
-
"enum/set types aren't implemented yet: %+" PRIsVALUE,
|
688
|
-
rb_type);
|
741
|
+
rb_value = rbm2_column_parse_variable_size_uint(rb_column, row_data);
|
689
742
|
break;
|
690
743
|
case MYSQL_TYPE_TINY_BLOB:
|
691
744
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
692
745
|
case MYSQL_TYPE_LONG_BLOB:
|
693
746
|
rb_raise(rb_eNotImpError,
|
694
|
-
"blob types aren't implemented yet: %+" PRIsVALUE,
|
695
|
-
rb_type
|
747
|
+
"blob types aren't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
|
748
|
+
rb_type,
|
749
|
+
rb_column);
|
696
750
|
break;
|
697
751
|
case MYSQL_TYPE_BLOB:
|
698
752
|
rb_value = rbm2_column_parse_blob(rb_column, row_data);
|
@@ -705,13 +759,17 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
|
705
759
|
break;
|
706
760
|
case MYSQL_TYPE_GEOMETRY:
|
707
761
|
rb_raise(rb_eNotImpError,
|
708
|
-
"geometry type isn't implemented yet: %+" PRIsVALUE
|
709
|
-
|
762
|
+
"geometry type isn't implemented yet: %+" PRIsVALUE
|
763
|
+
": %+" PRIsVALUE,
|
764
|
+
rb_type,
|
765
|
+
rb_column);
|
710
766
|
break;
|
711
767
|
default:
|
712
768
|
rb_raise(rb_eNotImpError,
|
713
|
-
"unknown type isn't implemented yet: %+" PRIsVALUE
|
714
|
-
|
769
|
+
"unknown type isn't implemented yet: %+" PRIsVALUE
|
770
|
+
": %+" PRIsVALUE,
|
771
|
+
rb_type,
|
772
|
+
rb_column);
|
715
773
|
break;
|
716
774
|
}
|
717
775
|
return rb_value;
|
@@ -730,6 +788,7 @@ typedef struct
|
|
730
788
|
VALUE rb_client;
|
731
789
|
VALUE rb_table_maps;
|
732
790
|
bool force_disable_use_checksum;
|
791
|
+
bool format_description_processed;
|
733
792
|
} rbm2_replication_client_wrapper;
|
734
793
|
|
735
794
|
static void
|
@@ -820,7 +879,7 @@ rbm2_replication_client_raise(VALUE self)
|
|
820
879
|
rb_usascii_encoding());
|
821
880
|
ID new_with_args;
|
822
881
|
CONST_ID(new_with_args, "new_with_args");
|
823
|
-
VALUE rb_error = rb_funcall(
|
882
|
+
VALUE rb_error = rb_funcall(rb_eMysql2Error,
|
824
883
|
new_with_args,
|
825
884
|
4,
|
826
885
|
rb_error_message,
|
@@ -877,6 +936,7 @@ rbm2_replication_client_initialize(int argc, VALUE *argv, VALUE self)
|
|
877
936
|
} else {
|
878
937
|
wrapper->force_disable_use_checksum = false;
|
879
938
|
}
|
939
|
+
wrapper->format_description_processed = false;
|
880
940
|
|
881
941
|
return RUBY_Qnil;
|
882
942
|
}
|
@@ -1098,6 +1158,57 @@ rbm2_row_parse(const uint8_t **row_data,
|
|
1098
1158
|
return rb_row;
|
1099
1159
|
}
|
1100
1160
|
|
1161
|
+
typedef struct
|
1162
|
+
{
|
1163
|
+
struct st_mariadb_rpl_rows_event *rows_event;
|
1164
|
+
VALUE rb_klass;
|
1165
|
+
VALUE rb_rows;
|
1166
|
+
VALUE rb_updated_rows;
|
1167
|
+
VALUE rb_table_map;
|
1168
|
+
} rbm2_replication_rows_event_parse_rows_data;
|
1169
|
+
|
1170
|
+
static VALUE
|
1171
|
+
rbm2_replication_rows_event_parse_rows_body(VALUE user_data)
|
1172
|
+
{
|
1173
|
+
rbm2_replication_rows_event_parse_rows_data *data =
|
1174
|
+
(rbm2_replication_rows_event_parse_rows_data *)user_data;
|
1175
|
+
|
1176
|
+
const uint8_t *column_bitmap =
|
1177
|
+
(const uint8_t *)(data->rows_event->column_bitmap);
|
1178
|
+
const uint8_t *column_update_bitmap =
|
1179
|
+
(const uint8_t *)(data->rows_event->column_update_bitmap);
|
1180
|
+
const uint8_t *row_data = data->rows_event->row_data;
|
1181
|
+
const uint8_t *row_data_end = row_data + data->rows_event->row_data_size;
|
1182
|
+
VALUE rb_columns = rb_iv_get(data->rb_table_map, "@columns");
|
1183
|
+
while (row_data < row_data_end) {
|
1184
|
+
VALUE rb_row = rbm2_row_parse(&row_data,
|
1185
|
+
data->rows_event->column_count,
|
1186
|
+
column_bitmap,
|
1187
|
+
rb_columns);
|
1188
|
+
rb_ary_push(data->rb_rows, rb_row);
|
1189
|
+
if (data->rb_klass == rb_cMysql2ReplicationUpdateRowsEvent) {
|
1190
|
+
VALUE rb_updated_row = rbm2_row_parse(&row_data,
|
1191
|
+
data->rows_event->column_count,
|
1192
|
+
column_update_bitmap,
|
1193
|
+
rb_columns);
|
1194
|
+
rb_ary_push(data->rb_updated_rows, rb_updated_row);
|
1195
|
+
}
|
1196
|
+
}
|
1197
|
+
return RUBY_Qnil;
|
1198
|
+
}
|
1199
|
+
|
1200
|
+
static VALUE
|
1201
|
+
rbm2_replication_rows_event_parse_rows_rescue(VALUE user_data, VALUE error)
|
1202
|
+
{
|
1203
|
+
rbm2_replication_rows_event_parse_rows_data *data =
|
1204
|
+
(rbm2_replication_rows_event_parse_rows_data *)user_data;
|
1205
|
+
rb_raise(rb_eMysql2ReplicationError,
|
1206
|
+
"failed to parse rows: %+" PRIsVALUE ": %+" PRIsVALUE,
|
1207
|
+
data->rb_table_map,
|
1208
|
+
rb_funcall(error, rb_intern("message"), 0));
|
1209
|
+
return RUBY_Qnil;
|
1210
|
+
}
|
1211
|
+
|
1101
1212
|
static VALUE
|
1102
1213
|
rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
1103
1214
|
MARIADB_RPL_EVENT *event)
|
@@ -1111,15 +1222,17 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
|
1111
1222
|
{
|
1112
1223
|
struct st_mariadb_rpl_rotate_event *e = &(event->event.rotate);
|
1113
1224
|
rb_iv_set(rb_event, "@position", ULL2NUM(e->position));
|
1114
|
-
size_t filename_size;
|
1225
|
+
size_t filename_size = e->filename.length;
|
1115
1226
|
if (event->timestamp == 0) {
|
1116
1227
|
/* Fake ROTATE_EVENT: https://mariadb.com/kb/en/fake-rotate_event/ */
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1228
|
+
if (!wrapper->format_description_processed) {
|
1229
|
+
filename_size = wrapper->rpl->buffer_size -
|
1230
|
+
EVENT_HEADER_OFS -
|
1231
|
+
sizeof(uint64_t); /* position */
|
1232
|
+
if (!wrapper->force_disable_use_checksum) {
|
1233
|
+
filename_size -= sizeof(uint32_t); /* checksum */
|
1234
|
+
}
|
1235
|
+
}
|
1123
1236
|
}
|
1124
1237
|
rb_iv_set(rb_event,
|
1125
1238
|
"@file_name",
|
@@ -1140,6 +1253,7 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
|
1140
1253
|
if (wrapper->force_disable_use_checksum) {
|
1141
1254
|
wrapper->rpl->use_checksum = false;
|
1142
1255
|
}
|
1256
|
+
wrapper->format_description_processed = true;
|
1143
1257
|
break;
|
1144
1258
|
case TABLE_MAP_EVENT:
|
1145
1259
|
klass = rb_cMysql2ReplicationTableMapEvent;
|
@@ -1201,10 +1315,6 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
|
1201
1315
|
struct st_mariadb_rpl_rows_event *e = &(event->event.rows);
|
1202
1316
|
VALUE rb_table_id = ULONG2NUM(e->table_id);
|
1203
1317
|
VALUE rb_table_map = rb_hash_aref(wrapper->rb_table_maps, rb_table_id);
|
1204
|
-
const uint8_t *column_bitmap =
|
1205
|
-
(const uint8_t *)(e->column_bitmap);
|
1206
|
-
const uint8_t *column_update_bitmap =
|
1207
|
-
(const uint8_t *)(e->column_update_bitmap);
|
1208
1318
|
rb_iv_set(rb_event, "@table_id", rb_table_id);
|
1209
1319
|
rb_iv_set(rb_event, "@table_map", rb_table_map);
|
1210
1320
|
rb_iv_set(rb_event, "@rows_flags", USHORT2NUM(e->flags));
|
@@ -1213,24 +1323,15 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
|
1213
1323
|
if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
|
1214
1324
|
rb_updated_rows = rb_ary_new();
|
1215
1325
|
}
|
1216
|
-
const uint8_t *row_data = e->row_data;
|
1217
|
-
const uint8_t *row_data_end = row_data + e->row_data_size;
|
1218
1326
|
if (!RB_NIL_P(rb_table_map)) {
|
1219
|
-
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1227
|
-
VALUE rb_updated_row = rbm2_row_parse(&row_data,
|
1228
|
-
e->column_count,
|
1229
|
-
column_update_bitmap,
|
1230
|
-
rb_columns);
|
1231
|
-
rb_ary_push(rb_updated_rows, rb_updated_row);
|
1232
|
-
}
|
1233
|
-
}
|
1327
|
+
rbm2_replication_rows_event_parse_rows_data data;
|
1328
|
+
data.rows_event = e;
|
1329
|
+
data.rb_klass = klass;
|
1330
|
+
data.rb_rows = rb_rows;
|
1331
|
+
data.rb_updated_rows = rb_updated_rows;
|
1332
|
+
data.rb_table_map = rb_table_map;
|
1333
|
+
rb_rescue(rbm2_replication_rows_event_parse_rows_body, (VALUE)&data,
|
1334
|
+
rbm2_replication_rows_event_parse_rows_rescue, (VALUE)&data);
|
1234
1335
|
}
|
1235
1336
|
rb_iv_set(rb_event, "@rows", rb_rows);
|
1236
1337
|
if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
|
@@ -1312,9 +1413,13 @@ Init_mysql2_replication(void)
|
|
1312
1413
|
rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
1313
1414
|
|
1314
1415
|
VALUE rb_mMysql2 = rb_const_get(rb_cObject, rb_intern("Mysql2"));
|
1315
|
-
|
1416
|
+
rb_eMysql2Error = rb_const_get(rb_mMysql2, rb_intern("Error"));
|
1316
1417
|
|
1317
1418
|
VALUE rb_mMysql2Replication = rb_define_module("Mysql2Replication");
|
1419
|
+
rb_eMysql2ReplicationError =
|
1420
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1421
|
+
"Error",
|
1422
|
+
rb_eStandardError);
|
1318
1423
|
|
1319
1424
|
rb_cMysql2ReplicationEvent =
|
1320
1425
|
rb_define_class_under(rb_mMysql2Replication, "Event", rb_cObject);
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mysql2-replication
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sutou Kouhei
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|