mysql2-replication 1.0.1 → 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: e4e53fa99301ddf9de5e0152b67093098271e727d7dbf21f4228bb0f1d1857cc
4
- data.tar.gz: 7345a93462c78c4d0fa7ff94f7c14e09005b4119366a58130855de1d3c94a7b6
3
+ metadata.gz: 86bbdf34e4db1d1d3379cdb75056fb9df7c4ef011362ac9356ff7bc3ff0113cd
4
+ data.tar.gz: c7b5dc5ad8fa263375deba6613466a1576fca8bfad288b967e6cbc1101e459c2
5
5
  SHA512:
6
- metadata.gz: 3d3cac78675064583fc9f02a6f362a1dc5d5ed75bc7ae61873e734697f72f14ab5c5fe87335370dbb4be3231d604140b0a1e258bc615c730582c9db441ce2823
7
- data.tar.gz: fb7bddd05753618b6fcef07c4e8ddea0ac611d9b94df1c80dd51671432799974b84667bb11d72475c405c73c80c56d90363a793fa5b036e29cb11dca3c83c1c8
6
+ metadata.gz: 74a50bc506b77572906cb977c9523bd3bcf00fcf038e12b53bb33cd6e409a1e85d680ca66ca3ce7c8d546102a3c4bbce704bce33fbea19aa3a9cb6c8cf4a08c2
7
+ data.tar.gz: 0a102c99217563a81df6d419ff11e94008bb59ad9bebd1e32bb05187d07033aecb65958ac238d8e6d3574346041523c93a64177d6d30109ab8a1805a757a185a
@@ -1,3 +1,5 @@
1
+ #include <stdbool.h>
2
+
1
3
  #include <ruby.h>
2
4
  #include <ruby/encoding.h>
3
5
  #include <ruby/thread.h>
@@ -10,11 +12,19 @@
10
12
  /* mysql2 */
11
13
  #include <client.h>
12
14
 
15
+
16
+ #ifndef RUBY_LL2NUM
17
+ # define RUBY_LL2NUM LL2NUM
18
+ #endif
19
+
20
+
13
21
  void Init_mysql2_replication(void);
14
22
 
15
23
  static VALUE rb_cDate;
16
24
 
17
- static VALUE rb_cMysql2Error;
25
+ static VALUE rb_eMysql2Error;
26
+
27
+ static VALUE rb_eMysql2ReplicationError;
18
28
 
19
29
  static VALUE rb_cMysql2ReplicationEvent;
20
30
  static VALUE rb_cMysql2ReplicationRotateEvent;
@@ -328,6 +338,37 @@ rbm2_metadata_parse(enum enum_field_types *column_type,
328
338
  }
329
339
  }
330
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
+
331
372
  static inline VALUE
332
373
  rbm2_column_parse_variable_length_string(VALUE rb_column,
333
374
  const uint8_t **row_data)
@@ -401,8 +442,9 @@ rbm2_column_parse_blob(VALUE rb_column,
401
442
  break;
402
443
  default:
403
444
  rb_raise(rb_eNotImpError,
404
- "unsupported length size for blob: %u",
405
- length_size);
445
+ "unsupported length size for blob: %u: %+" PRIsVALUE,
446
+ length_size,
447
+ rb_column);
406
448
  break;
407
449
  }
408
450
  return rb_value;
@@ -418,8 +460,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
418
460
  switch (type) {
419
461
  case MYSQL_TYPE_DECIMAL:
420
462
  rb_raise(rb_eNotImpError,
421
- "decimal type isn't implemented yet: %+" PRIsVALUE,
422
- rb_type);
463
+ "decimal type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
464
+ rb_type,
465
+ rb_column);
423
466
  break;
424
467
  case MYSQL_TYPE_TINY:
425
468
  rb_value = RB_CHR2FIX(*(*row_data));
@@ -468,12 +511,21 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
468
511
  M: 4bit
469
512
  D: 5bit
470
513
  */
471
- rb_value = rb_funcall(rb_cDate,
472
- rb_intern("new"),
473
- 3,
474
- RB_UINT2NUM((raw_date >> 9)),
475
- RB_UINT2NUM((raw_date >> 5) & ((1 << 4) - 1)),
476
- 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
+ }
477
529
  (*row_data) += 3;
478
530
  }
479
531
  break;
@@ -494,15 +546,22 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
494
546
  /* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_datetime */
495
547
  uint64_t raw_time = rbm2_read_uint64(*row_data);
496
548
  /* YYYYMMDDHHMMSS */
497
- rb_value = rb_funcall(rb_cTime,
498
- rb_intern("utc"),
499
- 6,
500
- RB_UINT2NUM((raw_time / (10 * 10))),
501
- RB_UINT2NUM((raw_time % (10 * 10)) / (10 * 8)),
502
- RB_UINT2NUM((raw_time % (10 * 8)) / (10 * 6)),
503
- RB_UINT2NUM((raw_time % (10 * 6)) / (10 * 4)),
504
- RB_UINT2NUM((raw_time % (10 * 4)) / (10 * 2)),
505
- RB_UINT2NUM((raw_time % (10 * 2))));
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
+ }
506
565
  (*row_data) += 8;
507
566
  }
508
567
  break;
@@ -512,8 +571,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
512
571
  break;
513
572
  case MYSQL_TYPE_NEWDATE:
514
573
  rb_raise(rb_eNotImpError,
515
- "newdate type isn't implemented yet: %+" PRIsVALUE,
516
- rb_type);
574
+ "newdate type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
575
+ rb_type,
576
+ rb_column);
517
577
  break;
518
578
  case MYSQL_TYPE_VARCHAR:
519
579
  rb_value = rbm2_column_parse_variable_length_string(rb_column, row_data);
@@ -542,9 +602,11 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
542
602
  break;
543
603
  default :
544
604
  rb_raise(rb_eNotImpError,
545
- "%d bit type isn't implemented yet: %+" PRIsVALUE,
605
+ "%d bit type isn't implemented yet: %+" PRIsVALUE
606
+ ": %+" PRIsVALUE,
546
607
  bits,
547
- rb_type);
608
+ rb_type,
609
+ rb_column);
548
610
  break;
549
611
  }
550
612
  }
@@ -638,8 +700,9 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
638
700
  break;
639
701
  case MYSQL_TYPE_TIME2:
640
702
  rb_raise(rb_eNotImpError,
641
- "time2 type isn't implemented yet: %+" PRIsVALUE,
642
- rb_type);
703
+ "time2 type isn't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
704
+ rb_type,
705
+ rb_column);
643
706
  break;
644
707
  case MYSQL_TYPE_JSON:
645
708
  rb_value = rbm2_column_parse_blob(rb_column, row_data);
@@ -675,16 +738,15 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
675
738
  break;
676
739
  case MYSQL_TYPE_ENUM:
677
740
  case MYSQL_TYPE_SET:
678
- rb_raise(rb_eNotImpError,
679
- "enum/set types aren't implemented yet: %+" PRIsVALUE,
680
- rb_type);
741
+ rb_value = rbm2_column_parse_variable_size_uint(rb_column, row_data);
681
742
  break;
682
743
  case MYSQL_TYPE_TINY_BLOB:
683
744
  case MYSQL_TYPE_MEDIUM_BLOB:
684
745
  case MYSQL_TYPE_LONG_BLOB:
685
746
  rb_raise(rb_eNotImpError,
686
- "blob types aren't implemented yet: %+" PRIsVALUE,
687
- rb_type);
747
+ "blob types aren't implemented yet: %+" PRIsVALUE ": %+" PRIsVALUE,
748
+ rb_type,
749
+ rb_column);
688
750
  break;
689
751
  case MYSQL_TYPE_BLOB:
690
752
  rb_value = rbm2_column_parse_blob(rb_column, row_data);
@@ -697,13 +759,17 @@ rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
697
759
  break;
698
760
  case MYSQL_TYPE_GEOMETRY:
699
761
  rb_raise(rb_eNotImpError,
700
- "geometry type isn't implemented yet: %+" PRIsVALUE,
701
- rb_type);
762
+ "geometry type isn't implemented yet: %+" PRIsVALUE
763
+ ": %+" PRIsVALUE,
764
+ rb_type,
765
+ rb_column);
702
766
  break;
703
767
  default:
704
768
  rb_raise(rb_eNotImpError,
705
- "unknown type isn't implemented yet: %+" PRIsVALUE,
706
- rb_type);
769
+ "unknown type isn't implemented yet: %+" PRIsVALUE
770
+ ": %+" PRIsVALUE,
771
+ rb_type,
772
+ rb_column);
707
773
  break;
708
774
  }
709
775
  return rb_value;
@@ -722,6 +788,7 @@ typedef struct
722
788
  VALUE rb_client;
723
789
  VALUE rb_table_maps;
724
790
  bool force_disable_use_checksum;
791
+ bool format_description_processed;
725
792
  } rbm2_replication_client_wrapper;
726
793
 
727
794
  static void
@@ -812,7 +879,7 @@ rbm2_replication_client_raise(VALUE self)
812
879
  rb_usascii_encoding());
813
880
  ID new_with_args;
814
881
  CONST_ID(new_with_args, "new_with_args");
815
- VALUE rb_error = rb_funcall(rb_cMysql2Error,
882
+ VALUE rb_error = rb_funcall(rb_eMysql2Error,
816
883
  new_with_args,
817
884
  4,
818
885
  rb_error_message,
@@ -869,6 +936,7 @@ rbm2_replication_client_initialize(int argc, VALUE *argv, VALUE self)
869
936
  } else {
870
937
  wrapper->force_disable_use_checksum = false;
871
938
  }
939
+ wrapper->format_description_processed = false;
872
940
 
873
941
  return RUBY_Qnil;
874
942
  }
@@ -1090,6 +1158,57 @@ rbm2_row_parse(const uint8_t **row_data,
1090
1158
  return rb_row;
1091
1159
  }
1092
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
+
1093
1212
  static VALUE
1094
1213
  rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
1095
1214
  MARIADB_RPL_EVENT *event)
@@ -1103,15 +1222,17 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
1103
1222
  {
1104
1223
  struct st_mariadb_rpl_rotate_event *e = &(event->event.rotate);
1105
1224
  rb_iv_set(rb_event, "@position", ULL2NUM(e->position));
1106
- size_t filename_size;
1225
+ size_t filename_size = e->filename.length;
1107
1226
  if (event->timestamp == 0) {
1108
1227
  /* Fake ROTATE_EVENT: https://mariadb.com/kb/en/fake-rotate_event/ */
1109
- filename_size = wrapper->rpl->buffer_size -
1110
- EVENT_HEADER_OFS -
1111
- sizeof(uint64_t) - /* position */
1112
- sizeof(uint32_t); /* checksum */
1113
- } else {
1114
- 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
+ }
1115
1236
  }
1116
1237
  rb_iv_set(rb_event,
1117
1238
  "@file_name",
@@ -1132,6 +1253,7 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
1132
1253
  if (wrapper->force_disable_use_checksum) {
1133
1254
  wrapper->rpl->use_checksum = false;
1134
1255
  }
1256
+ wrapper->format_description_processed = true;
1135
1257
  break;
1136
1258
  case TABLE_MAP_EVENT:
1137
1259
  klass = rb_cMysql2ReplicationTableMapEvent;
@@ -1193,10 +1315,6 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
1193
1315
  struct st_mariadb_rpl_rows_event *e = &(event->event.rows);
1194
1316
  VALUE rb_table_id = ULONG2NUM(e->table_id);
1195
1317
  VALUE rb_table_map = rb_hash_aref(wrapper->rb_table_maps, rb_table_id);
1196
- const uint8_t *column_bitmap =
1197
- (const uint8_t *)(e->column_bitmap);
1198
- const uint8_t *column_update_bitmap =
1199
- (const uint8_t *)(e->column_update_bitmap);
1200
1318
  rb_iv_set(rb_event, "@table_id", rb_table_id);
1201
1319
  rb_iv_set(rb_event, "@table_map", rb_table_map);
1202
1320
  rb_iv_set(rb_event, "@rows_flags", USHORT2NUM(e->flags));
@@ -1205,24 +1323,15 @@ rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
1205
1323
  if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
1206
1324
  rb_updated_rows = rb_ary_new();
1207
1325
  }
1208
- const uint8_t *row_data = e->row_data;
1209
- const uint8_t *row_data_end = row_data + e->row_data_size;
1210
1326
  if (!RB_NIL_P(rb_table_map)) {
1211
- VALUE rb_columns = rb_iv_get(rb_table_map, "@columns");
1212
- while (row_data < row_data_end) {
1213
- VALUE rb_row = rbm2_row_parse(&row_data,
1214
- e->column_count,
1215
- column_bitmap,
1216
- rb_columns);
1217
- rb_ary_push(rb_rows, rb_row);
1218
- if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
1219
- VALUE rb_updated_row = rbm2_row_parse(&row_data,
1220
- e->column_count,
1221
- column_update_bitmap,
1222
- rb_columns);
1223
- rb_ary_push(rb_updated_rows, rb_updated_row);
1224
- }
1225
- }
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);
1226
1335
  }
1227
1336
  rb_iv_set(rb_event, "@rows", rb_rows);
1228
1337
  if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
@@ -1304,9 +1413,13 @@ Init_mysql2_replication(void)
1304
1413
  rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
1305
1414
 
1306
1415
  VALUE rb_mMysql2 = rb_const_get(rb_cObject, rb_intern("Mysql2"));
1307
- rb_cMysql2Error = rb_const_get(rb_mMysql2, rb_intern("Error"));
1416
+ rb_eMysql2Error = rb_const_get(rb_mMysql2, rb_intern("Error"));
1308
1417
 
1309
1418
  VALUE rb_mMysql2Replication = rb_define_module("Mysql2Replication");
1419
+ rb_eMysql2ReplicationError =
1420
+ rb_define_class_under(rb_mMysql2Replication,
1421
+ "Error",
1422
+ rb_eStandardError);
1310
1423
 
1311
1424
  rb_cMysql2ReplicationEvent =
1312
1425
  rb_define_class_under(rb_mMysql2Replication, "Event", rb_cObject);
@@ -1,3 +1,3 @@
1
1
  module Mysql2Replication
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.5"
3
3
  end
@@ -35,4 +35,6 @@ Gem::Specification.new do |spec|
35
35
  end
36
36
 
37
37
  spec.add_runtime_dependency("mysql2")
38
+ spec.add_runtime_dependency("native-package-installer")
39
+ spec.add_runtime_dependency("pkg-config")
38
40
  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.1
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: 2021-12-21 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
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: native-package-installer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pkg-config
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  description: ''
28
56
  email:
29
57
  - kou@clear-code.com
@@ -62,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
90
  - !ruby/object:Gem::Version
63
91
  version: '0'
64
92
  requirements: []
65
- rubygems_version: 3.3.0.dev
93
+ rubygems_version: 3.4.0.dev
66
94
  signing_key:
67
95
  specification_version: 4
68
96
  summary: mysql2-replication is an extension of [mysql2 gem](https://rubygems.org/gems/mysql2).