mysql2-replication 1.0.0 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/mysql2-replication/extconf.rb +62 -0
- data/ext/mysql2-replication/mysql2_replication.c +1435 -0
- data/lib/mysql2-replication/version.rb +1 -1
- data/mysql2-replication.gemspec +5 -1
- metadata +36 -5
@@ -0,0 +1,1435 @@
|
|
1
|
+
#include <stdbool.h>
|
2
|
+
|
3
|
+
#include <ruby.h>
|
4
|
+
#include <ruby/encoding.h>
|
5
|
+
#include <ruby/thread.h>
|
6
|
+
|
7
|
+
/* libmariadb */
|
8
|
+
#include <mysql.h>
|
9
|
+
#include <mariadb_com.h>
|
10
|
+
#include <mariadb_rpl.h>
|
11
|
+
|
12
|
+
/* mysql2 */
|
13
|
+
#include <client.h>
|
14
|
+
|
15
|
+
|
16
|
+
#ifndef RUBY_LL2NUM
|
17
|
+
# define RUBY_LL2NUM LL2NUM
|
18
|
+
#endif
|
19
|
+
|
20
|
+
|
21
|
+
void Init_mysql2_replication(void);
|
22
|
+
|
23
|
+
static VALUE rb_cDate;
|
24
|
+
|
25
|
+
static VALUE rb_cMysql2Error;
|
26
|
+
|
27
|
+
static VALUE rb_cMysql2ReplicationEvent;
|
28
|
+
static VALUE rb_cMysql2ReplicationRotateEvent;
|
29
|
+
static VALUE rb_cMysql2ReplicationFormatDescriptionEvent;
|
30
|
+
static VALUE rb_cMysql2ReplicationTableMapEvent;
|
31
|
+
static VALUE rb_cMysql2ReplicationWriteRowsEvent;
|
32
|
+
static VALUE rb_cMysql2ReplicationUpdateRowsEvent;
|
33
|
+
static VALUE rb_cMysql2ReplicationDeleteRowsEvent;
|
34
|
+
|
35
|
+
static VALUE
|
36
|
+
rbm2_replication_rows_event_statement_end_p(VALUE self)
|
37
|
+
{
|
38
|
+
return (NUM2USHORT(rb_iv_get(self, "@rows_flags")) & FL_STMT_END) ?
|
39
|
+
RUBY_Qtrue : RUBY_Qfalse;
|
40
|
+
}
|
41
|
+
|
42
|
+
static inline int8_t
|
43
|
+
rbm2_read_int8(const uint8_t *data)
|
44
|
+
{
|
45
|
+
return *((const int8_t *)data);
|
46
|
+
}
|
47
|
+
|
48
|
+
static inline uint8_t
|
49
|
+
rbm2_read_uint8(const uint8_t *data)
|
50
|
+
{
|
51
|
+
return *data;
|
52
|
+
}
|
53
|
+
|
54
|
+
static inline int16_t
|
55
|
+
rbm2_read_int16(const uint8_t *data)
|
56
|
+
{
|
57
|
+
return *((const int16_t *)data);
|
58
|
+
}
|
59
|
+
|
60
|
+
static inline uint16_t
|
61
|
+
rbm2_read_uint16(const uint8_t *data)
|
62
|
+
{
|
63
|
+
return *((const uint16_t *)data);
|
64
|
+
}
|
65
|
+
|
66
|
+
static inline uint16_t
|
67
|
+
rbm2_read_uint16_bigendian(const uint8_t *data)
|
68
|
+
{
|
69
|
+
return (((uint32_t)(data[0]) << 8) +
|
70
|
+
((uint32_t)(data[1])));
|
71
|
+
}
|
72
|
+
|
73
|
+
static inline int32_t
|
74
|
+
rbm2_read_int24(const uint8_t *data)
|
75
|
+
{
|
76
|
+
uint32_t value = (((uint32_t)(data[0])) |
|
77
|
+
((uint32_t)(data[1]) << 8) |
|
78
|
+
((uint32_t)(data[2]) << 16));
|
79
|
+
if (data[2] & 128) {
|
80
|
+
return (int32_t)(value | (255 << 24));
|
81
|
+
} else {
|
82
|
+
return value;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
static inline uint32_t
|
87
|
+
rbm2_read_uint24(const uint8_t *data)
|
88
|
+
{
|
89
|
+
return (((uint32_t)(data[0])) +
|
90
|
+
((uint32_t)(data[1]) << 8) +
|
91
|
+
((uint32_t)(data[2]) << 16));
|
92
|
+
}
|
93
|
+
|
94
|
+
static inline uint32_t
|
95
|
+
rbm2_read_uint24_bigendian(const uint8_t *data)
|
96
|
+
{
|
97
|
+
return (((uint32_t)(data[0]) << 16) +
|
98
|
+
((uint32_t)(data[1]) << 8) +
|
99
|
+
((uint32_t)(data[2])));
|
100
|
+
}
|
101
|
+
|
102
|
+
static inline int32_t
|
103
|
+
rbm2_read_int32(const uint8_t *data)
|
104
|
+
{
|
105
|
+
return *((const int32_t *)data);
|
106
|
+
}
|
107
|
+
|
108
|
+
static inline uint32_t
|
109
|
+
rbm2_read_uint32(const uint8_t *data)
|
110
|
+
{
|
111
|
+
return *((const uint32_t *)data);
|
112
|
+
}
|
113
|
+
|
114
|
+
static inline uint32_t
|
115
|
+
rbm2_read_uint32_bigendian(const uint8_t *data)
|
116
|
+
{
|
117
|
+
return (((uint32_t)(data[0]) << 24) +
|
118
|
+
((uint32_t)(data[1]) << 16) +
|
119
|
+
((uint32_t)(data[2]) << 8) +
|
120
|
+
((uint32_t)(data[3])));
|
121
|
+
}
|
122
|
+
|
123
|
+
static inline uint64_t
|
124
|
+
rbm2_read_uint40_bigendian(const uint8_t *data)
|
125
|
+
{
|
126
|
+
return (((uint64_t)(data[0]) << 32) +
|
127
|
+
((uint64_t)(data[1]) << 24) +
|
128
|
+
((uint64_t)(data[2]) << 16) +
|
129
|
+
((uint64_t)(data[3]) << 8) +
|
130
|
+
((uint64_t)(data[4])));
|
131
|
+
}
|
132
|
+
|
133
|
+
static inline int64_t
|
134
|
+
rbm2_read_int64(const uint8_t *data)
|
135
|
+
{
|
136
|
+
return *((const int64_t *)data);
|
137
|
+
}
|
138
|
+
|
139
|
+
static inline uint64_t
|
140
|
+
rbm2_read_uint64(const uint8_t *data)
|
141
|
+
{
|
142
|
+
return *((const uint64_t *)data);
|
143
|
+
}
|
144
|
+
|
145
|
+
static ID
|
146
|
+
rbm2_column_type_to_id(enum enum_field_types column_type)
|
147
|
+
{
|
148
|
+
switch (column_type) {
|
149
|
+
case MYSQL_TYPE_DECIMAL:
|
150
|
+
return rb_intern("decimal");
|
151
|
+
case MYSQL_TYPE_TINY:
|
152
|
+
return rb_intern("tiny");
|
153
|
+
case MYSQL_TYPE_SHORT:
|
154
|
+
return rb_intern("short");
|
155
|
+
case MYSQL_TYPE_LONG:
|
156
|
+
return rb_intern("long");
|
157
|
+
case MYSQL_TYPE_FLOAT:
|
158
|
+
return rb_intern("float");
|
159
|
+
case MYSQL_TYPE_DOUBLE:
|
160
|
+
return rb_intern("double");
|
161
|
+
case MYSQL_TYPE_NULL:
|
162
|
+
return rb_intern("null");
|
163
|
+
case MYSQL_TYPE_TIMESTAMP:
|
164
|
+
return rb_intern("timestamp");
|
165
|
+
case MYSQL_TYPE_LONGLONG:
|
166
|
+
return rb_intern("longlong");
|
167
|
+
case MYSQL_TYPE_INT24:
|
168
|
+
return rb_intern("int24");
|
169
|
+
case MYSQL_TYPE_DATE:
|
170
|
+
return rb_intern("date");
|
171
|
+
case MYSQL_TYPE_TIME:
|
172
|
+
return rb_intern("time");
|
173
|
+
case MYSQL_TYPE_DATETIME:
|
174
|
+
return rb_intern("datetime");
|
175
|
+
case MYSQL_TYPE_YEAR:
|
176
|
+
return rb_intern("year");
|
177
|
+
case MYSQL_TYPE_NEWDATE:
|
178
|
+
return rb_intern("newdate");
|
179
|
+
case MYSQL_TYPE_VARCHAR:
|
180
|
+
return rb_intern("varchar");
|
181
|
+
case MYSQL_TYPE_BIT:
|
182
|
+
return rb_intern("bit");
|
183
|
+
case MYSQL_TYPE_TIMESTAMP2:
|
184
|
+
return rb_intern("timestamp2");
|
185
|
+
case MYSQL_TYPE_DATETIME2:
|
186
|
+
return rb_intern("datetime2");
|
187
|
+
case MYSQL_TYPE_TIME2:
|
188
|
+
return rb_intern("time2");
|
189
|
+
case MYSQL_TYPE_JSON:
|
190
|
+
return rb_intern("json");
|
191
|
+
case MYSQL_TYPE_NEWDECIMAL:
|
192
|
+
return rb_intern("newdecimal");
|
193
|
+
case MYSQL_TYPE_ENUM:
|
194
|
+
return rb_intern("enum");
|
195
|
+
case MYSQL_TYPE_SET:
|
196
|
+
return rb_intern("set");
|
197
|
+
case MYSQL_TYPE_TINY_BLOB:
|
198
|
+
return rb_intern("tiny_blob");
|
199
|
+
case MYSQL_TYPE_MEDIUM_BLOB:
|
200
|
+
return rb_intern("medium_blob");
|
201
|
+
case MYSQL_TYPE_LONG_BLOB:
|
202
|
+
return rb_intern("long_blob");
|
203
|
+
case MYSQL_TYPE_BLOB:
|
204
|
+
return rb_intern("blob");
|
205
|
+
case MYSQL_TYPE_VAR_STRING:
|
206
|
+
return rb_intern("var_string");
|
207
|
+
case MYSQL_TYPE_STRING:
|
208
|
+
return rb_intern("string");
|
209
|
+
case MYSQL_TYPE_GEOMETRY:
|
210
|
+
return rb_intern("geometry");
|
211
|
+
default:
|
212
|
+
return rb_intern("unknown");
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
static VALUE
|
217
|
+
rbm2_column_type_to_symbol(enum enum_field_types column_type)
|
218
|
+
{
|
219
|
+
return rb_id2sym(rbm2_column_type_to_id(column_type));
|
220
|
+
}
|
221
|
+
|
222
|
+
static void
|
223
|
+
rbm2_metadata_parse(enum enum_field_types *column_type,
|
224
|
+
const uint8_t **metadata,
|
225
|
+
VALUE rb_column)
|
226
|
+
{
|
227
|
+
switch (*column_type) {
|
228
|
+
case MYSQL_TYPE_DECIMAL:
|
229
|
+
case MYSQL_TYPE_TINY:
|
230
|
+
case MYSQL_TYPE_SHORT:
|
231
|
+
case MYSQL_TYPE_LONG:
|
232
|
+
break;
|
233
|
+
case MYSQL_TYPE_FLOAT:
|
234
|
+
case MYSQL_TYPE_DOUBLE:
|
235
|
+
rb_hash_aset(rb_column,
|
236
|
+
rb_id2sym(rb_intern("size")),
|
237
|
+
UINT2NUM((*metadata)[0]));
|
238
|
+
(*metadata) += 1;
|
239
|
+
break;
|
240
|
+
case MYSQL_TYPE_NULL:
|
241
|
+
case MYSQL_TYPE_TIMESTAMP:
|
242
|
+
case MYSQL_TYPE_LONGLONG:
|
243
|
+
case MYSQL_TYPE_INT24:
|
244
|
+
case MYSQL_TYPE_DATE:
|
245
|
+
case MYSQL_TYPE_TIME:
|
246
|
+
case MYSQL_TYPE_DATETIME:
|
247
|
+
case MYSQL_TYPE_YEAR:
|
248
|
+
case MYSQL_TYPE_NEWDATE:
|
249
|
+
break;
|
250
|
+
case MYSQL_TYPE_VARCHAR:
|
251
|
+
rb_hash_aset(rb_column,
|
252
|
+
rb_id2sym(rb_intern("max_length")),
|
253
|
+
UINT2NUM(rbm2_read_uint16(*metadata)));
|
254
|
+
(*metadata) += 2;
|
255
|
+
break;
|
256
|
+
case MYSQL_TYPE_BIT:
|
257
|
+
{
|
258
|
+
uint8_t bits = (*metadata)[0];
|
259
|
+
uint8_t bytes = (*metadata)[1];
|
260
|
+
rb_hash_aset(rb_column,
|
261
|
+
rb_id2sym(rb_intern("bits")),
|
262
|
+
UINT2NUM((bytes * 8) + bits));
|
263
|
+
(*metadata) += 2;
|
264
|
+
}
|
265
|
+
break;
|
266
|
+
case MYSQL_TYPE_TIMESTAMP2:
|
267
|
+
case MYSQL_TYPE_DATETIME2:
|
268
|
+
case MYSQL_TYPE_TIME2:
|
269
|
+
rb_hash_aset(rb_column,
|
270
|
+
rb_id2sym(rb_intern("decimals")),
|
271
|
+
UINT2NUM((*metadata)[0]));
|
272
|
+
(*metadata) += 1;
|
273
|
+
break;
|
274
|
+
case MYSQL_TYPE_JSON:
|
275
|
+
rb_hash_aset(rb_column,
|
276
|
+
rb_id2sym(rb_intern("length_size")),
|
277
|
+
UINT2NUM((*metadata)[0]));
|
278
|
+
(*metadata) += 1;
|
279
|
+
break;
|
280
|
+
case MYSQL_TYPE_NEWDECIMAL:
|
281
|
+
rb_hash_aset(rb_column,
|
282
|
+
rb_id2sym(rb_intern("precision")),
|
283
|
+
UINT2NUM((*metadata)[0]));
|
284
|
+
rb_hash_aset(rb_column,
|
285
|
+
rb_id2sym(rb_intern("scale")),
|
286
|
+
UINT2NUM((*metadata)[1]));
|
287
|
+
(*metadata) += 2;
|
288
|
+
break;
|
289
|
+
case MYSQL_TYPE_ENUM:
|
290
|
+
case MYSQL_TYPE_SET:
|
291
|
+
rb_hash_aset(rb_column,
|
292
|
+
rb_id2sym(rb_intern("size")),
|
293
|
+
UINT2NUM((*metadata)[1]));
|
294
|
+
(*metadata) += 2;
|
295
|
+
break;
|
296
|
+
case MYSQL_TYPE_TINY_BLOB:
|
297
|
+
case MYSQL_TYPE_MEDIUM_BLOB:
|
298
|
+
case MYSQL_TYPE_LONG_BLOB:
|
299
|
+
break;
|
300
|
+
case MYSQL_TYPE_BLOB:
|
301
|
+
rb_hash_aset(rb_column,
|
302
|
+
rb_id2sym(rb_intern("length_size")),
|
303
|
+
UINT2NUM((*metadata)[0]));
|
304
|
+
(*metadata) += 1;
|
305
|
+
break;
|
306
|
+
case MYSQL_TYPE_VAR_STRING:
|
307
|
+
case MYSQL_TYPE_STRING:
|
308
|
+
{
|
309
|
+
/* See also Field_string::do_save_field_metadata() */
|
310
|
+
*column_type = (*metadata)[0];
|
311
|
+
switch (*column_type) {
|
312
|
+
case MYSQL_TYPE_ENUM:
|
313
|
+
case MYSQL_TYPE_SET:
|
314
|
+
rb_hash_aset(rb_column,
|
315
|
+
rb_id2sym(rb_intern("size")),
|
316
|
+
UINT2NUM((*metadata)[1]));
|
317
|
+
break;
|
318
|
+
default:
|
319
|
+
rb_hash_aset(rb_column,
|
320
|
+
rb_id2sym(rb_intern("max_length")),
|
321
|
+
UINT2NUM((((((*metadata)[0] >> 4) & 0x03) ^ 0x03) << 8) +
|
322
|
+
(*metadata)[1]));
|
323
|
+
break;
|
324
|
+
}
|
325
|
+
(*metadata) += 2;
|
326
|
+
}
|
327
|
+
break;
|
328
|
+
case MYSQL_TYPE_GEOMETRY:
|
329
|
+
rb_hash_aset(rb_column,
|
330
|
+
rb_id2sym(rb_intern("length_size")),
|
331
|
+
UINT2NUM((*metadata)[0]));
|
332
|
+
(*metadata) += 1;
|
333
|
+
break;
|
334
|
+
default:
|
335
|
+
break;
|
336
|
+
}
|
337
|
+
}
|
338
|
+
|
339
|
+
static inline VALUE
|
340
|
+
rbm2_column_parse_variable_length_string(VALUE rb_column,
|
341
|
+
const uint8_t **row_data)
|
342
|
+
{
|
343
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_varchar-and-other-variable-length-string-types */
|
344
|
+
uint32_t max_length =
|
345
|
+
NUM2UINT(rb_hash_aref(rb_column,
|
346
|
+
rb_id2sym(rb_intern("max_length"))));
|
347
|
+
VALUE rb_value;
|
348
|
+
if (max_length > 255) {
|
349
|
+
uint16_t length = rbm2_read_uint16(*row_data);
|
350
|
+
(*row_data) += 2;
|
351
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
352
|
+
length);
|
353
|
+
(*row_data) += length;
|
354
|
+
} else {
|
355
|
+
uint8_t length = rbm2_read_uint8(*row_data);
|
356
|
+
(*row_data) += 1;
|
357
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
358
|
+
length);
|
359
|
+
(*row_data) += length;
|
360
|
+
}
|
361
|
+
return rb_value;
|
362
|
+
}
|
363
|
+
|
364
|
+
static inline VALUE
|
365
|
+
rbm2_column_parse_blob(VALUE rb_column,
|
366
|
+
const uint8_t **row_data)
|
367
|
+
{
|
368
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_blob-and-other-blob-types */
|
369
|
+
uint32_t length_size =
|
370
|
+
NUM2UINT(rb_hash_aref(rb_column,
|
371
|
+
rb_id2sym(rb_intern("length_size"))));
|
372
|
+
VALUE rb_value;
|
373
|
+
switch (length_size) {
|
374
|
+
case 1:
|
375
|
+
{
|
376
|
+
uint8_t length = rbm2_read_uint8(*row_data);
|
377
|
+
(*row_data) += 1;
|
378
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
379
|
+
length);
|
380
|
+
(*row_data) += length;
|
381
|
+
}
|
382
|
+
break;
|
383
|
+
case 2:
|
384
|
+
{
|
385
|
+
uint16_t length = rbm2_read_uint16(*row_data);
|
386
|
+
(*row_data) += 2;
|
387
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
388
|
+
length);
|
389
|
+
(*row_data) += length;
|
390
|
+
}
|
391
|
+
break;
|
392
|
+
case 3:
|
393
|
+
{
|
394
|
+
uint32_t length = rbm2_read_uint24(*row_data);
|
395
|
+
(*row_data) += 3;
|
396
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
397
|
+
length);
|
398
|
+
(*row_data) += length;
|
399
|
+
}
|
400
|
+
break;
|
401
|
+
case 4:
|
402
|
+
{
|
403
|
+
uint32_t length = rbm2_read_uint32(*row_data);
|
404
|
+
(*row_data) += 4;
|
405
|
+
rb_value = rb_str_new((const char *)(*row_data),
|
406
|
+
length);
|
407
|
+
(*row_data) += length;
|
408
|
+
}
|
409
|
+
break;
|
410
|
+
default:
|
411
|
+
rb_raise(rb_eNotImpError,
|
412
|
+
"unsupported length size for blob: %u",
|
413
|
+
length_size);
|
414
|
+
break;
|
415
|
+
}
|
416
|
+
return rb_value;
|
417
|
+
}
|
418
|
+
|
419
|
+
static VALUE
|
420
|
+
rbm2_column_parse(VALUE rb_column, const uint8_t **row_data)
|
421
|
+
{
|
422
|
+
VALUE rb_value = RUBY_Qnil;
|
423
|
+
VALUE rb_type = rb_hash_aref(rb_column, rb_id2sym(rb_intern("type")));
|
424
|
+
VALUE rb_type_id = rb_hash_aref(rb_column, rb_id2sym(rb_intern("type_id")));
|
425
|
+
enum enum_field_types type = NUM2UINT(rb_type_id);
|
426
|
+
switch (type) {
|
427
|
+
case MYSQL_TYPE_DECIMAL:
|
428
|
+
rb_raise(rb_eNotImpError,
|
429
|
+
"decimal type isn't implemented yet: %+" PRIsVALUE,
|
430
|
+
rb_type);
|
431
|
+
break;
|
432
|
+
case MYSQL_TYPE_TINY:
|
433
|
+
rb_value = RB_CHR2FIX(*(*row_data));
|
434
|
+
(*row_data) += 1;
|
435
|
+
break;
|
436
|
+
case MYSQL_TYPE_SHORT:
|
437
|
+
rb_value = RB_INT2NUM(rbm2_read_int16(*row_data));
|
438
|
+
(*row_data) += 2;
|
439
|
+
break;
|
440
|
+
case MYSQL_TYPE_LONG:
|
441
|
+
rb_value = RB_INT2NUM(rbm2_read_int32(*row_data));
|
442
|
+
(*row_data) += 4;
|
443
|
+
break;
|
444
|
+
case MYSQL_TYPE_FLOAT:
|
445
|
+
rb_value = rb_float_new(*((const float *)(*row_data)));
|
446
|
+
(*row_data) += 4;
|
447
|
+
break;
|
448
|
+
case MYSQL_TYPE_DOUBLE:
|
449
|
+
rb_value = rb_float_new(*((const double *)(*row_data)));
|
450
|
+
(*row_data) += 8;
|
451
|
+
break;
|
452
|
+
case MYSQL_TYPE_NULL:
|
453
|
+
break;
|
454
|
+
case MYSQL_TYPE_TIMESTAMP:
|
455
|
+
rb_value = rb_funcall(rb_cTime,
|
456
|
+
rb_intern("at"),
|
457
|
+
1,
|
458
|
+
RB_UINT2NUM(rbm2_read_uint32(*row_data)));
|
459
|
+
(*row_data) += 4;
|
460
|
+
break;
|
461
|
+
case MYSQL_TYPE_LONGLONG:
|
462
|
+
rb_value = RB_LL2NUM(rbm2_read_int64(*row_data));
|
463
|
+
(*row_data) += 8;
|
464
|
+
break;
|
465
|
+
case MYSQL_TYPE_INT24:
|
466
|
+
rb_value = RB_INT2NUM(rbm2_read_int24(*row_data));
|
467
|
+
(*row_data) += 3;
|
468
|
+
break;
|
469
|
+
case MYSQL_TYPE_DATE:
|
470
|
+
{
|
471
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_date */
|
472
|
+
uint32_t raw_date = rbm2_read_uint24(*row_data);
|
473
|
+
/*
|
474
|
+
YYYYYYYMMMMDDDDD
|
475
|
+
Y: 6bit
|
476
|
+
M: 4bit
|
477
|
+
D: 5bit
|
478
|
+
*/
|
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))));
|
485
|
+
(*row_data) += 3;
|
486
|
+
}
|
487
|
+
break;
|
488
|
+
case MYSQL_TYPE_TIME:
|
489
|
+
{
|
490
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_time */
|
491
|
+
uint32_t raw_time = rbm2_read_uint24(*row_data);
|
492
|
+
/* HHMMSS */
|
493
|
+
rb_value = rb_sprintf("%02u:%02u:%02u",
|
494
|
+
(raw_time / (10 * 4)),
|
495
|
+
(raw_time % (10 * 4)) / (10 * 2),
|
496
|
+
(raw_time % (10 * 2)));
|
497
|
+
(*row_data) += 3;
|
498
|
+
}
|
499
|
+
break;
|
500
|
+
case MYSQL_TYPE_DATETIME:
|
501
|
+
{
|
502
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_datetime */
|
503
|
+
uint64_t raw_time = rbm2_read_uint64(*row_data);
|
504
|
+
/* 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)));
|
514
|
+
(*row_data) += 8;
|
515
|
+
}
|
516
|
+
break;
|
517
|
+
case MYSQL_TYPE_YEAR:
|
518
|
+
rb_value = RB_UINT2NUM(rbm2_read_uint8(*row_data) + 1900);
|
519
|
+
(*row_data) += 1;
|
520
|
+
break;
|
521
|
+
case MYSQL_TYPE_NEWDATE:
|
522
|
+
rb_raise(rb_eNotImpError,
|
523
|
+
"newdate type isn't implemented yet: %+" PRIsVALUE,
|
524
|
+
rb_type);
|
525
|
+
break;
|
526
|
+
case MYSQL_TYPE_VARCHAR:
|
527
|
+
rb_value = rbm2_column_parse_variable_length_string(rb_column, row_data);
|
528
|
+
break;
|
529
|
+
case MYSQL_TYPE_BIT:
|
530
|
+
{
|
531
|
+
uint8_t bits =
|
532
|
+
RB_NUM2UINT(rb_hash_aref(rb_column,
|
533
|
+
rb_id2sym(rb_intern("bits"))));
|
534
|
+
switch ((bits + 7) / 8) {
|
535
|
+
case 1:
|
536
|
+
rb_value = RB_UINT2NUM(rbm2_read_uint8(*row_data));
|
537
|
+
(*row_data) += 1;
|
538
|
+
break;
|
539
|
+
case 2:
|
540
|
+
rb_value = RB_UINT2NUM(rbm2_read_uint16(*row_data));
|
541
|
+
(*row_data) += 2;
|
542
|
+
break;
|
543
|
+
case 3:
|
544
|
+
rb_value = RB_UINT2NUM(rbm2_read_uint24(*row_data));
|
545
|
+
(*row_data) += 3;
|
546
|
+
break;
|
547
|
+
case 4:
|
548
|
+
rb_value = RB_UINT2NUM(rbm2_read_uint32(*row_data));
|
549
|
+
(*row_data) += 4;
|
550
|
+
break;
|
551
|
+
default :
|
552
|
+
rb_raise(rb_eNotImpError,
|
553
|
+
"%d bit type isn't implemented yet: %+" PRIsVALUE,
|
554
|
+
bits,
|
555
|
+
rb_type);
|
556
|
+
break;
|
557
|
+
}
|
558
|
+
}
|
559
|
+
break;
|
560
|
+
case MYSQL_TYPE_TIMESTAMP2:
|
561
|
+
{
|
562
|
+
/* https://mariadb.com/kb/en/rows_event_v1/#mysql_type_timestamp2 */
|
563
|
+
uint32_t decimals =
|
564
|
+
RB_NUM2UINT(rb_hash_aref(rb_column,
|
565
|
+
rb_id2sym(rb_intern("decimals"))));
|
566
|
+
uint32_t seconds = rbm2_read_uint32_bigendian(*row_data);
|
567
|
+
(*row_data) += 4;
|
568
|
+
uint32_t fractional_seconds = 0;
|
569
|
+
switch ((decimals + 1) / 2) {
|
570
|
+
case 1:
|
571
|
+
fractional_seconds = rbm2_read_uint8(*row_data) * 10000;
|
572
|
+
(*row_data) += 1;
|
573
|
+
break;
|
574
|
+
case 2:
|
575
|
+
fractional_seconds = rbm2_read_uint16_bigendian(*row_data) * 100;
|
576
|
+
(*row_data) += 2;
|
577
|
+
break;
|
578
|
+
case 3:
|
579
|
+
fractional_seconds = rbm2_read_uint24_bigendian(*row_data);
|
580
|
+
(*row_data) += 3;
|
581
|
+
break;
|
582
|
+
default :
|
583
|
+
break;
|
584
|
+
}
|
585
|
+
rb_value = rb_funcall(rb_cTime,
|
586
|
+
rb_intern("at"),
|
587
|
+
2,
|
588
|
+
UINT2NUM(seconds),
|
589
|
+
UINT2NUM(fractional_seconds));
|
590
|
+
}
|
591
|
+
break;
|
592
|
+
case MYSQL_TYPE_DATETIME2:
|
593
|
+
{
|
594
|
+
/*
|
595
|
+
See the documentation of TIME_to_longlong_datetime_packed().
|
596
|
+
|
597
|
+
https://github.com/mysql/mysql-server/blob/mysql-8.0.27/mysys/my_time.cc#L1672-L1691
|
598
|
+
*/
|
599
|
+
uint64_t integer_part = rbm2_read_uint40_bigendian(*row_data);
|
600
|
+
(*row_data) += 5;
|
601
|
+
uint32_t fractional_seconds = 0;
|
602
|
+
uint32_t decimals =
|
603
|
+
NUM2UINT(rb_hash_aref(rb_column,
|
604
|
+
rb_id2sym(rb_intern("decimals"))));
|
605
|
+
switch ((decimals + 1) / 2) {
|
606
|
+
case 1:
|
607
|
+
fractional_seconds = rbm2_read_uint8(*row_data) * 10000;
|
608
|
+
(*row_data) += 1;
|
609
|
+
break;
|
610
|
+
case 2:
|
611
|
+
fractional_seconds = rbm2_read_uint16_bigendian(*row_data) * 100;
|
612
|
+
(*row_data) += 2;
|
613
|
+
break;
|
614
|
+
case 3:
|
615
|
+
fractional_seconds = rbm2_read_uint24_bigendian(*row_data);
|
616
|
+
(*row_data) += 3;
|
617
|
+
break;
|
618
|
+
default :
|
619
|
+
break;
|
620
|
+
}
|
621
|
+
uint32_t symd = integer_part >> 17;
|
622
|
+
uint32_t sym = symd >> 5;
|
623
|
+
uint32_t sign = sym >> 17;
|
624
|
+
uint32_t ym = sym % (1 << 17);
|
625
|
+
uint32_t year = ym / 13;
|
626
|
+
if (sign == 0) {
|
627
|
+
year = -year;
|
628
|
+
}
|
629
|
+
uint32_t month = ym % 13;
|
630
|
+
uint32_t day = symd % (1 << 5);
|
631
|
+
uint32_t hms = integer_part % (1 << 17);
|
632
|
+
uint32_t hour = hms >> 12;
|
633
|
+
uint32_t minute = (hms >> 6) % (1 << 6);
|
634
|
+
uint32_t second = hms % (1 << 6);
|
635
|
+
rb_value = rb_funcall(rb_cTime,
|
636
|
+
rb_intern("utc"),
|
637
|
+
7,
|
638
|
+
UINT2NUM(year),
|
639
|
+
UINT2NUM(month),
|
640
|
+
UINT2NUM(day),
|
641
|
+
UINT2NUM(hour),
|
642
|
+
UINT2NUM(minute),
|
643
|
+
UINT2NUM(second),
|
644
|
+
UINT2NUM(fractional_seconds));
|
645
|
+
}
|
646
|
+
break;
|
647
|
+
case MYSQL_TYPE_TIME2:
|
648
|
+
rb_raise(rb_eNotImpError,
|
649
|
+
"time2 type isn't implemented yet: %+" PRIsVALUE,
|
650
|
+
rb_type);
|
651
|
+
break;
|
652
|
+
case MYSQL_TYPE_JSON:
|
653
|
+
rb_value = rbm2_column_parse_blob(rb_column, row_data);
|
654
|
+
break;
|
655
|
+
case MYSQL_TYPE_NEWDECIMAL:
|
656
|
+
{
|
657
|
+
/* TODO: See also bin2decimal(). */
|
658
|
+
const uint32_t digits_per_integer = 9;
|
659
|
+
const int32_t compressed_bytes[] = {0, 1, 1, 2, 3, 3, 4, 4, 4};
|
660
|
+
uint32_t precision =
|
661
|
+
NUM2UINT(rb_hash_aref(rb_column,
|
662
|
+
rb_id2sym(rb_intern("precision"))));
|
663
|
+
uint32_t scale =
|
664
|
+
NUM2UINT(rb_hash_aref(rb_column,
|
665
|
+
rb_id2sym(rb_intern("scale"))));
|
666
|
+
uint32_t integral = precision - scale;
|
667
|
+
uint32_t uncompressed_integral = integral / digits_per_integer;
|
668
|
+
uint32_t uncompressed_fractional = scale / digits_per_integer;
|
669
|
+
uint32_t compressed_integral =
|
670
|
+
integral - (uncompressed_integral * digits_per_integer);
|
671
|
+
uint32_t compressed_fractional =
|
672
|
+
scale - (uncompressed_fractional * digits_per_integer);
|
673
|
+
|
674
|
+
(*row_data) += compressed_bytes[compressed_integral];
|
675
|
+
if (uncompressed_integral > 1) {
|
676
|
+
(*row_data) += (4 * (uncompressed_integral - 1));
|
677
|
+
}
|
678
|
+
if (uncompressed_fractional > 1) {
|
679
|
+
(*row_data) += (4 * (uncompressed_fractional - 1));
|
680
|
+
}
|
681
|
+
(*row_data) += compressed_bytes[compressed_fractional];
|
682
|
+
}
|
683
|
+
break;
|
684
|
+
case MYSQL_TYPE_ENUM:
|
685
|
+
case MYSQL_TYPE_SET:
|
686
|
+
rb_raise(rb_eNotImpError,
|
687
|
+
"enum/set types aren't implemented yet: %+" PRIsVALUE,
|
688
|
+
rb_type);
|
689
|
+
break;
|
690
|
+
case MYSQL_TYPE_TINY_BLOB:
|
691
|
+
case MYSQL_TYPE_MEDIUM_BLOB:
|
692
|
+
case MYSQL_TYPE_LONG_BLOB:
|
693
|
+
rb_raise(rb_eNotImpError,
|
694
|
+
"blob types aren't implemented yet: %+" PRIsVALUE,
|
695
|
+
rb_type);
|
696
|
+
break;
|
697
|
+
case MYSQL_TYPE_BLOB:
|
698
|
+
rb_value = rbm2_column_parse_blob(rb_column, row_data);
|
699
|
+
break;
|
700
|
+
case MYSQL_TYPE_VAR_STRING:
|
701
|
+
rb_value = rbm2_column_parse_variable_length_string(rb_column, row_data);
|
702
|
+
break;
|
703
|
+
case MYSQL_TYPE_STRING:
|
704
|
+
rb_value = rbm2_column_parse_variable_length_string(rb_column, row_data);
|
705
|
+
break;
|
706
|
+
case MYSQL_TYPE_GEOMETRY:
|
707
|
+
rb_raise(rb_eNotImpError,
|
708
|
+
"geometry type isn't implemented yet: %+" PRIsVALUE,
|
709
|
+
rb_type);
|
710
|
+
break;
|
711
|
+
default:
|
712
|
+
rb_raise(rb_eNotImpError,
|
713
|
+
"unknown type isn't implemented yet: %+" PRIsVALUE,
|
714
|
+
rb_type);
|
715
|
+
break;
|
716
|
+
}
|
717
|
+
return rb_value;
|
718
|
+
}
|
719
|
+
|
720
|
+
static inline bool
|
721
|
+
rbm2_bitmap_is_set(const uint8_t *bitmap, uint32_t i)
|
722
|
+
{
|
723
|
+
return (bitmap[i >> 3] >> (i & 0x07)) & 1;
|
724
|
+
}
|
725
|
+
|
726
|
+
typedef struct
|
727
|
+
{
|
728
|
+
MARIADB_RPL *rpl;
|
729
|
+
MARIADB_RPL_EVENT *rpl_event;
|
730
|
+
VALUE rb_client;
|
731
|
+
VALUE rb_table_maps;
|
732
|
+
bool force_disable_use_checksum;
|
733
|
+
} rbm2_replication_client_wrapper;
|
734
|
+
|
735
|
+
static void
|
736
|
+
rbm2_replication_client_mark(void *data)
|
737
|
+
{
|
738
|
+
rbm2_replication_client_wrapper *wrapper = data;
|
739
|
+
rb_gc_mark(wrapper->rb_client);
|
740
|
+
rb_gc_mark(wrapper->rb_table_maps);
|
741
|
+
}
|
742
|
+
|
743
|
+
static void
|
744
|
+
rbm2_replication_client_free(void *data)
|
745
|
+
{
|
746
|
+
rbm2_replication_client_wrapper *wrapper = data;
|
747
|
+
if (wrapper->rpl_event) {
|
748
|
+
mariadb_free_rpl_event(wrapper->rpl_event);
|
749
|
+
}
|
750
|
+
if (wrapper->rpl) {
|
751
|
+
mariadb_rpl_close(wrapper->rpl);
|
752
|
+
}
|
753
|
+
ruby_xfree(wrapper);
|
754
|
+
}
|
755
|
+
|
756
|
+
static const rb_data_type_t rbm2_replication_client_type = {
|
757
|
+
"Mysql2Replication::Client",
|
758
|
+
{
|
759
|
+
rbm2_replication_client_mark,
|
760
|
+
rbm2_replication_client_free,
|
761
|
+
},
|
762
|
+
NULL,
|
763
|
+
NULL,
|
764
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
765
|
+
};
|
766
|
+
|
767
|
+
static VALUE
|
768
|
+
rbm2_replication_client_alloc(VALUE klass)
|
769
|
+
{
|
770
|
+
rbm2_replication_client_wrapper *wrapper;
|
771
|
+
VALUE rb_wrapper = TypedData_Make_Struct(klass,
|
772
|
+
rbm2_replication_client_wrapper,
|
773
|
+
&rbm2_replication_client_type,
|
774
|
+
wrapper);
|
775
|
+
wrapper->rpl = NULL;
|
776
|
+
wrapper->rpl_event = NULL;
|
777
|
+
wrapper->rb_client = RUBY_Qnil;
|
778
|
+
wrapper->rb_table_maps = rb_hash_new();
|
779
|
+
return rb_wrapper;
|
780
|
+
}
|
781
|
+
|
782
|
+
static inline rbm2_replication_client_wrapper *
|
783
|
+
rbm2_replication_client_get_wrapper(VALUE self)
|
784
|
+
{
|
785
|
+
rbm2_replication_client_wrapper *wrapper;
|
786
|
+
TypedData_Get_Struct(self,
|
787
|
+
rbm2_replication_client_wrapper,
|
788
|
+
&rbm2_replication_client_type,
|
789
|
+
wrapper);
|
790
|
+
return wrapper;
|
791
|
+
}
|
792
|
+
|
793
|
+
static inline mysql_client_wrapper *
|
794
|
+
rbm2_replication_client_wrapper_get_client_wrapper(
|
795
|
+
rbm2_replication_client_wrapper *replication_client_wrapper)
|
796
|
+
{
|
797
|
+
GET_CLIENT(replication_client_wrapper->rb_client);
|
798
|
+
return wrapper;
|
799
|
+
}
|
800
|
+
|
801
|
+
static inline MYSQL *
|
802
|
+
rbm2_replication_client_wrapper_get_client(
|
803
|
+
rbm2_replication_client_wrapper *wrapper)
|
804
|
+
{
|
805
|
+
return rbm2_replication_client_wrapper_get_client_wrapper(wrapper)->client;
|
806
|
+
}
|
807
|
+
|
808
|
+
static void
|
809
|
+
rbm2_replication_client_raise(VALUE self)
|
810
|
+
{
|
811
|
+
rbm2_replication_client_wrapper *wrapper =
|
812
|
+
rbm2_replication_client_get_wrapper(self);
|
813
|
+
mysql_client_wrapper *client_wrapper =
|
814
|
+
rbm2_replication_client_wrapper_get_client_wrapper(wrapper);
|
815
|
+
VALUE rb_error_message =
|
816
|
+
rb_enc_str_new_cstr(mysql_error(client_wrapper->client),
|
817
|
+
rb_utf8_encoding());
|
818
|
+
VALUE rb_sql_state =
|
819
|
+
rb_enc_str_new_cstr(mysql_sqlstate(client_wrapper->client),
|
820
|
+
rb_usascii_encoding());
|
821
|
+
ID new_with_args;
|
822
|
+
CONST_ID(new_with_args, "new_with_args");
|
823
|
+
VALUE rb_error = rb_funcall(rb_cMysql2Error,
|
824
|
+
new_with_args,
|
825
|
+
4,
|
826
|
+
rb_error_message,
|
827
|
+
LONG2NUM(client_wrapper->server_version),
|
828
|
+
UINT2NUM(mysql_errno(client_wrapper->client)),
|
829
|
+
rb_sql_state);
|
830
|
+
rb_exc_raise(rb_error);
|
831
|
+
}
|
832
|
+
|
833
|
+
static VALUE
|
834
|
+
rbm2_replication_client_initialize(int argc, VALUE *argv, VALUE self)
|
835
|
+
{
|
836
|
+
VALUE rb_client;
|
837
|
+
VALUE rb_options;
|
838
|
+
VALUE rb_checksum = RUBY_Qnil;
|
839
|
+
|
840
|
+
rb_scan_args(argc, argv, "10:", &rb_client, &rb_options);
|
841
|
+
if (!RB_NIL_P(rb_options)) {
|
842
|
+
static ID keyword_ids[1];
|
843
|
+
VALUE keyword_args[1];
|
844
|
+
if (keyword_ids[0] == 0) {
|
845
|
+
CONST_ID(keyword_ids[0], "checksum");
|
846
|
+
}
|
847
|
+
rb_get_kwargs(rb_options, keyword_ids, 0, 1, keyword_args);
|
848
|
+
if (keyword_args[0] != RUBY_Qundef) {
|
849
|
+
rb_checksum = keyword_args[0];
|
850
|
+
}
|
851
|
+
}
|
852
|
+
|
853
|
+
rbm2_replication_client_wrapper *wrapper =
|
854
|
+
rbm2_replication_client_get_wrapper(self);
|
855
|
+
wrapper->rb_client = rb_client;
|
856
|
+
wrapper->rpl =
|
857
|
+
mariadb_rpl_init(rbm2_replication_client_wrapper_get_client(wrapper));
|
858
|
+
if (!wrapper->rpl) {
|
859
|
+
rbm2_replication_client_raise(self);
|
860
|
+
}
|
861
|
+
|
862
|
+
{
|
863
|
+
VALUE rb_query;
|
864
|
+
if (RB_NIL_P(rb_checksum)) {
|
865
|
+
rb_query = rb_str_new_cstr("SET @master_binlog_checksum = "
|
866
|
+
"@@global.binlog_checksum");
|
867
|
+
} else {
|
868
|
+
rb_query = rb_sprintf("SET @master_binlog_checksum = '%"PRIsVALUE"'",
|
869
|
+
rb_checksum);
|
870
|
+
}
|
871
|
+
ID id_query;
|
872
|
+
CONST_ID(id_query, "query");
|
873
|
+
rb_funcall(rb_client, id_query, 1, rb_query);
|
874
|
+
}
|
875
|
+
if (rb_equal(rb_str_new_cstr("NONE"), rb_checksum)) {
|
876
|
+
wrapper->force_disable_use_checksum = true;
|
877
|
+
} else {
|
878
|
+
wrapper->force_disable_use_checksum = false;
|
879
|
+
}
|
880
|
+
|
881
|
+
return RUBY_Qnil;
|
882
|
+
}
|
883
|
+
|
884
|
+
static VALUE
|
885
|
+
rbm2_replication_client_get_file_name(VALUE self)
|
886
|
+
{
|
887
|
+
rbm2_replication_client_wrapper *wrapper =
|
888
|
+
rbm2_replication_client_get_wrapper(self);
|
889
|
+
const char *file_name;
|
890
|
+
size_t file_name_length;
|
891
|
+
int result = mariadb_rpl_get_optionsv(wrapper->rpl,
|
892
|
+
MARIADB_RPL_FILENAME,
|
893
|
+
&file_name,
|
894
|
+
&file_name_length);
|
895
|
+
if (result != 0) {
|
896
|
+
rbm2_replication_client_raise(self);
|
897
|
+
}
|
898
|
+
return rb_str_new(file_name, file_name_length);
|
899
|
+
}
|
900
|
+
|
901
|
+
static VALUE
|
902
|
+
rbm2_replication_client_set_file_name(VALUE self, VALUE file_name)
|
903
|
+
{
|
904
|
+
rbm2_replication_client_wrapper *wrapper =
|
905
|
+
rbm2_replication_client_get_wrapper(self);
|
906
|
+
int result;
|
907
|
+
if (RB_NIL_P(file_name)) {
|
908
|
+
result = mariadb_rpl_optionsv(wrapper->rpl,
|
909
|
+
MARIADB_RPL_FILENAME,
|
910
|
+
NULL,
|
911
|
+
0);
|
912
|
+
} else {
|
913
|
+
result = mariadb_rpl_optionsv(wrapper->rpl,
|
914
|
+
MARIADB_RPL_FILENAME,
|
915
|
+
RSTRING_PTR(file_name),
|
916
|
+
RSTRING_LEN(file_name));
|
917
|
+
}
|
918
|
+
if (result != 0) {
|
919
|
+
rbm2_replication_client_raise(self);
|
920
|
+
}
|
921
|
+
return file_name;
|
922
|
+
}
|
923
|
+
|
924
|
+
static VALUE
|
925
|
+
rbm2_replication_client_get_start_position(VALUE self)
|
926
|
+
{
|
927
|
+
rbm2_replication_client_wrapper *wrapper =
|
928
|
+
rbm2_replication_client_get_wrapper(self);
|
929
|
+
unsigned long start_position;
|
930
|
+
int result = mariadb_rpl_get_optionsv(wrapper->rpl,
|
931
|
+
MARIADB_RPL_START,
|
932
|
+
&start_position);
|
933
|
+
if (result != 0) {
|
934
|
+
rbm2_replication_client_raise(self);
|
935
|
+
}
|
936
|
+
return ULONG2NUM(start_position);
|
937
|
+
}
|
938
|
+
|
939
|
+
static VALUE
|
940
|
+
rbm2_replication_client_set_start_position(VALUE self, VALUE start_position)
|
941
|
+
{
|
942
|
+
rbm2_replication_client_wrapper *wrapper =
|
943
|
+
rbm2_replication_client_get_wrapper(self);
|
944
|
+
int result = mariadb_rpl_optionsv(wrapper->rpl,
|
945
|
+
MARIADB_RPL_START,
|
946
|
+
NUM2ULONG(start_position));
|
947
|
+
if (result != 0) {
|
948
|
+
rbm2_replication_client_raise(self);
|
949
|
+
}
|
950
|
+
return start_position;
|
951
|
+
}
|
952
|
+
|
953
|
+
static VALUE
|
954
|
+
rbm2_replication_client_get_server_id(VALUE self)
|
955
|
+
{
|
956
|
+
rbm2_replication_client_wrapper *wrapper =
|
957
|
+
rbm2_replication_client_get_wrapper(self);
|
958
|
+
unsigned int server_id;
|
959
|
+
int result = mariadb_rpl_get_optionsv(wrapper->rpl,
|
960
|
+
MARIADB_RPL_SERVER_ID,
|
961
|
+
&server_id);
|
962
|
+
if (result != 0) {
|
963
|
+
rbm2_replication_client_raise(self);
|
964
|
+
}
|
965
|
+
return UINT2NUM(server_id);
|
966
|
+
}
|
967
|
+
|
968
|
+
static VALUE
|
969
|
+
rbm2_replication_client_set_server_id(VALUE self, VALUE server_id)
|
970
|
+
{
|
971
|
+
rbm2_replication_client_wrapper *wrapper =
|
972
|
+
rbm2_replication_client_get_wrapper(self);
|
973
|
+
int result = mariadb_rpl_optionsv(wrapper->rpl,
|
974
|
+
MARIADB_RPL_SERVER_ID,
|
975
|
+
NUM2UINT(server_id));
|
976
|
+
if (result != 0) {
|
977
|
+
rbm2_replication_client_raise(self);
|
978
|
+
}
|
979
|
+
return server_id;
|
980
|
+
}
|
981
|
+
|
982
|
+
static VALUE
|
983
|
+
rbm2_replication_client_get_flags(VALUE self)
|
984
|
+
{
|
985
|
+
rbm2_replication_client_wrapper *wrapper =
|
986
|
+
rbm2_replication_client_get_wrapper(self);
|
987
|
+
unsigned int flags;
|
988
|
+
int result = mariadb_rpl_get_optionsv(wrapper->rpl,
|
989
|
+
MARIADB_RPL_FLAGS,
|
990
|
+
&flags);
|
991
|
+
if (result != 0) {
|
992
|
+
rbm2_replication_client_raise(self);
|
993
|
+
}
|
994
|
+
return UINT2NUM(flags);
|
995
|
+
}
|
996
|
+
|
997
|
+
static VALUE
|
998
|
+
rbm2_replication_client_set_flags(VALUE self, VALUE flags)
|
999
|
+
{
|
1000
|
+
rbm2_replication_client_wrapper *wrapper =
|
1001
|
+
rbm2_replication_client_get_wrapper(self);
|
1002
|
+
int result = mariadb_rpl_optionsv(wrapper->rpl,
|
1003
|
+
MARIADB_RPL_FLAGS,
|
1004
|
+
NUM2UINT(flags));
|
1005
|
+
if (result != 0) {
|
1006
|
+
rbm2_replication_client_raise(self);
|
1007
|
+
}
|
1008
|
+
return flags;
|
1009
|
+
}
|
1010
|
+
|
1011
|
+
static void *
|
1012
|
+
rbm2_replication_client_close_without_gvl(void *data)
|
1013
|
+
{
|
1014
|
+
rbm2_replication_client_wrapper *wrapper = data;
|
1015
|
+
if (wrapper->rpl_event) {
|
1016
|
+
mariadb_free_rpl_event(wrapper->rpl_event);
|
1017
|
+
wrapper->rpl_event = NULL;
|
1018
|
+
}
|
1019
|
+
if (wrapper->rpl) {
|
1020
|
+
mariadb_rpl_close(wrapper->rpl);
|
1021
|
+
wrapper->rpl = NULL;
|
1022
|
+
}
|
1023
|
+
return NULL;
|
1024
|
+
}
|
1025
|
+
|
1026
|
+
static VALUE
|
1027
|
+
rbm2_replication_client_close(VALUE self)
|
1028
|
+
{
|
1029
|
+
rbm2_replication_client_wrapper *wrapper =
|
1030
|
+
rbm2_replication_client_get_wrapper(self);
|
1031
|
+
rb_thread_call_without_gvl(rbm2_replication_client_close_without_gvl,
|
1032
|
+
wrapper,
|
1033
|
+
RUBY_UBF_IO,
|
1034
|
+
0);
|
1035
|
+
return Qnil;
|
1036
|
+
}
|
1037
|
+
|
1038
|
+
static void *
|
1039
|
+
rbm2_replication_client_open_without_gvl(void *data)
|
1040
|
+
{
|
1041
|
+
rbm2_replication_client_wrapper *wrapper = data;
|
1042
|
+
int result = mariadb_rpl_open(wrapper->rpl);
|
1043
|
+
return (void *)(intptr_t)result;
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
static VALUE
|
1047
|
+
rbm2_replication_client_open(VALUE self)
|
1048
|
+
{
|
1049
|
+
rbm2_replication_client_wrapper *wrapper =
|
1050
|
+
rbm2_replication_client_get_wrapper(self);
|
1051
|
+
int result =
|
1052
|
+
(intptr_t)rb_thread_call_without_gvl(
|
1053
|
+
rbm2_replication_client_open_without_gvl,
|
1054
|
+
wrapper,
|
1055
|
+
RUBY_UBF_IO,
|
1056
|
+
0);
|
1057
|
+
if (result != 0) {
|
1058
|
+
rbm2_replication_client_raise(self);
|
1059
|
+
}
|
1060
|
+
if (rb_block_given_p()) {
|
1061
|
+
return rb_ensure(rb_yield, self,
|
1062
|
+
rbm2_replication_client_close, self);
|
1063
|
+
} else {
|
1064
|
+
return Qnil;
|
1065
|
+
}
|
1066
|
+
}
|
1067
|
+
|
1068
|
+
static void *
|
1069
|
+
rbm2_replication_client_fetch_without_gvl(void *data)
|
1070
|
+
{
|
1071
|
+
rbm2_replication_client_wrapper *wrapper = data;
|
1072
|
+
wrapper->rpl_event = mariadb_rpl_fetch(wrapper->rpl, wrapper->rpl_event);
|
1073
|
+
return wrapper->rpl_event;
|
1074
|
+
}
|
1075
|
+
|
1076
|
+
static VALUE
|
1077
|
+
rbm2_row_parse(const uint8_t **row_data,
|
1078
|
+
uint32_t n_columns,
|
1079
|
+
const uint8_t *column_bitmap,
|
1080
|
+
VALUE rb_columns)
|
1081
|
+
{
|
1082
|
+
VALUE rb_row = rb_hash_new();
|
1083
|
+
uint32_t i;
|
1084
|
+
const uint8_t *row_null_bitmap = *row_data;
|
1085
|
+
(*row_data) += (n_columns + 7) / 8;
|
1086
|
+
for (i = 0; i < n_columns; i++) {
|
1087
|
+
if (!rbm2_bitmap_is_set(column_bitmap, i)) {
|
1088
|
+
continue;
|
1089
|
+
}
|
1090
|
+
if (rbm2_bitmap_is_set(row_null_bitmap, i)) {
|
1091
|
+
rb_hash_aset(rb_row, UINT2NUM(i), RUBY_Qnil);
|
1092
|
+
} else {
|
1093
|
+
VALUE rb_column = RARRAY_PTR(rb_columns)[i];
|
1094
|
+
VALUE rb_column_value = rbm2_column_parse(rb_column, row_data);
|
1095
|
+
rb_hash_aset(rb_row, UINT2NUM(i), rb_column_value);
|
1096
|
+
}
|
1097
|
+
}
|
1098
|
+
return rb_row;
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
static VALUE
|
1102
|
+
rbm2_replication_event_new(rbm2_replication_client_wrapper *wrapper,
|
1103
|
+
MARIADB_RPL_EVENT *event)
|
1104
|
+
{
|
1105
|
+
VALUE klass;
|
1106
|
+
VALUE rb_event;
|
1107
|
+
switch (event->event_type) {
|
1108
|
+
case ROTATE_EVENT:
|
1109
|
+
klass = rb_cMysql2ReplicationRotateEvent;
|
1110
|
+
rb_event = rb_class_new_instance(0, NULL, klass);
|
1111
|
+
{
|
1112
|
+
struct st_mariadb_rpl_rotate_event *e = &(event->event.rotate);
|
1113
|
+
rb_iv_set(rb_event, "@position", ULL2NUM(e->position));
|
1114
|
+
size_t filename_size;
|
1115
|
+
if (event->timestamp == 0) {
|
1116
|
+
/* 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;
|
1123
|
+
}
|
1124
|
+
rb_iv_set(rb_event,
|
1125
|
+
"@file_name",
|
1126
|
+
rb_str_new(e->filename.str, filename_size));
|
1127
|
+
}
|
1128
|
+
break;
|
1129
|
+
case FORMAT_DESCRIPTION_EVENT:
|
1130
|
+
klass = rb_cMysql2ReplicationFormatDescriptionEvent;
|
1131
|
+
rb_event = rb_class_new_instance(0, NULL, klass);
|
1132
|
+
{
|
1133
|
+
struct st_mariadb_rpl_format_description_event *e =
|
1134
|
+
&(event->event.format_description);
|
1135
|
+
rb_iv_set(rb_event, "@format", USHORT2NUM(e->format));
|
1136
|
+
rb_iv_set(rb_event, "@server_version", rb_str_new_cstr(e->server_version));
|
1137
|
+
rb_iv_set(rb_event, "@timestamp", UINT2NUM(e->timestamp));
|
1138
|
+
rb_iv_set(rb_event, "@header_length", UINT2NUM(e->header_len));
|
1139
|
+
}
|
1140
|
+
if (wrapper->force_disable_use_checksum) {
|
1141
|
+
wrapper->rpl->use_checksum = false;
|
1142
|
+
}
|
1143
|
+
break;
|
1144
|
+
case TABLE_MAP_EVENT:
|
1145
|
+
klass = rb_cMysql2ReplicationTableMapEvent;
|
1146
|
+
rb_event = rb_class_new_instance(0, NULL, klass);
|
1147
|
+
{
|
1148
|
+
struct st_mariadb_rpl_table_map_event *e = &(event->event.table_map);
|
1149
|
+
VALUE rb_table_id = ULONG2NUM(e->table_id);
|
1150
|
+
rb_iv_set(rb_event, "@table_id", rb_table_id);
|
1151
|
+
rb_iv_set(rb_event, "@database", rb_str_new(e->database.str,
|
1152
|
+
e->database.length));
|
1153
|
+
rb_iv_set(rb_event, "@table", rb_str_new(e->table.str,
|
1154
|
+
e->table.length));
|
1155
|
+
{
|
1156
|
+
VALUE rb_columns = rb_ary_new_capa(e->column_count);
|
1157
|
+
const uint8_t *column_types = (const uint8_t *)(e->column_types.str);
|
1158
|
+
const uint8_t *metadata = (const uint8_t *)(e->metadata.str);
|
1159
|
+
uint32_t i;
|
1160
|
+
for (i = 0; i < e->column_count; i++) {
|
1161
|
+
uint8_t column_type = column_types[i];
|
1162
|
+
enum enum_field_types real_column_type = column_type;
|
1163
|
+
VALUE rb_column = rb_hash_new();
|
1164
|
+
rbm2_metadata_parse(&real_column_type,
|
1165
|
+
&metadata,
|
1166
|
+
rb_column);
|
1167
|
+
rb_hash_aset(rb_column,
|
1168
|
+
rb_id2sym(rb_intern("type")),
|
1169
|
+
rbm2_column_type_to_symbol(real_column_type));
|
1170
|
+
rb_hash_aset(rb_column,
|
1171
|
+
rb_id2sym(rb_intern("type_id")),
|
1172
|
+
UINT2NUM(real_column_type));
|
1173
|
+
rb_ary_push(rb_columns, rb_column);
|
1174
|
+
}
|
1175
|
+
rb_iv_set(rb_event, "@columns", rb_columns);
|
1176
|
+
}
|
1177
|
+
rb_hash_aset(wrapper->rb_table_maps, rb_table_id, rb_event);
|
1178
|
+
}
|
1179
|
+
break;
|
1180
|
+
case WRITE_ROWS_EVENT_V1:
|
1181
|
+
case WRITE_ROWS_EVENT:
|
1182
|
+
case UPDATE_ROWS_EVENT_V1:
|
1183
|
+
case UPDATE_ROWS_EVENT:
|
1184
|
+
case DELETE_ROWS_EVENT_V1:
|
1185
|
+
case DELETE_ROWS_EVENT:
|
1186
|
+
switch (event->event_type) {
|
1187
|
+
case WRITE_ROWS_EVENT_V1:
|
1188
|
+
case WRITE_ROWS_EVENT:
|
1189
|
+
klass = rb_cMysql2ReplicationWriteRowsEvent;
|
1190
|
+
break;
|
1191
|
+
case UPDATE_ROWS_EVENT_V1:
|
1192
|
+
case UPDATE_ROWS_EVENT:
|
1193
|
+
klass = rb_cMysql2ReplicationUpdateRowsEvent;
|
1194
|
+
break;
|
1195
|
+
default:
|
1196
|
+
klass = rb_cMysql2ReplicationDeleteRowsEvent;
|
1197
|
+
break;
|
1198
|
+
}
|
1199
|
+
rb_event = rb_class_new_instance(0, NULL, klass);
|
1200
|
+
{
|
1201
|
+
struct st_mariadb_rpl_rows_event *e = &(event->event.rows);
|
1202
|
+
VALUE rb_table_id = ULONG2NUM(e->table_id);
|
1203
|
+
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
|
+
rb_iv_set(rb_event, "@table_id", rb_table_id);
|
1209
|
+
rb_iv_set(rb_event, "@table_map", rb_table_map);
|
1210
|
+
rb_iv_set(rb_event, "@rows_flags", USHORT2NUM(e->flags));
|
1211
|
+
VALUE rb_rows = rb_ary_new();
|
1212
|
+
VALUE rb_updated_rows = RUBY_Qnil;
|
1213
|
+
if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
|
1214
|
+
rb_updated_rows = rb_ary_new();
|
1215
|
+
}
|
1216
|
+
const uint8_t *row_data = e->row_data;
|
1217
|
+
const uint8_t *row_data_end = row_data + e->row_data_size;
|
1218
|
+
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
|
+
}
|
1234
|
+
}
|
1235
|
+
rb_iv_set(rb_event, "@rows", rb_rows);
|
1236
|
+
if (klass == rb_cMysql2ReplicationUpdateRowsEvent) {
|
1237
|
+
rb_iv_set(rb_event, "@updated_rows", rb_updated_rows);
|
1238
|
+
}
|
1239
|
+
if (e->flags & FL_STMT_END) {
|
1240
|
+
rb_hash_clear(wrapper->rb_table_maps);
|
1241
|
+
}
|
1242
|
+
}
|
1243
|
+
break;
|
1244
|
+
default:
|
1245
|
+
klass = rb_cMysql2ReplicationEvent;
|
1246
|
+
rb_event = rb_class_new_instance(0, NULL, klass);
|
1247
|
+
break;
|
1248
|
+
}
|
1249
|
+
rb_iv_set(rb_event, "@type", UINT2NUM(event->event_type));
|
1250
|
+
rb_iv_set(rb_event, "@timestamp", UINT2NUM(event->timestamp));
|
1251
|
+
rb_iv_set(rb_event, "@server_id", UINT2NUM(event->server_id));
|
1252
|
+
rb_iv_set(rb_event, "@length", UINT2NUM(event->event_length));
|
1253
|
+
rb_iv_set(rb_event, "@next_position", UINT2NUM(event->next_event_pos));
|
1254
|
+
rb_iv_set(rb_event, "@flags", USHORT2NUM(event->flags));
|
1255
|
+
return rb_event;
|
1256
|
+
}
|
1257
|
+
|
1258
|
+
static VALUE
|
1259
|
+
rbm2_replication_client_fetch(VALUE self)
|
1260
|
+
{
|
1261
|
+
rbm2_replication_client_wrapper *wrapper =
|
1262
|
+
rbm2_replication_client_get_wrapper(self);
|
1263
|
+
MYSQL *client = rbm2_replication_client_wrapper_get_client(wrapper);
|
1264
|
+
do {
|
1265
|
+
MARIADB_RPL_EVENT *event =
|
1266
|
+
rb_thread_call_without_gvl(rbm2_replication_client_fetch_without_gvl,
|
1267
|
+
wrapper,
|
1268
|
+
RUBY_UBF_IO,
|
1269
|
+
0);
|
1270
|
+
if (mysql_errno(client) != 0) {
|
1271
|
+
rbm2_replication_client_raise(self);
|
1272
|
+
}
|
1273
|
+
if (!event) {
|
1274
|
+
if (wrapper->rpl->buffer_size == 0) {
|
1275
|
+
return RUBY_Qnil;
|
1276
|
+
}
|
1277
|
+
continue;
|
1278
|
+
}
|
1279
|
+
return rbm2_replication_event_new(wrapper, event);
|
1280
|
+
} while (true);
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
static VALUE
|
1284
|
+
rbm2_replication_client_each(VALUE self)
|
1285
|
+
{
|
1286
|
+
rbm2_replication_client_wrapper *wrapper =
|
1287
|
+
rbm2_replication_client_get_wrapper(self);
|
1288
|
+
MYSQL *client = rbm2_replication_client_wrapper_get_client(wrapper);
|
1289
|
+
do {
|
1290
|
+
MARIADB_RPL_EVENT *event =
|
1291
|
+
rb_thread_call_without_gvl(rbm2_replication_client_fetch_without_gvl,
|
1292
|
+
wrapper,
|
1293
|
+
RUBY_UBF_IO,
|
1294
|
+
0);
|
1295
|
+
if (mysql_errno(client) != 0) {
|
1296
|
+
rbm2_replication_client_raise(self);
|
1297
|
+
}
|
1298
|
+
if (!event) {
|
1299
|
+
if (wrapper->rpl->buffer_size == 0) {
|
1300
|
+
return RUBY_Qnil;
|
1301
|
+
}
|
1302
|
+
continue;
|
1303
|
+
}
|
1304
|
+
rb_yield(rbm2_replication_event_new(wrapper, event));
|
1305
|
+
} while (true);
|
1306
|
+
return RUBY_Qnil;
|
1307
|
+
}
|
1308
|
+
|
1309
|
+
void
|
1310
|
+
Init_mysql2_replication(void)
|
1311
|
+
{
|
1312
|
+
rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
|
1313
|
+
|
1314
|
+
VALUE rb_mMysql2 = rb_const_get(rb_cObject, rb_intern("Mysql2"));
|
1315
|
+
rb_cMysql2Error = rb_const_get(rb_mMysql2, rb_intern("Error"));
|
1316
|
+
|
1317
|
+
VALUE rb_mMysql2Replication = rb_define_module("Mysql2Replication");
|
1318
|
+
|
1319
|
+
rb_cMysql2ReplicationEvent =
|
1320
|
+
rb_define_class_under(rb_mMysql2Replication, "Event", rb_cObject);
|
1321
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "type", true, false);
|
1322
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "timestamp", true, false);
|
1323
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "server_id", true, false);
|
1324
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "length", true, false);
|
1325
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "next_position", true, false);
|
1326
|
+
rb_define_attr(rb_cMysql2ReplicationEvent, "flags", true, false);
|
1327
|
+
|
1328
|
+
rb_cMysql2ReplicationRotateEvent =
|
1329
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1330
|
+
"RotateEvent",
|
1331
|
+
rb_cMysql2ReplicationEvent);
|
1332
|
+
rb_define_attr(rb_cMysql2ReplicationRotateEvent, "position", true, false);
|
1333
|
+
rb_define_attr(rb_cMysql2ReplicationRotateEvent, "file_name", true, false);
|
1334
|
+
|
1335
|
+
rb_cMysql2ReplicationFormatDescriptionEvent =
|
1336
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1337
|
+
"FormatDescriptionEvent",
|
1338
|
+
rb_cMysql2ReplicationEvent);
|
1339
|
+
rb_define_attr(rb_cMysql2ReplicationFormatDescriptionEvent,
|
1340
|
+
"format", true, false);
|
1341
|
+
rb_define_attr(rb_cMysql2ReplicationFormatDescriptionEvent,
|
1342
|
+
"server_version", true, false);
|
1343
|
+
rb_define_attr(rb_cMysql2ReplicationFormatDescriptionEvent,
|
1344
|
+
"timestamp", true, false);
|
1345
|
+
rb_define_attr(rb_cMysql2ReplicationFormatDescriptionEvent,
|
1346
|
+
"header_length", true, false);
|
1347
|
+
|
1348
|
+
VALUE rb_cMysql2ReplicationRowsEvent =
|
1349
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1350
|
+
"RowsEvent",
|
1351
|
+
rb_cMysql2ReplicationEvent);
|
1352
|
+
rb_define_attr(rb_cMysql2ReplicationRowsEvent, "table_id", true, false);
|
1353
|
+
rb_define_attr(rb_cMysql2ReplicationRowsEvent, "table_map", true, false);
|
1354
|
+
rb_define_attr(rb_cMysql2ReplicationRowsEvent, "rows_flags", true, false);
|
1355
|
+
rb_define_attr(rb_cMysql2ReplicationRowsEvent, "rows", true, false);
|
1356
|
+
rb_define_method(rb_cMysql2ReplicationRowsEvent,
|
1357
|
+
"statement_end?",
|
1358
|
+
rbm2_replication_rows_event_statement_end_p,
|
1359
|
+
0);
|
1360
|
+
|
1361
|
+
rb_cMysql2ReplicationWriteRowsEvent =
|
1362
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1363
|
+
"WriteRowsEvent",
|
1364
|
+
rb_cMysql2ReplicationRowsEvent);
|
1365
|
+
rb_cMysql2ReplicationUpdateRowsEvent =
|
1366
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1367
|
+
"UpdateRowsEvent",
|
1368
|
+
rb_cMysql2ReplicationRowsEvent);
|
1369
|
+
rb_define_attr(rb_cMysql2ReplicationUpdateRowsEvent,
|
1370
|
+
"updated_rows", true, false);
|
1371
|
+
rb_cMysql2ReplicationDeleteRowsEvent =
|
1372
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1373
|
+
"DeleteRowsEvent",
|
1374
|
+
rb_cMysql2ReplicationRowsEvent);
|
1375
|
+
|
1376
|
+
rb_cMysql2ReplicationTableMapEvent =
|
1377
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1378
|
+
"TableMapEvent",
|
1379
|
+
rb_cMysql2ReplicationEvent);
|
1380
|
+
rb_define_attr(rb_cMysql2ReplicationTableMapEvent, "table_id", true, false);
|
1381
|
+
rb_define_attr(rb_cMysql2ReplicationTableMapEvent, "database", true, false);
|
1382
|
+
rb_define_attr(rb_cMysql2ReplicationTableMapEvent, "table", true, false);
|
1383
|
+
rb_define_attr(rb_cMysql2ReplicationTableMapEvent, "columns", true, false);
|
1384
|
+
|
1385
|
+
VALUE rb_cMysql2ReplicationClient =
|
1386
|
+
rb_define_class_under(rb_mMysql2Replication,
|
1387
|
+
"Client",
|
1388
|
+
rb_cObject);
|
1389
|
+
rb_define_alloc_func(rb_cMysql2ReplicationClient,
|
1390
|
+
rbm2_replication_client_alloc);
|
1391
|
+
rb_include_module(rb_cMysql2ReplicationClient, rb_mEnumerable);
|
1392
|
+
|
1393
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1394
|
+
"initialize", rbm2_replication_client_initialize, -1);
|
1395
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1396
|
+
"file_name", rbm2_replication_client_get_file_name, 0);
|
1397
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1398
|
+
"file_name=", rbm2_replication_client_set_file_name, 1);
|
1399
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1400
|
+
"start_position",
|
1401
|
+
rbm2_replication_client_get_start_position, 0);
|
1402
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1403
|
+
"start_position=",
|
1404
|
+
rbm2_replication_client_set_start_position, 1);
|
1405
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1406
|
+
"server_id", rbm2_replication_client_get_server_id, 0);
|
1407
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1408
|
+
"server_id=", rbm2_replication_client_set_server_id, 1);
|
1409
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1410
|
+
"flags", rbm2_replication_client_get_flags, 0);
|
1411
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1412
|
+
"flags=", rbm2_replication_client_set_flags, 1);
|
1413
|
+
|
1414
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1415
|
+
"open", rbm2_replication_client_open, 0);
|
1416
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1417
|
+
"fetch", rbm2_replication_client_fetch, 0);
|
1418
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1419
|
+
"close", rbm2_replication_client_close, 0);
|
1420
|
+
|
1421
|
+
rb_define_method(rb_cMysql2ReplicationClient,
|
1422
|
+
"each", rbm2_replication_client_each, 0);
|
1423
|
+
|
1424
|
+
VALUE rb_cMysql2ReplicationFlags =
|
1425
|
+
rb_define_module_under(rb_mMysql2Replication, "Flags");
|
1426
|
+
rb_define_const(rb_cMysql2ReplicationFlags,
|
1427
|
+
"BINLOG_DUMP_NON_BLOCK",
|
1428
|
+
UINT2NUM(MARIADB_RPL_BINLOG_DUMP_NON_BLOCK));
|
1429
|
+
rb_define_const(rb_cMysql2ReplicationFlags,
|
1430
|
+
"BINLOG_SEND_ANNOTATE_ROWS",
|
1431
|
+
UINT2NUM(MARIADB_RPL_BINLOG_SEND_ANNOTATE_ROWS));
|
1432
|
+
rb_define_const(rb_cMysql2ReplicationFlags,
|
1433
|
+
"IGNORE_HEARTBEAT",
|
1434
|
+
UINT2NUM(MARIADB_RPL_IGNORE_HEARTBEAT));
|
1435
|
+
}
|