flydata 0.5.12 → 0.5.13
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/Gemfile +1 -0
- data/Gemfile.lock +3 -0
- data/Rakefile +12 -0
- data/VERSION +1 -1
- data/ext/flydata/flydata.h +13 -0
- data/ext/flydata/json/extconf.rb +3 -0
- data/ext/flydata/json/json_ext.cpp +137 -0
- data/ext/flydata/parser/mysql/.gitignore +1 -0
- data/ext/flydata/parser/mysql/dump_parser_ext.cpp +106 -0
- data/ext/flydata/parser/mysql/extconf.rb +3 -0
- data/ext/flydata/parser/mysql/parser.txt +121 -0
- data/ext/flydata/parser/mysql/sql_parser.cpp +414 -0
- data/ext/flydata/parser/mysql/sql_parser.h +15 -0
- data/flydata-core/lib/flydata-core/mysql/command_generator.rb +20 -9
- data/flydata-core/spec/mysql/command_generator_spec.rb +17 -17
- data/flydata.gemspec +0 -0
- data/lib/flydata/command/sync.rb +78 -90
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +4 -1
- data/lib/flydata/json.rb +1 -0
- data/lib/flydata/json/.gitignore +1 -0
- data/lib/flydata/parser/mysql/.gitignore +1 -0
- data/lib/flydata/parser/mysql/dump_parser.rb +21 -5
- data/spec/flydata/command/sync_spec.rb +20 -13
- data/spec/flydata/parser/mysql/dump_parser_spec.rb +104 -0
- data/spec/flydata/sync_file_manager_spec.rb +3 -3
- data/test-suite.sh +1 -0
- metadata +38 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4b03db81cb7465b262dce0c4c8e33a14b5e290b
|
4
|
+
data.tar.gz: 42c08437e1b5f0d8452f2f2504666d6ce83006a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6de4243e12d2ec8d0c0c62a68a21fd9f1bef9f5a40caebe494687656ab5714d1d88e56ff7aa091796c52a57321e74e6c287ddab02e3968a0029e0203ff3ea47a
|
7
|
+
data.tar.gz: 910e524b426859dae7e5996bf25148aedf2eebea36decbc602965b483d8cf010ff224e998707c6d35bac7f80036ff0f609ef6dfd88410bf562700d967ad30b34
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -88,6 +88,8 @@ GEM
|
|
88
88
|
slop (~> 3.4)
|
89
89
|
rack (1.5.2)
|
90
90
|
rake (10.3.2)
|
91
|
+
rake-compiler (0.9.5)
|
92
|
+
rake
|
91
93
|
rdoc (4.1.1)
|
92
94
|
json (~> 1.4)
|
93
95
|
rest-client (1.7.2)
|
@@ -139,6 +141,7 @@ DEPENDENCIES
|
|
139
141
|
mysql2 (~> 0.3, >= 0.3.17)
|
140
142
|
protected_attributes (~> 1.0, >= 1.0.8)
|
141
143
|
pry
|
144
|
+
rake-compiler (~> 0.9, >= 0.9.5)
|
142
145
|
rest-client (~> 1.6, >= 1.6.7)
|
143
146
|
rspec (~> 3.0)
|
144
147
|
ruby-prof (~> 0.15, >= 0.15.1)
|
data/Rakefile
CHANGED
@@ -32,3 +32,15 @@ RSpec::Core::RakeTask.new(:spec) do |t|
|
|
32
32
|
end
|
33
33
|
|
34
34
|
task :default => :spec
|
35
|
+
|
36
|
+
require 'rake/extensiontask'
|
37
|
+
|
38
|
+
Rake::ExtensionTask.new "dump_parser_ext" do |ext|
|
39
|
+
ext.ext_dir = "ext/flydata/parser/mysql"
|
40
|
+
ext.lib_dir = "lib/flydata/parser/mysql"
|
41
|
+
end
|
42
|
+
|
43
|
+
Rake::ExtensionTask.new "json_ext" do |ext|
|
44
|
+
ext.ext_dir = "ext/flydata/json"
|
45
|
+
ext.lib_dir = "lib/flydata/json"
|
46
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.5.
|
1
|
+
0.5.13
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef __FLYDATA_H
|
2
|
+
#define __FLYDATA_H
|
3
|
+
|
4
|
+
#define __F(f) (reinterpret_cast<VALUE (*)(...)>(f))
|
5
|
+
|
6
|
+
#ifdef DEBUG
|
7
|
+
#define debug_print(fmt, ...) \
|
8
|
+
do { if (DEBUG) fprintf(stderr, fmt, __VA_ARGS__); } while (0)
|
9
|
+
#else
|
10
|
+
#define debug_print
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#endif // __FLYDATA_H
|
@@ -0,0 +1,137 @@
|
|
1
|
+
#include <sstream>
|
2
|
+
#include <ruby.h>
|
3
|
+
#include <ruby/encoding.h>
|
4
|
+
#include "../flydata.h"
|
5
|
+
|
6
|
+
extern "C" {
|
7
|
+
#ifdef _WIN32
|
8
|
+
_declspec(dllexport)
|
9
|
+
#endif
|
10
|
+
void Init_json_ext();
|
11
|
+
}
|
12
|
+
|
13
|
+
inline void add_json_value(const char* buf, long buf_len, bool quote, std::stringstream& ss)
|
14
|
+
{
|
15
|
+
if (quote)
|
16
|
+
{
|
17
|
+
ss.put('\"');
|
18
|
+
}
|
19
|
+
const char* ptr = 0;
|
20
|
+
long len = 0;
|
21
|
+
const char* esc_str = 0;
|
22
|
+
for (long i = 0; i < buf_len; i++) {
|
23
|
+
if (!ptr) { ptr = buf + i; len = 0; }
|
24
|
+
switch (buf[i])
|
25
|
+
{
|
26
|
+
case '\"':
|
27
|
+
esc_str = "\\\"";
|
28
|
+
case '\\':
|
29
|
+
esc_str = "\\\\";
|
30
|
+
case '/':
|
31
|
+
esc_str = "\\/";
|
32
|
+
case '\b':
|
33
|
+
esc_str = "\\b";
|
34
|
+
case '\f':
|
35
|
+
esc_str = "\\f";
|
36
|
+
case '\n':
|
37
|
+
esc_str = "\\n";
|
38
|
+
case '\r':
|
39
|
+
esc_str = "\\r";
|
40
|
+
case '\t':
|
41
|
+
esc_str = "\\t";
|
42
|
+
|
43
|
+
if (len > 0)
|
44
|
+
{
|
45
|
+
ss.write(ptr, len);
|
46
|
+
}
|
47
|
+
ss.write(esc_str, 2);
|
48
|
+
ptr = 0; len = 0;
|
49
|
+
break;
|
50
|
+
default:
|
51
|
+
len++;
|
52
|
+
break;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
if (len > 0) {
|
56
|
+
ss.write(ptr, len);
|
57
|
+
}
|
58
|
+
|
59
|
+
if (quote)
|
60
|
+
{
|
61
|
+
ss.put('\"');
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
inline void add_json_value(VALUE value, std::stringstream& ss)
|
66
|
+
{
|
67
|
+
switch(TYPE(value))
|
68
|
+
{
|
69
|
+
case T_STRING:
|
70
|
+
add_json_value(RSTRING_PTR(value), RSTRING_LEN(value), true, ss);
|
71
|
+
break;
|
72
|
+
case T_NIL:
|
73
|
+
add_json_value("null", 4, false, ss);
|
74
|
+
break;
|
75
|
+
case T_TRUE:
|
76
|
+
add_json_value("true", 4, false, ss);
|
77
|
+
break;
|
78
|
+
case T_FALSE:
|
79
|
+
add_json_value("false", 5, false, ss);
|
80
|
+
break;
|
81
|
+
default:
|
82
|
+
VALUE v = rb_funcall(value, rb_intern("to_s"), 0);
|
83
|
+
add_json_value(RSTRING_PTR(v), RSTRING_LEN(v), true, ss);
|
84
|
+
break;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
inline void add_kv_pair(VALUE key, VALUE value, std::stringstream& ss)
|
89
|
+
{
|
90
|
+
if (TYPE(key) != T_STRING)
|
91
|
+
{
|
92
|
+
key = rb_funcall(key, rb_intern("to_s"), 0);
|
93
|
+
}
|
94
|
+
add_json_value(key, ss);
|
95
|
+
ss.put(':');
|
96
|
+
add_json_value(value, ss);
|
97
|
+
}
|
98
|
+
|
99
|
+
static VALUE rb_json_generate_kv_pairs(VALUE self, VALUE key_ary, VALUE value_ary)
|
100
|
+
{
|
101
|
+
long key_len = RARRAY_LEN(key_ary);
|
102
|
+
long value_len = RARRAY_LEN(value_ary);
|
103
|
+
|
104
|
+
if (key_len != value_len)
|
105
|
+
{
|
106
|
+
rb_raise(rb_eArgError, "length of arrays must match");
|
107
|
+
}
|
108
|
+
|
109
|
+
std::stringstream ss;
|
110
|
+
|
111
|
+
ss << "{";
|
112
|
+
|
113
|
+
for (long i = 0; i < key_len; i++)
|
114
|
+
{
|
115
|
+
if (i > 0) { ss << ","; }
|
116
|
+
|
117
|
+
VALUE key = rb_ary_entry(key_ary, i);
|
118
|
+
VALUE value = rb_ary_entry(value_ary, i);
|
119
|
+
|
120
|
+
add_kv_pair(key, value, ss);
|
121
|
+
}
|
122
|
+
ss << "}";
|
123
|
+
|
124
|
+
std::string str = ss.str();
|
125
|
+
VALUE json = rb_str_new(str.data(), str.size());
|
126
|
+
int enc = rb_enc_find_index("UTF-8");
|
127
|
+
rb_enc_associate_index(json, enc);
|
128
|
+
|
129
|
+
return json;
|
130
|
+
}
|
131
|
+
|
132
|
+
void Init_json_ext()
|
133
|
+
{
|
134
|
+
VALUE mJSON = rb_define_module("JSON");
|
135
|
+
|
136
|
+
rb_define_singleton_method(mJSON, "generate_kv_pairs", __F(&rb_json_generate_kv_pairs), 2);
|
137
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
Makefile
|
@@ -0,0 +1,106 @@
|
|
1
|
+
//#define DEBUG 1
|
2
|
+
|
3
|
+
#include <iostream>
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <ruby/encoding.h>
|
6
|
+
#include "sql_parser.h"
|
7
|
+
#include "../../flydata.h"
|
8
|
+
|
9
|
+
extern "C" {
|
10
|
+
#ifdef _WIN32
|
11
|
+
_declspec(dllexport)
|
12
|
+
#endif
|
13
|
+
void Init_dump_parser_ext();
|
14
|
+
}
|
15
|
+
|
16
|
+
class InsertParserCallbackHandler : public ParserCallbackHandler
|
17
|
+
{
|
18
|
+
VALUE m_rows;
|
19
|
+
VALUE m_row;
|
20
|
+
VALUE m_value;
|
21
|
+
|
22
|
+
public:
|
23
|
+
|
24
|
+
InsertParserCallbackHandler() : ParserCallbackHandler(), m_rows(rb_ary_new()), m_row(rb_ary_new()), m_value(Qnil)
|
25
|
+
{
|
26
|
+
}
|
27
|
+
|
28
|
+
void value_callback(const char* str, long len, bool end_value)
|
29
|
+
{
|
30
|
+
if (m_value == Qnil)
|
31
|
+
{
|
32
|
+
if (str || len > 0)
|
33
|
+
{
|
34
|
+
m_value = rb_str_new(str, len);
|
35
|
+
int enc = rb_enc_find_index("UTF-8");
|
36
|
+
rb_enc_associate_index(m_value, enc);
|
37
|
+
debug_print("new value:%s\n", StringValueCStr(m_value));
|
38
|
+
}
|
39
|
+
else
|
40
|
+
{
|
41
|
+
m_value = Qnil;
|
42
|
+
debug_print("new value:%s\n", "nil");
|
43
|
+
}
|
44
|
+
}
|
45
|
+
else
|
46
|
+
{
|
47
|
+
rb_str_cat(m_value, str, len);
|
48
|
+
debug_print("value appended:%s\n", StringValueCStr(m_value));
|
49
|
+
}
|
50
|
+
|
51
|
+
if (end_value)
|
52
|
+
{
|
53
|
+
rb_ary_push(m_row, m_value);
|
54
|
+
debug_print("value committed:%s\n",
|
55
|
+
m_value == Qnil ? "nil" : StringValueCStr(m_value));
|
56
|
+
m_value = Qnil;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
void row_end_callback()
|
61
|
+
{
|
62
|
+
if (m_row)
|
63
|
+
{
|
64
|
+
rb_ary_push(m_rows, m_row);
|
65
|
+
debug_print("row pushed\n", 0);
|
66
|
+
m_row = rb_ary_new();
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE rows()
|
71
|
+
{
|
72
|
+
return m_rows;
|
73
|
+
}
|
74
|
+
};
|
75
|
+
|
76
|
+
static VALUE rb_insert_parser_parse2(VALUE self, VALUE sql)
|
77
|
+
{
|
78
|
+
InsertParserCallbackHandler ch;
|
79
|
+
|
80
|
+
long error_at = -1;
|
81
|
+
if (sql != Qnil)
|
82
|
+
{
|
83
|
+
StringValue(sql);
|
84
|
+
error_at = parse_insert_query(RSTRING_PTR(sql), RSTRING_LEN(sql), ch);
|
85
|
+
}
|
86
|
+
|
87
|
+
if (error_at > -1) {
|
88
|
+
VALUE mFlydata = rb_define_module("Flydata");
|
89
|
+
VALUE eAgentError = rb_define_class_under(mFlydata, "AgentError", rb_eStandardError);
|
90
|
+
VALUE eDumpParseError = rb_define_class_under(mFlydata, "DumpParseError", eAgentError);
|
91
|
+
rb_raise(eDumpParseError, "Parse error at %ld", error_at);
|
92
|
+
}
|
93
|
+
|
94
|
+
return ch.rows();
|
95
|
+
}
|
96
|
+
|
97
|
+
void Init_dump_parser_ext()
|
98
|
+
{
|
99
|
+
VALUE mFlydata = rb_define_module("Flydata");
|
100
|
+
VALUE mParser = rb_define_module_under(mFlydata, "Parser");
|
101
|
+
VALUE mMysql = rb_define_module_under(mParser, "Mysql");
|
102
|
+
VALUE cMysqlDumpParser = rb_define_class_under(mMysql, "MysqlDumpParser", rb_cObject);
|
103
|
+
VALUE cInsertParser = rb_define_class_under(cMysqlDumpParser, "InsertParser", rb_cObject);
|
104
|
+
|
105
|
+
rb_define_private_method(cInsertParser, "_parse2", __F(&rb_insert_parser_parse2), 1);
|
106
|
+
}
|
@@ -0,0 +1,121 @@
|
|
1
|
+
start:
|
2
|
+
"(" => :value
|
3
|
+
else => :start
|
4
|
+
|
5
|
+
value:
|
6
|
+
" ", "\t", "\n", "," => :value
|
7
|
+
"'" => :first_char
|
8
|
+
"0" => (mark), :first_zero
|
9
|
+
[1-9-] => (mark), :number
|
10
|
+
"N" => :null_n
|
11
|
+
")" => (row_end_callback), :start
|
12
|
+
else => :error
|
13
|
+
|
14
|
+
first_zero:
|
15
|
+
"0" => (mark), :leading_zero
|
16
|
+
[1-9] => (mark), :number
|
17
|
+
"." => :number
|
18
|
+
[xX] => :hex_blob
|
19
|
+
"," => (value_callback, :end_value)(mark reset), :value
|
20
|
+
")" => (value_callback, :end_value)(mark reset)(row_end_callback), :start
|
21
|
+
else => :error
|
22
|
+
|
23
|
+
leading_zero:
|
24
|
+
"0" => (mark), :leading_zero
|
25
|
+
[1-9] => (mark), :number
|
26
|
+
"." => :number
|
27
|
+
"," => (value_callback, :end_value)(mark reset), :value
|
28
|
+
")" => (value_callback, :end_value)(mark reset)(row_end_callback), :start
|
29
|
+
else => :error
|
30
|
+
|
31
|
+
number:
|
32
|
+
[0-9.] => :number
|
33
|
+
"," => (value_callback, :end_value)(mark reset), :value
|
34
|
+
")" => (value_callback, :end_value)(mark reset)(row_end_callback), :start
|
35
|
+
else => :error
|
36
|
+
|
37
|
+
null_n:
|
38
|
+
"U" => :null_u
|
39
|
+
else => :error
|
40
|
+
|
41
|
+
null_u:
|
42
|
+
"L" => :null_l1
|
43
|
+
else => :error
|
44
|
+
|
45
|
+
null_l1:
|
46
|
+
"L" => :null_l2
|
47
|
+
else => :error
|
48
|
+
|
49
|
+
null_l2:
|
50
|
+
"," => (value_callback 0, :end_value)(mark_reset), :value # 0 is NULL pointer
|
51
|
+
")" => (value_callback 0, :end_value)(mark_reset)(row_end_callback), :start # 0 is NULL pointer
|
52
|
+
else => :error
|
53
|
+
|
54
|
+
hex_blob:
|
55
|
+
[0-9a-fA-F] => :hex_blob_number
|
56
|
+
else => :error
|
57
|
+
|
58
|
+
hex_blob_number:
|
59
|
+
[0-9a-fA-F] => :hex_blob_number
|
60
|
+
"," => (value_callback, :end_value)(mark_reset), :value
|
61
|
+
")" => (value_callback, :end_value)(mark_reset)(row_end_callback), :start
|
62
|
+
else => :error
|
63
|
+
|
64
|
+
first_char:
|
65
|
+
"\\" => (mark), :escape
|
66
|
+
"'" => (mark)(value_callback, :end_value)(mark_reset), :value
|
67
|
+
mask 110xxxxx => (mark)(temp_mark), :utf8_2_firstbyte
|
68
|
+
mask 1110xxxx => (mark)(temp_mark), :utf8_3_firstbyte
|
69
|
+
mask 11110xxx => (mark)(temp_mark), :utf8_4_firstbyte
|
70
|
+
else => (mark), :following_char
|
71
|
+
|
72
|
+
utf8_2_firstbyte:
|
73
|
+
mask 10xxxxxx => (temp_mark reset), :following_char
|
74
|
+
else (value_callback mark...temp_mark)(mark reset)(value_callback "\xc2\xbf\xc2\xbf")(temp_mark reset), :first_char
|
75
|
+
|
76
|
+
utf8_3_firstbyte:
|
77
|
+
mask 10xxxxxx => :utf8_3_secondbyte
|
78
|
+
else => :utf8_3_error_secondbyte
|
79
|
+
|
80
|
+
utf8_3_secondbyte:
|
81
|
+
mask 10xxxxxx => (temp_mark reset), :following_char
|
82
|
+
else (value_callback mark...temp_mark)(mark reset)(value_callback "\xc2\xbf\xc2\xbf\xc2\xbf")(temp_mark reset), :first_char
|
83
|
+
|
84
|
+
utf8_3_error_secondbyte:
|
85
|
+
any char => (value_callback mark...temp_mark)(mark reset)(value_callback "\xc2\xbf\xc2\xbf\xc2\xbf")(temp_mark reset), :first_char
|
86
|
+
|
87
|
+
utf8_4_firstbyte:
|
88
|
+
mask 10xxxxxx => :utf8_4_secondbyte
|
89
|
+
else => :utf8_4_error_secondbyte
|
90
|
+
|
91
|
+
utf8_4_secondbyte:
|
92
|
+
mask 10xxxxxx => :utf_4_thirdbyte
|
93
|
+
else => :utf8_4_error_thirdbyte
|
94
|
+
|
95
|
+
utf8_4_error_secondbyte:
|
96
|
+
any_char => :utf8_4_error_thirdbyte
|
97
|
+
|
98
|
+
utf8_4_thirdbyte:
|
99
|
+
mask 10xxxxxx => (temp_mark reset), :following_char
|
100
|
+
else (value_callback mark...temp_mark)(mark reset)(value_callback "\xc2\xbf\xc2\xbf\xc2\xbf\xc2\xbf")(temp_mark reset), :first_char
|
101
|
+
|
102
|
+
utf8_4_error_thirdbyte:
|
103
|
+
any char => (value_callback mark...temp_mark)(mark reset)(value_callback "\xc2\xbf\xc2\xbf\xc2\xbf\xc2\xbf")(temp_mark reset), :first_char
|
104
|
+
|
105
|
+
following_char:
|
106
|
+
"\\" => (value_callback)(mark), :escape
|
107
|
+
"'" => (value_callback, :end_value)(mark_reset), :value
|
108
|
+
mask 110xxxxx => (temp_mark), :utf8_2_firstbyte
|
109
|
+
mask 1110xxxx => (temp_mark), :utf8_3_firstbyte
|
110
|
+
mask 11110xxx => (temp_mark), :utf8_4_firstbyte
|
111
|
+
else => :following_char
|
112
|
+
|
113
|
+
escape:
|
114
|
+
"\\" => (value_callback "\\")(mark_reset), :first_char
|
115
|
+
"'" => (value_callback "'")(mark_reset), :first_char
|
116
|
+
'"' => (value_callback '"')(mark_reset), :first_char
|
117
|
+
"n" => (value_callback "\n")(mark_reset), :first_char
|
118
|
+
"r" => (value_callback "\r")(mark_reset), :first_char
|
119
|
+
"0" => (value_callback "\0")(mark_reset), :first_char
|
120
|
+
"Z" => (value_callback "\Z")(mark_reset), :first_char
|
121
|
+
else => :following_char
|