mysql2-replication 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dae33ecb6c6b2ecfade5316344529e995ef41efefbf22791cef85b07c14253f6
4
- data.tar.gz: 9407c34a9d180cb06ee7e22072db0f4727213ef96e5134f6c47c7e2c7aef48d2
3
+ metadata.gz: 86bbdf34e4db1d1d3379cdb75056fb9df7c4ef011362ac9356ff7bc3ff0113cd
4
+ data.tar.gz: c7b5dc5ad8fa263375deba6613466a1576fca8bfad288b967e6cbc1101e459c2
5
5
  SHA512:
6
- metadata.gz: c991529269be9df8fb90d312ff644eb069103dc80538c5c5f0484a04d9bfd12b8218e164e48aff82011646a2bd3a9a1f827050211277d676ff3cb0c8095775c1
7
- data.tar.gz: 6c56fc58282cff73dc930f791945bdf23d872df53e70b3b655c0e7dbb78a0c89823d8105438856aee8d642f10b793599932a26b60100fdf19824fffd60d65cf2
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 rb_cMysql2Error;
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
- rb_value = rb_funcall(rb_cDate,
480
- rb_intern("new"),
481
- 3,
482
- RB_UINT2NUM((raw_date >> 9)),
483
- RB_UINT2NUM((raw_date >> 5) & ((1 << 4) - 1)),
484
- RB_UINT2NUM((raw_date & ((1 << 5) - 1))));
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
- rb_value = rb_funcall(rb_cTime,
506
- rb_intern("utc"),
507
- 6,
508
- RB_UINT2NUM((raw_time / 10000000000)),
509
- RB_UINT2NUM((raw_time % 10000000000) / 100000000),
510
- RB_UINT2NUM((raw_time % 100000000) / 1000000),
511
- RB_UINT2NUM((raw_time % 1000000) / 10000),
512
- RB_UINT2NUM((raw_time % 10000) / 100),
513
- RB_UINT2NUM((raw_time % 100)));
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
- rb_raise(rb_eNotImpError,
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
- rb_type);
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
- rb_type);
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(rb_cMysql2Error,
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
- filename_size = wrapper->rpl->buffer_size -
1118
- EVENT_HEADER_OFS -
1119
- sizeof(uint64_t) - /* position */
1120
- sizeof(uint32_t); /* checksum */
1121
- } else {
1122
- filename_size = e->filename.length;
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
- VALUE rb_columns = rb_iv_get(rb_table_map, "@columns");
1220
- while (row_data < row_data_end) {
1221
- VALUE rb_row = rbm2_row_parse(&row_data,
1222
- e->column_count,
1223
- column_bitmap,
1224
- rb_columns);
1225
- rb_ary_push(rb_rows, rb_row);
1226
- if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
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
- rb_cMysql2Error = rb_const_get(rb_mMysql2, rb_intern("Error"));
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);
@@ -1,3 +1,3 @@
1
1
  module Mysql2Replication
2
- VERSION = "1.0.4"
2
+ VERSION = "1.0.5"
3
3
  end
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
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-07 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mysql2