flydata 0.5.12 → 0.5.13

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