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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82270f47e1280076e3dc0b40a86cc548e0da6636
4
- data.tar.gz: bed0f9307f53602e2956369b5419e3173410d8bd
3
+ metadata.gz: d4b03db81cb7465b262dce0c4c8e33a14b5e290b
4
+ data.tar.gz: 42c08437e1b5f0d8452f2f2504666d6ce83006a7
5
5
  SHA512:
6
- metadata.gz: e765cd79b44de76a883867a81718e9c7b4ab4834c0ae97d59faa57728bea4e1888bc97d8c993edd6103ea6c5da1786ca33b58f18f532c5eb04c3b6e518f95a2f
7
- data.tar.gz: e62f777a303bae1fee4810bc1a1133ef2ca3d12b212ab4932666605e822d57f3ebcaf0ced16433c1b9894e43a286bd824edf30a210f24ab0a764a706420429d4
6
+ metadata.gz: 6de4243e12d2ec8d0c0c62a68a21fd9f1bef9f5a40caebe494687656ab5714d1d88e56ff7aa091796c52a57321e74e6c287ddab02e3968a0029e0203ff3ea47a
7
+ data.tar.gz: 910e524b426859dae7e5996bf25148aedf2eebea36decbc602965b483d8cf010ff224e998707c6d35bac7f80036ff0f609ef6dfd88410bf562700d967ad30b34
data/Gemfile CHANGED
@@ -29,4 +29,5 @@ group :development do
29
29
  gem 'activerecord', '~> 4.0', '>= 4.0.0'
30
30
  gem 'protected_attributes', '~> 1.0', '>= 1.0.8'
31
31
  gem 'pry'
32
+ gem 'rake-compiler', '~> 0.9', '>= 0.9.5'
32
33
  end
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.12
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,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile "flydata/json/json_ext"
@@ -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,3 @@
1
+ require "mkmf"
2
+
3
+ create_makefile "flydata/parser/mysql/dump_parser_ext"
@@ -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