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.
@@ -0,0 +1,414 @@
1
+ #include <iostream>
2
+ #include "sql_parser.h"
3
+
4
+ static int $DEBUG = 0;
5
+
6
+ enum status_t {
7
+ start,
8
+ value,
9
+ first_zero,
10
+ leading_zero,
11
+ number,
12
+ null_n,
13
+ null_u,
14
+ null_l1,
15
+ null_l2,
16
+ hex_blob,
17
+ hex_blob_number,
18
+ first_char,
19
+ following_char,
20
+ utf8_2_firstbyte,
21
+ utf8_3_firstbyte,
22
+ utf8_3_secondbyte,
23
+ utf8_3_err_secondbyte,
24
+ utf8_4_firstbyte,
25
+ utf8_4_secondbyte,
26
+ utf8_4_err_secondbyte,
27
+ utf8_4_thirdbyte,
28
+ utf8_4_err_thirdbyte,
29
+ escape,
30
+ error
31
+ };
32
+
33
+ long parse_insert_query(const char* sql, long len, ParserCallbackHandler& ch)
34
+ {
35
+ const char* current = sql;
36
+ long pos = 0;
37
+ status_t status = start;
38
+ const char* mark = 0;
39
+ const char* temp_mark = 0;
40
+ int value_len = 0;
41
+ long ret = -1; // success
42
+
43
+ for (int itor = 0; itor <= len; itor++) {
44
+ // the loop iterates through the terminate character
45
+ current = itor < len ? sql + itor : "\0";
46
+ pos++; value_len++;
47
+ switch (status) {
48
+ case start:
49
+ if (*current == '(') {
50
+ status = value;
51
+ } else {
52
+ status = start;
53
+ }
54
+ break;
55
+
56
+ case value:
57
+ if ($DEBUG) std::cout << "value[" << *current << "]: " << std::endl << std::flush;
58
+ if (*current == '\'') {
59
+ status = first_char;
60
+ } else if (*current == 'N') {
61
+ status = null_n;
62
+ } else if (*current == '0') {
63
+ mark = current; value_len = 1;//mark
64
+ status = first_zero;
65
+ } else if ( (*current >= '1' && *current <= '9') || *current == '-' ) {
66
+ mark = current; value_len = 1;//mark
67
+ status = number;
68
+ } else if (*current == ',') {
69
+ status = value;
70
+ } else if (*current == ')') {
71
+ ch.row_end_callback();//row end callback
72
+ status = start;
73
+ } else {
74
+ status = error;
75
+ }
76
+ break;
77
+
78
+ case first_zero:
79
+ if ($DEBUG) std::cout << "first_zero[" << *current << "]: " << std::endl << std::flush;
80
+ if (*current == ',') {
81
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
82
+ mark = 0; value_len = 0; //mark_reset
83
+ status = value;
84
+ } else if (*current == ')') {
85
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
86
+ mark = 0; value_len = 0; //mark_reset
87
+ ch.row_end_callback();//row end callback
88
+ status = start;
89
+ } else if (*current == '.') {
90
+ status = number;
91
+ } else if (*current == 'x' || *current == 'X') {
92
+ status = hex_blob;
93
+ } else if (*current == '0') {
94
+ mark = current; value_len = 1; //mark
95
+ status = leading_zero;
96
+ } else if (*current >= '1' && *current <= '9') {
97
+ mark = current; value_len = 1; //mark
98
+ status = number;
99
+ } else {
100
+ status = error;
101
+ }
102
+ break;
103
+
104
+ case leading_zero:
105
+ if ($DEBUG) std::cout << "leading_zero[" << *current << "]: " << std::endl << std::flush;
106
+ if (*current == ',') {
107
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
108
+ mark = 0; value_len = 0; //mark_reset
109
+ status = value;
110
+ } else if (*current == ')') {
111
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
112
+ mark = 0; value_len = 0; //mark_reset
113
+ ch.row_end_callback();//row end callback
114
+ status = start;
115
+ } else if (*current == '.') {
116
+ status = number;
117
+ } else if (*current == '0') {
118
+ mark = current; value_len = 1; //mark
119
+ status = leading_zero;
120
+ } else if (*current >= '1' && *current <= '9') {
121
+ mark = current; value_len = 1; //mark
122
+ status = number;
123
+ } else {
124
+ status = error;
125
+ }
126
+ break;
127
+
128
+ case number:
129
+ if ($DEBUG) std::cout << "number[" << *current << "]: " << std::endl << std::flush;
130
+ if ((*current >= '0' && *current <= '9') || *current == '.') {
131
+ status = number;
132
+ } else if (*current == ',') {
133
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
134
+ mark = 0; value_len = 0; //mark_reset
135
+ status = value;
136
+ } else if (*current == ')') {
137
+ ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
138
+ mark = 0; value_len = 0; //mark_reset
139
+ ch.row_end_callback();//row end callback
140
+ status = start;
141
+ } else {
142
+ status = error;
143
+ }
144
+ break;
145
+
146
+ case null_n:
147
+ if ($DEBUG) std::cout << "null_n[" << *current << "]: " << std::endl << std::flush;
148
+ if (*current == 'U') {
149
+ status = null_u;
150
+ } else {
151
+ status = error;
152
+ }
153
+ break;
154
+
155
+ case null_u:
156
+ if ($DEBUG) std::cout << "null_u[" << *current << "]: " << std::endl << std::flush;
157
+ if (*current == 'L') {
158
+ status = null_l1;
159
+ } else {
160
+ status = error;
161
+ }
162
+ break;
163
+
164
+ case null_l1:
165
+ if ($DEBUG) std::cout << "null_l1[" << *current << "]: " << std::endl << std::flush;
166
+ if (*current == 'L') {
167
+ status = null_l2;
168
+ } else {
169
+ status = error;
170
+ }
171
+ break;
172
+
173
+ case null_l2:
174
+ if ($DEBUG) std::cout << "null_l2[" << *current << "]: " << std::endl << std::flush;
175
+ if (*current == ',') {
176
+ //# 0 is NULL pointer
177
+ ch.value_callback(0, 0, true);//value_callback 0 :end_value
178
+ mark = 0; value_len = 0;
179
+ status = value;
180
+ } else if (*current == ')') {
181
+ //# 0 is NULL pointer
182
+ ch.value_callback(0, 0, true);//value_callback 0, :end_value
183
+ mark = 0; value_len = 0;
184
+ ch.row_end_callback();//row end callback
185
+ status = start;
186
+ } else {
187
+ status = error;
188
+ }
189
+ break;
190
+
191
+ case hex_blob:
192
+ if ($DEBUG) std::cout << "hex_blob[" << *current << "]: " << std::endl << std::flush;
193
+ if ((*current >= '0' && *current <= '9') ||
194
+ (*current >= 'A' && *current <= 'F') ||
195
+ (*current >= 'a' && *current <= 'f')) {
196
+ status = hex_blob_number;
197
+ } else {
198
+ status = error;
199
+ }
200
+ break;
201
+
202
+ case hex_blob_number:
203
+ if ($DEBUG) std::cout << "hex_blob_number[" << *current << "]: " << std::endl << std::flush;
204
+ if ((*current >= '0' && *current <= '9') ||
205
+ (*current >= 'A' && *current <= 'F') ||
206
+ (*current >= 'a' && *current <= 'f')) {
207
+ status = hex_blob_number;
208
+ } else if (*current == ',') {
209
+ ch.value_callback(mark, value_len - 1, true);//value_callback, :end_value
210
+ mark = 0; value_len = 0; //mark_reset
211
+ status = value;
212
+ } else if (*current == ')') {
213
+ ch.value_callback(mark, value_len - 1, true);//value_callback, :end_value
214
+ mark = 0; value_len = 0; //mark_reset
215
+ ch.row_end_callback();//row_end_callback
216
+ status = start;
217
+ } else {
218
+ status = error;
219
+ }
220
+ break;
221
+
222
+ case first_char:
223
+ if ($DEBUG) std::cout << "first_char[" << *current << "]: " << std::endl << std::flush;
224
+ if (*current == '\'') {
225
+ mark = current; value_len = 1; //mark
226
+ ch.value_callback(mark, value_len - 1, true);//value_callback, :end_value
227
+ mark = 0; value_len = 0; //mark_reset
228
+ status = value;
229
+ } else if (*current == '\\') {
230
+ mark = current; value_len = 1; //mark
231
+ status = escape;
232
+ } else if ((*current & 0xe0) == 0xc0) {
233
+ mark = current; value_len = 1; //mark
234
+ temp_mark = current; //temp_mark
235
+ status = utf8_2_firstbyte;
236
+ } else if ((*current & 0xf0) == 0xe0) {
237
+ mark = current; value_len = 1; //mark
238
+ temp_mark = current; //temp_mark
239
+ status = utf8_3_firstbyte;
240
+ } else if ((*current & 0xf8) == 0xf0) {
241
+ mark = current; value_len = 1; //mark
242
+ temp_mark = current; //temp_mark
243
+ status = utf8_4_firstbyte;
244
+ } else {
245
+ mark = current; value_len = 1; //mark
246
+ status = following_char;
247
+ }
248
+ break;
249
+
250
+ case utf8_2_firstbyte:
251
+ if ($DEBUG) std::cout << "utf8_2_firstbyte[" << *current << "]: " << std::endl << std::flush;
252
+ if ((*current & 0xe0) == 0x80) {
253
+ temp_mark = 0; //temp_mark reset)
254
+ status = following_char;
255
+ } else {
256
+ ch.value_callback(mark, temp_mark - mark, false);//value_callback mark...temp_mark
257
+ mark = 0; value_len = 0; //mark_reset
258
+ ch.value_callback("\xef\xbf\xbd\xef\xbf\xbd", 6, false); //value_callback "\xef\xbf\xbd\xef\xbf\xbd"
259
+ temp_mark = 0; //temp_mark reset
260
+ status = first_char;
261
+ }
262
+ break;
263
+
264
+ case utf8_3_firstbyte:
265
+ if ($DEBUG) std::cout << "utf8_3_firstbyte[" << *current << "]: " << std::endl << std::flush;
266
+ if ((*current & 0xe0) == 0x80) {
267
+ status = utf8_3_secondbyte;
268
+ } else {
269
+ status = utf8_3_err_secondbyte;
270
+ }
271
+ break;
272
+
273
+ case utf8_3_secondbyte:
274
+ if ($DEBUG) std::cout << "utf8_3_secondbyte[" << *current << "]: " << std::endl << std::flush;
275
+ if ((*current & 0xe0) == 0x80) {
276
+ temp_mark = 0; //temp_mark reset)
277
+ status = following_char;
278
+ } else {
279
+ ch.value_callback(mark, temp_mark - mark, false);//value_callback mark...temp_mark
280
+ mark = 0; value_len = 0; //mark_reset
281
+ ch.value_callback("\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd", 9, false); //value_callback "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"
282
+ temp_mark = 0; //temp_mark reset
283
+ status = first_char;
284
+ }
285
+ break;
286
+
287
+ case utf8_3_err_secondbyte:
288
+ if ($DEBUG) std::cout << "utf8_3_err_secondbyte[" << *current << "]: " << std::endl << std::flush;
289
+ ch.value_callback(mark, temp_mark - mark, false);//value_callback mark...temp_mark
290
+ mark = 0; value_len = 0; //mark_reset
291
+ ch.value_callback("\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd", 9, false); //value_callback "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"
292
+ temp_mark = 0; //temp_mark reset
293
+ status = first_char;
294
+ break;
295
+
296
+ case utf8_4_firstbyte:
297
+ if ($DEBUG) std::cout << "utf8_4_firstbyte[" << *current << "]: " << std::endl << std::flush;
298
+ if ((*current & 0xe0) == 0x80) {
299
+ status = utf8_4_secondbyte;
300
+ } else {
301
+ status = utf8_4_err_secondbyte;
302
+ }
303
+ break;
304
+
305
+ case utf8_4_secondbyte:
306
+ if ($DEBUG) std::cout << "utf8_4_secondbyte[" << *current << "]: " << std::endl << std::flush;
307
+ if ((*current & 0xe0) == 0x80) {
308
+ status = utf8_4_thirdbyte;
309
+ } else {
310
+ status = utf8_4_err_thirdbyte;
311
+ }
312
+ break;
313
+
314
+ case utf8_4_err_secondbyte:
315
+ if ($DEBUG) std::cout << "utf8_4_err_secondbyte[" << *current << "]: " << std::endl << std::flush;
316
+ status = utf8_4_err_thirdbyte;
317
+ break;
318
+
319
+ case utf8_4_thirdbyte:
320
+ if ($DEBUG) std::cout << "utf8_4_thirdbyte[" << *current << "]: " << std::endl << std::flush;
321
+ if ((*current & 0xe0) == 0x80) {
322
+ temp_mark = 0; //temp_mark reset)
323
+ status = following_char;
324
+ } else {
325
+ ch.value_callback(mark, temp_mark - mark, false);//value_callback mark...temp_mark
326
+ mark = 0; value_len = 0; //mark_reset
327
+ ch.value_callback("\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd", 12, false); //value_callback "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"
328
+ temp_mark = 0; //temp_mark reset
329
+ status = first_char;
330
+ }
331
+ break;
332
+
333
+ case utf8_4_err_thirdbyte:
334
+ if ($DEBUG) std::cout << "utf8_4_err_thirdbyte[" << *current << "]: " << std::endl << std::flush;
335
+ ch.value_callback(mark, temp_mark - mark, false);//value_callback mark...temp_mark
336
+ mark = 0; value_len = 0; //mark_reset
337
+ ch.value_callback("\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd", 12, false); //value_callback "\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd"
338
+ temp_mark = 0; //temp_mark reset
339
+ status = first_char;
340
+ break;
341
+
342
+ case following_char:
343
+ if ($DEBUG) std::cout << "following_char[" << *current << "]: " << std::endl << std::flush;
344
+ if (*current == '\'') {
345
+ ch.value_callback(mark, value_len - 1, true);//value_callback, :end_value
346
+ mark = 0; value_len = 0; //mark_reset
347
+ status = value;
348
+ } else if (*current == '\\') {
349
+ ch.value_callback(mark, value_len - 1, false);//value_callback
350
+ mark = current; value_len = 1;
351
+ status = escape;
352
+ } else if ((*current & 0xe0) == 0xc0) {
353
+ temp_mark = current; //temp_mark
354
+ status = utf8_2_firstbyte;
355
+ } else if ((*current & 0xf0) == 0xe0) {
356
+ temp_mark = current; //temp_mark
357
+ status = utf8_3_firstbyte;
358
+ } else if ((*current & 0xf8) == 0xf0) {
359
+ temp_mark = current; //temp_mark
360
+ status = utf8_4_firstbyte;
361
+ } else {
362
+ status = following_char;
363
+ }
364
+ break;
365
+
366
+ case escape:
367
+ if ($DEBUG) std::cout << "escape[" << *current << "]: " << std::endl << std::flush;
368
+ if (*current == '\"') {
369
+ ch.value_callback("\"", 1, false);//value_callback '\"'
370
+ mark = 0; value_len = 0;
371
+ status = first_char;
372
+ } else if (*current == '\'') {
373
+ ch.value_callback("\'", 1, false);//value_callback '\''
374
+ mark = 0; value_len = 0;
375
+ status = first_char;
376
+ } else if (*current == 'n') {
377
+ ch.value_callback("\n", 1, false);//value_callback '\n'
378
+ mark = 0; value_len = 0;
379
+ status = first_char;
380
+ } else if (*current == '\\') {
381
+ ch.value_callback("\\", 1, false);//value_callback '\\'
382
+ mark = 0; value_len = 0;
383
+ status = first_char;
384
+ } else if (*current == 'r') {
385
+ ch.value_callback("\r", 1, false);//value_callback '\r'
386
+ mark = 0; value_len = 0;
387
+ status = first_char;
388
+ } else if (*current == 'Z') {
389
+ ch.value_callback("\x1a", 1, false);//value_callback '\Z'
390
+ mark = 0; value_len = 0;
391
+ status = first_char;
392
+ } else if (*current == '0') {
393
+ ch.value_callback("\0", 1, false);//value_callback '\0'
394
+ mark = 0; value_len = 0;
395
+ status = first_char;
396
+ } else {
397
+ status = following_char;
398
+ }
399
+ break;
400
+
401
+ case error:
402
+ if ($DEBUG) std::cout << "error[" << *current << "]: " << std::endl << std::flush;
403
+ ret = pos - 1;
404
+ break;
405
+
406
+ default:
407
+ if ($DEBUG) std::cout << "default[" << *current << "]: " << std::endl << std::flush;
408
+ break;
409
+ }//switch
410
+ if (ret != -1)
411
+ break;
412
+ }//for
413
+ return ret;
414
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef __SQL_PARSER_H
2
+ #define __SQL_PARSER_H
3
+
4
+ class ParserCallbackHandler
5
+ {
6
+ public:
7
+ virtual void value_callback(const char* str, long len, bool end_value)=0;
8
+ virtual void row_end_callback()=0;
9
+ };
10
+
11
+ // Return: -1 if no error. Otherwise, the byte position in the string where
12
+ // a parse error occurred.
13
+ extern long parse_insert_query(const char* sql, long len, ParserCallbackHandler& ch);
14
+
15
+ #endif // __SQL_PARSER_H
@@ -1,10 +1,21 @@
1
1
  require 'open3'
2
+ require 'shellwords'
2
3
  require 'flydata-core/table_def/mysql_table_def'
3
4
 
4
5
  module FlydataCore
5
6
  module Mysql
6
7
  class CommandGenerator
7
- DEFAULT_MYSQL_CMD_OPTION = "--default-character-set=utf8 --protocol=tcp"
8
+ DEFAULT_OPTION = "--default-character-set=utf8 --protocol=tcp"
9
+ DEFAULT_MYSQL_OPTION = "#{DEFAULT_OPTION} --skip-auto-rehash"
10
+
11
+ def self.default_cmd_option(command)
12
+ case command
13
+ when 'mysql'
14
+ DEFAULT_MYSQL_OPTION
15
+ else #mysqldump
16
+ DEFAULT_OPTION
17
+ end
18
+ end
8
19
 
9
20
  # Generate mysql/mysqldump command with options
10
21
  # options must be hash
@@ -21,21 +32,21 @@ module FlydataCore
21
32
  raise ArgumentError.new("option must be hash.") unless option.kind_of?(Hash)
22
33
  option = convert_keys_to_sym(option)
23
34
  command = option[:command] ? option[:command] : 'mysql'
24
- host = option[:host] ? "-h #{option[:host]}" : nil
25
- port = option[:port] ? "-P #{option[:port]}" : nil
26
- username = option[:username] ? "-u#{option[:username]}" : nil
35
+ host = option[:host] ? "-h #{option[:host].shellescape}" : nil
36
+ port = option[:port] ? "-P #{option[:port].to_s.shellescape}" : nil
37
+ username = option[:username] ? "-u#{option[:username].shellescape}" : nil
27
38
  password = if !(option[:password].to_s.empty?)
28
- "-p\"#{option[:password].gsub('$','\\$').gsub('"','\\"').gsub('`', '\\\`')}\""
39
+ "-p#{option[:password].shellescape}"
29
40
  else
30
41
  nil
31
42
  end
32
- database = option[:database]
33
- tables = option[:tables] ? option[:tables].join(' ') : nil
43
+ database = option[:database].shellescape if option[:database]
44
+ tables = option[:tables] ? option[:tables].collect{|t| t.shellescape}.join(' ') : nil
34
45
  ssl_ca = option[:ssl_ca] ? option[:ssl_ca] : nil
35
46
  ssl_cipher = option[:ssl_cipher] ? option[:ssl_cipher] : nil
36
47
 
37
- default_option = option[:no_default_option] ? "" : DEFAULT_MYSQL_CMD_OPTION
38
- default_option += " --ssl-ca=#{ssl_ca}" if ssl_ca
48
+ default_option = option[:no_default_option] ? "" : default_cmd_option(command)
49
+ default_option += " --ssl-ca #{ssl_ca}" if ssl_ca
39
50
  default_option += " --ssl-cipher=#{ssl_cipher}" unless ssl_cipher.to_s.empty?
40
51
  default_option = nil if default_option == ''
41
52