flydata 0.5.12 → 0.5.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|