flydata 0.2.7 → 0.2.8
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/VERSION +1 -1
- data/flydata.gemspec +3 -3
- data/lib/flydata/command/base.rb +7 -1
- data/lib/flydata/command/sync.rb +9 -0
- data/lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb +4 -2
- data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +3 -2
- data/lib/flydata/fluent-plugins/mysql/dml_record_handler.rb +1 -1
- data/lib/flydata/parser/mysql/mysql_alter_table.treetop +461 -22
- data/lib/flydata/util/encryptor.rb +1 -1
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +26 -2
- data/spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb +1 -1
- data/spec/flydata/parser/mysql/alter_table_parser_spec.rb +499 -81
- metadata +2 -2
@@ -9,7 +9,7 @@ module Flydata
|
|
9
9
|
def encrypt(text, key)
|
10
10
|
validate_presence(text: text, key: key)
|
11
11
|
cipher = build_cipher(:encrypt, key)
|
12
|
-
Base64.
|
12
|
+
Base64.strict_encode64(cipher.update(text) + cipher.final)
|
13
13
|
end
|
14
14
|
|
15
15
|
def decrypt(text, key, param_name = nil)
|
@@ -105,6 +105,10 @@ EOT
|
|
105
105
|
# QUERY: alter table modify column
|
106
106
|
TEST_EVENT_QUERY_ALTER_TABLE_MODIFY_COLUMN = <<EOT
|
107
107
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>112, "next_position"=>1352, "flags"=>0, "event_type"=>"Query", "thread_id"=>48, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"alter table test_table modify column sum float"}
|
108
|
+
EOT
|
109
|
+
# QUERY: alter table add index
|
110
|
+
TEST_EVENT_QUERY_ALTER_TABLE_ADD_INDEX = <<EOT
|
111
|
+
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>217, "next_position"=>337, "flags"=>0, "event_type"=>"Query", "thread_id"=>10097, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0, 12, 1, 109, 97, 107, 95, 100, 101, 118, 101, 108, 111, 112, 109, 101, 110, 116, 0], "db_name"=>"test_db", "query"=>"ALTER TABLE `test_db`.`test_table` \nADD INDEX `my_index` USING HASH (`extra` ASC) COMMENT 'How does this look in binlog?'"}
|
108
112
|
EOT
|
109
113
|
# - 03 STOP_EVENT
|
110
114
|
TEST_EVENT_STOP = <<EOT
|
@@ -179,6 +183,7 @@ EOT
|
|
179
183
|
let(:update_three_byte_event) { create_event(TEST_EVENT_THREE_BYTE_UPDATE) }
|
180
184
|
let(:alter_table_add_column_event) { create_event(TEST_EVENT_QUERY_ALTER_TABLE_ADD_COLUMN) }
|
181
185
|
let(:alter_table_drop_column_event) { create_event(TEST_EVENT_QUERY_ALTER_TABLE_DROP_COLUMN) }
|
186
|
+
let(:alter_table_add_index_event) { create_event(TEST_EVENT_QUERY_ALTER_TABLE_ADD_INDEX) }
|
182
187
|
|
183
188
|
let(:query_event) { create_event(TEST_EVENT_QUERY_CREATE_DATABSE) }
|
184
189
|
let(:table_map_event) { create_event(TEST_EVENT_TABLE_MAP) }
|
@@ -309,7 +314,7 @@ EOT
|
|
309
314
|
table_rev: 2, # increment revision
|
310
315
|
seq: 2,
|
311
316
|
actions: [{
|
312
|
-
action: :add_column, column: "sum", :type=>'int4'}],
|
317
|
+
action: :add_column, column: "sum", :type=>'int4', :query=>'add column sum integer'}],
|
313
318
|
})
|
314
319
|
end
|
315
320
|
end
|
@@ -324,7 +329,26 @@ EOT
|
|
324
329
|
table_rev: 2, # increment revision
|
325
330
|
seq: 2,
|
326
331
|
actions: [{
|
327
|
-
action: :drop_column, column: "sum"}],
|
332
|
+
action: :drop_column, column: "sum", :query=>'drop column sum'}],
|
333
|
+
})
|
334
|
+
end
|
335
|
+
end
|
336
|
+
|
337
|
+
context 'when received alter table add index event' do
|
338
|
+
it 'emits a nonbreaking event without table_rev increment' do
|
339
|
+
expect_emitted_records(alter_table_add_index_event, {
|
340
|
+
type: :alter_table,
|
341
|
+
table_name: "test_table",
|
342
|
+
schema_name: "test_db",
|
343
|
+
respect_order: true,
|
344
|
+
src_pos: "mysql-bin.000048\t#{337 - 217}",
|
345
|
+
table_rev: 1,
|
346
|
+
seq: 2,
|
347
|
+
actions: [{
|
348
|
+
action: :add_index,
|
349
|
+
support_level: :nonbreaking,
|
350
|
+
query: "ADD INDEX `my_index` USING HASH (`extra` ASC) COMMENT 'How does this look in binlog?'",
|
351
|
+
}],
|
328
352
|
})
|
329
353
|
end
|
330
354
|
end
|
@@ -69,7 +69,7 @@ module Mysql
|
|
69
69
|
expect(parser).to receive(:parse).and_return(nil)
|
70
70
|
end
|
71
71
|
it "returns nil with a warn log" do
|
72
|
-
expect($log).to receive(:
|
72
|
+
expect($log).to receive(:error).with(/Received unsupported alter table query\. query:'#{query}'/)
|
73
73
|
|
74
74
|
expect(subject.process(record, normalized_query)).to eq(nil)
|
75
75
|
end
|
@@ -25,7 +25,8 @@ describe 'MysqlAlterTableParser' do
|
|
25
25
|
actions: [{
|
26
26
|
action: :add_column,
|
27
27
|
column: "value",
|
28
|
-
type: "varchar(78)"
|
28
|
+
type: "varchar(78)",
|
29
|
+
query: "add column value varchar(26)"
|
29
30
|
}]
|
30
31
|
})
|
31
32
|
end
|
@@ -41,7 +42,8 @@ describe 'MysqlAlterTableParser' do
|
|
41
42
|
actions: [{
|
42
43
|
action: :add_column,
|
43
44
|
column: "value",
|
44
|
-
type: "varbinary(4294967295)"
|
45
|
+
type: "varbinary(4294967295)",
|
46
|
+
query: "add column value longblob"
|
45
47
|
}]
|
46
48
|
})
|
47
49
|
end
|
@@ -57,28 +59,42 @@ describe 'MysqlAlterTableParser' do
|
|
57
59
|
actions: [{
|
58
60
|
action: :add_column,
|
59
61
|
column: "value",
|
60
|
-
type: "varchar(78)"
|
62
|
+
type: "varchar(78)",
|
63
|
+
query: "add value varchar(26)"
|
61
64
|
}]
|
62
65
|
})
|
63
66
|
end
|
64
67
|
end
|
65
68
|
|
66
69
|
context 'with multiple columns' do
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
70
|
+
shared_examples 'test result hash' do
|
71
|
+
it do
|
72
|
+
expect(subject).to eq({
|
73
|
+
type: :alter_table,
|
74
|
+
table_name: "test_table",
|
75
|
+
actions: [{
|
76
|
+
action: :add_column,
|
77
|
+
column: "value1",
|
78
|
+
type: "varchar(78)",
|
79
|
+
query: "#{expected_query}"
|
80
|
+
},{
|
81
|
+
action: :add_column,
|
82
|
+
column: "value2",
|
83
|
+
type: "varchar(78)",
|
84
|
+
query: "#{expected_query}"
|
85
|
+
}]
|
86
|
+
})
|
87
|
+
end
|
88
|
+
end
|
89
|
+
context 'with spaces before opening bracket' do
|
90
|
+
let(:query) { "alter table test_table add column (value1 varchar(26), value2 varchar(26))" }
|
91
|
+
let(:expected_query) {"add column (value1 varchar(26), value2 varchar(26))"}
|
92
|
+
include_examples 'test result hash'
|
93
|
+
end
|
94
|
+
context 'without spaces before opening bracket' do
|
95
|
+
let(:query) { "alter table test_table add column(value1 varchar(26), value2 varchar(26))" }
|
96
|
+
let(:expected_query) {"add column(value1 varchar(26), value2 varchar(26))"}
|
97
|
+
include_examples 'test result hash'
|
82
98
|
end
|
83
99
|
end
|
84
100
|
|
@@ -91,11 +107,13 @@ describe 'MysqlAlterTableParser' do
|
|
91
107
|
actions: [{
|
92
108
|
action: :add_column,
|
93
109
|
column: "value1",
|
94
|
-
type: "varchar(78)"
|
110
|
+
type: "varchar(78)",
|
111
|
+
query: "add ( value1 varchar(26), value2 varchar(26) )"
|
95
112
|
},{
|
96
113
|
action: :add_column,
|
97
114
|
column: "value2",
|
98
|
-
type: "varchar(78)"
|
115
|
+
type: "varchar(78)",
|
116
|
+
query: "add ( value1 varchar(26), value2 varchar(26) )"
|
99
117
|
}]
|
100
118
|
})
|
101
119
|
end
|
@@ -113,11 +131,13 @@ describe 'MysqlAlterTableParser' do
|
|
113
131
|
type: "varchar(78)",
|
114
132
|
not_null: true,
|
115
133
|
default: "flydata",
|
134
|
+
query: "add (value1 varchar(26) not null default 'flydata', value2 int auto_increment)"
|
116
135
|
},{
|
117
136
|
action: :add_column,
|
118
137
|
column: "value2",
|
119
138
|
type: "int4",
|
120
139
|
auto_increment: true,
|
140
|
+
query: "add (value1 varchar(26) not null default 'flydata', value2 int auto_increment)"
|
121
141
|
}]
|
122
142
|
})
|
123
143
|
end
|
@@ -135,11 +155,13 @@ describe 'MysqlAlterTableParser' do
|
|
135
155
|
type: "varchar(78)",
|
136
156
|
not_null: true,
|
137
157
|
default: "flydata",
|
158
|
+
query: "add (`value1` varchar(26) not null default 'flydata', `value2` int auto_increment)"
|
138
159
|
},{
|
139
160
|
action: :add_column,
|
140
161
|
column: "value2",
|
141
162
|
type: "int4",
|
142
163
|
auto_increment: true,
|
164
|
+
query: "add (`value1` varchar(26) not null default 'flydata', `value2` int auto_increment)"
|
143
165
|
}]
|
144
166
|
})
|
145
167
|
end
|
@@ -156,13 +178,15 @@ describe 'MysqlAlterTableParser' do
|
|
156
178
|
column: "value",
|
157
179
|
type: "varchar(78)",
|
158
180
|
after: 'id',
|
181
|
+
query: "add column value varchar(26) after id"
|
159
182
|
}]
|
160
183
|
})
|
161
184
|
end
|
162
185
|
end
|
163
|
-
|
164
|
-
|
165
|
-
let(:
|
186
|
+
shared_examples "generating a flydata record for the given query" do
|
187
|
+
let(:after_column_name) { 'id' }
|
188
|
+
let(:actions) { %Q|add column value varchar(26) comment 'Ignorable comment' after #{after_column}| }
|
189
|
+
let(:query) { %Q|alter table `test_table` #{actions}| }
|
166
190
|
it do
|
167
191
|
expect(subject).to eq({
|
168
192
|
type: :alter_table,
|
@@ -171,11 +195,23 @@ describe 'MysqlAlterTableParser' do
|
|
171
195
|
action: :add_column,
|
172
196
|
column: "value",
|
173
197
|
type: "varchar(78)",
|
174
|
-
after:
|
198
|
+
after: after_column_name,
|
199
|
+
query: actions
|
175
200
|
}]
|
176
201
|
})
|
177
202
|
end
|
178
203
|
end
|
204
|
+
context 'with after option, quoted after column name' do
|
205
|
+
let(:after_column) { "`#{after_column_name}`" }
|
206
|
+
|
207
|
+
it_behaves_like "generating a flydata record for the given query"
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'with after option, backticks only on table name and a comment' do
|
211
|
+
let(:after_column) { after_column_name }
|
212
|
+
|
213
|
+
it_behaves_like "generating a flydata record for the given query"
|
214
|
+
end
|
179
215
|
|
180
216
|
context 'with first option' do
|
181
217
|
let(:query) { "alter table test_table add column value varchar(26) first" }
|
@@ -188,6 +224,7 @@ describe 'MysqlAlterTableParser' do
|
|
188
224
|
column: "value",
|
189
225
|
type: "varchar(78)",
|
190
226
|
position: :first,
|
227
|
+
query: "add column value varchar(26) first"
|
191
228
|
}]
|
192
229
|
})
|
193
230
|
end
|
@@ -205,6 +242,7 @@ describe 'MysqlAlterTableParser' do
|
|
205
242
|
type: "varchar(78)",
|
206
243
|
unique: true,
|
207
244
|
position: :first,
|
245
|
+
query: "add column value varchar(26) UNIQUE first"
|
208
246
|
}]
|
209
247
|
})
|
210
248
|
end
|
@@ -214,7 +252,7 @@ describe 'MysqlAlterTableParser' do
|
|
214
252
|
shared_examples "a query parser parsing a query adding a column with a default value" do
|
215
253
|
let(:query) { "alter table test_table add column col #{data_type} default #{value}" }
|
216
254
|
it do
|
217
|
-
|
255
|
+
is_expected.to eq({
|
218
256
|
type: :alter_table,
|
219
257
|
table_name: "test_table",
|
220
258
|
actions: [{
|
@@ -222,108 +260,109 @@ describe 'MysqlAlterTableParser' do
|
|
222
260
|
column: "col",
|
223
261
|
type: expected_data_type,
|
224
262
|
default: expected_value,
|
263
|
+
query: "add column col #{data_type} default #{value}"
|
225
264
|
}]
|
226
265
|
})
|
227
266
|
end
|
228
267
|
end
|
229
|
-
|
268
|
+
|
230
269
|
context 'for timestamp column' do
|
231
270
|
let(:data_type) { "timestamp" }
|
232
271
|
let(:expected_data_type) { "datetime" }
|
233
272
|
context 'taking current_timestamp' do
|
234
273
|
let(:value) { "current_timestamp" }
|
235
274
|
let(:expected_value) { "current_timestamp" }
|
236
|
-
|
275
|
+
|
237
276
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
238
277
|
end
|
239
278
|
context 'taking localtime' do
|
240
279
|
let(:value) { "localtime" }
|
241
280
|
let(:expected_value) { "current_timestamp" }
|
242
|
-
|
281
|
+
|
243
282
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
244
283
|
end
|
245
284
|
context 'taking localtimestamp' do
|
246
285
|
let(:value) { "localtimestamp" }
|
247
286
|
let(:expected_value) { "current_timestamp" }
|
248
|
-
|
287
|
+
|
249
288
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
250
289
|
end
|
251
290
|
context 'taking now()' do
|
252
291
|
let(:value) { "now()" }
|
253
292
|
let(:expected_value) { "current_timestamp" }
|
254
|
-
|
293
|
+
|
255
294
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
256
295
|
end
|
257
296
|
end
|
258
|
-
|
297
|
+
|
259
298
|
context 'for integer column' do
|
260
299
|
let(:data_type) { "int(11)" }
|
261
300
|
let(:expected_data_type) { "int4(11)" }
|
262
|
-
|
301
|
+
|
263
302
|
context 'taking a positive number without sign' do
|
264
303
|
let(:value) { "1" }
|
265
304
|
let(:expected_value) { "1" }
|
266
|
-
|
305
|
+
|
267
306
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
268
307
|
end
|
269
308
|
context 'taking a positive number' do
|
270
309
|
let(:value) { "+1" }
|
271
310
|
let(:expected_value) { "1" }
|
272
|
-
|
311
|
+
|
273
312
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
274
313
|
end
|
275
314
|
context 'taking a negative number' do
|
276
315
|
let(:value) { "-1" }
|
277
316
|
let(:expected_value) { "-1" }
|
278
|
-
|
317
|
+
|
279
318
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
280
319
|
end
|
281
320
|
context 'taking a negative number string' do
|
282
321
|
let(:value) { %Q|'-1'| }
|
283
322
|
let(:expected_value) { "-1" }
|
284
|
-
|
323
|
+
|
285
324
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
286
325
|
end
|
287
326
|
context 'taking null' do
|
288
327
|
let(:value) { %Q|NULL| }
|
289
328
|
let(:expected_value) { nil }
|
290
|
-
|
329
|
+
|
291
330
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
292
331
|
end
|
293
332
|
end
|
294
|
-
|
333
|
+
|
295
334
|
context 'for decimal column' do
|
296
335
|
let(:data_type) { "decimal(10,2)" }
|
297
336
|
let(:expected_data_type) { "numeric(10,2)" }
|
298
|
-
|
337
|
+
|
299
338
|
context 'taking a positive number without sign' do
|
300
339
|
let(:value) { "2.4" }
|
301
340
|
let(:expected_value) { "2.4" }
|
302
|
-
|
341
|
+
|
303
342
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
304
343
|
end
|
305
344
|
context 'taking a positive number with sign' do
|
306
345
|
let(:value) { "+0.4" }
|
307
346
|
let(:expected_value) { "0.4" }
|
308
|
-
|
347
|
+
|
309
348
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
310
349
|
end
|
311
350
|
context 'taking a positive number no integer part' do
|
312
351
|
let(:value) { ".05" }
|
313
352
|
let(:expected_value) { "0.05" }
|
314
|
-
|
353
|
+
|
315
354
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
316
355
|
end
|
317
356
|
context 'taking a negative number' do
|
318
357
|
let(:value) { "-20.43" }
|
319
358
|
let(:expected_value) { "-20.43" }
|
320
|
-
|
359
|
+
|
321
360
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
322
361
|
end
|
323
362
|
context 'taking a negative number no integer part' do
|
324
363
|
let(:value) { "-.43" }
|
325
364
|
let(:expected_value) { "-0.43" }
|
326
|
-
|
365
|
+
|
327
366
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
328
367
|
end
|
329
368
|
end
|
@@ -331,35 +370,35 @@ describe 'MysqlAlterTableParser' do
|
|
331
370
|
context 'for varchar column' do
|
332
371
|
let(:data_type) { "varchar(10)" }
|
333
372
|
let(:expected_data_type) { "varchar(30)" }
|
334
|
-
|
373
|
+
|
335
374
|
context 'taking null' do
|
336
375
|
let(:value) { "NULL" }
|
337
376
|
let(:expected_value) { nil }
|
338
|
-
|
377
|
+
|
339
378
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
340
379
|
end
|
341
380
|
context 'taking empty string' do
|
342
381
|
let(:value) { %Q|''| }
|
343
382
|
let(:expected_value) { "" }
|
344
|
-
|
383
|
+
|
345
384
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
346
385
|
end
|
347
386
|
context 'taking a string with spaces' do
|
348
387
|
let(:value) { %Q|'0 0 0 0 0 0 0'| }
|
349
388
|
let(:expected_value) { "0 0 0 0 0 0 0" }
|
350
|
-
|
389
|
+
|
351
390
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
352
391
|
end
|
353
392
|
context 'taking a backslash' do
|
354
393
|
let(:value) { %q|'\\\\'| }
|
355
394
|
let(:expected_value) { %q|\\\\| }
|
356
|
-
|
395
|
+
|
357
396
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
358
397
|
end
|
359
398
|
context 'taking a string with special characters' do
|
360
399
|
let(:value) { %q|'https://flydata.com $ \\\\\'\"\n\t'| }
|
361
400
|
let(:expected_value) { %q|https://flydata.com $ \\\\\'\"\n\t| }
|
362
|
-
|
401
|
+
|
363
402
|
it_behaves_like "a query parser parsing a query adding a column with a default value"
|
364
403
|
end
|
365
404
|
end
|
@@ -376,6 +415,7 @@ describe 'MysqlAlterTableParser' do
|
|
376
415
|
action: :add_column,
|
377
416
|
column: "extra",
|
378
417
|
type: "varchar(#{length * 3})",
|
418
|
+
query: "add column extra varchar(#{length}) null"
|
379
419
|
}]
|
380
420
|
})
|
381
421
|
end
|
@@ -390,7 +430,8 @@ describe 'MysqlAlterTableParser' do
|
|
390
430
|
table_name: "test_table",
|
391
431
|
actions: [{
|
392
432
|
action: :drop_column,
|
393
|
-
column: "value"
|
433
|
+
column: "value",
|
434
|
+
query: "drop column value"
|
394
435
|
}])
|
395
436
|
end
|
396
437
|
end
|
@@ -403,7 +444,8 @@ describe 'MysqlAlterTableParser' do
|
|
403
444
|
table_name: "test_table",
|
404
445
|
actions: [{
|
405
446
|
action: :drop_column,
|
406
|
-
column: "value"
|
447
|
+
column: "value",
|
448
|
+
query: "drop value"
|
407
449
|
}])
|
408
450
|
end
|
409
451
|
end
|
@@ -416,7 +458,8 @@ describe 'MysqlAlterTableParser' do
|
|
416
458
|
table_name: "test_table",
|
417
459
|
actions: [{
|
418
460
|
action: :drop_column,
|
419
|
-
column: "value"
|
461
|
+
column: "value",
|
462
|
+
query: "drop `value`"
|
420
463
|
}])
|
421
464
|
end
|
422
465
|
end
|
@@ -429,7 +472,8 @@ describe 'MysqlAlterTableParser' do
|
|
429
472
|
table_name: "test_table",
|
430
473
|
actions: [{
|
431
474
|
action: :drop_column,
|
432
|
-
column: "value"
|
475
|
+
column: "value",
|
476
|
+
query: "drop value"
|
433
477
|
}])
|
434
478
|
end
|
435
479
|
end
|
@@ -442,7 +486,8 @@ describe 'MysqlAlterTableParser' do
|
|
442
486
|
table_name: "test_table",
|
443
487
|
actions: [{
|
444
488
|
action: :drop_column,
|
445
|
-
column: "value"
|
489
|
+
column: "value",
|
490
|
+
query: "DROP value"
|
446
491
|
}])
|
447
492
|
end
|
448
493
|
end
|
@@ -456,7 +501,8 @@ describe 'MysqlAlterTableParser' do
|
|
456
501
|
table_name: "test_table",
|
457
502
|
actions: [{
|
458
503
|
action: :drop_column,
|
459
|
-
column: "value"
|
504
|
+
column: "value",
|
505
|
+
query: "drop value"
|
460
506
|
}])
|
461
507
|
end
|
462
508
|
end
|
@@ -470,35 +516,12 @@ describe 'MysqlAlterTableParser' do
|
|
470
516
|
table_name: "test_table",
|
471
517
|
actions: [{
|
472
518
|
action: :drop_column,
|
473
|
-
column: "value"
|
519
|
+
column: "value",
|
520
|
+
query: "drop `value`"
|
474
521
|
}])
|
475
522
|
end
|
476
523
|
end
|
477
524
|
|
478
|
-
context 'when query has unsupported drop dextension' do
|
479
|
-
subject { parser.parse(query) }
|
480
|
-
|
481
|
-
context 'with primary key drop' do
|
482
|
-
let(:query) { "alter table test_table drop PRIMARY KEY" }
|
483
|
-
it { expect(subject).to be_nil }
|
484
|
-
end
|
485
|
-
|
486
|
-
context 'with index drop' do
|
487
|
-
let(:query) { "alter table test_table drop Index index_name" }
|
488
|
-
it { expect(subject).to be_nil }
|
489
|
-
end
|
490
|
-
|
491
|
-
context 'with key drop' do
|
492
|
-
let(:query) { "alter table test_table drop key index_name" }
|
493
|
-
it { expect(subject).to be_nil }
|
494
|
-
end
|
495
|
-
|
496
|
-
context 'with foreign key drop' do
|
497
|
-
let(:query) { "alter table test_table drop foreign key foreign_key_name" }
|
498
|
-
it { expect(subject).to be_nil }
|
499
|
-
end
|
500
|
-
end
|
501
|
-
|
502
525
|
context 'with multiple alter specs' do
|
503
526
|
context 'with add column and drop column' do
|
504
527
|
let(:query) { "alter table test_table add column value varchar(26) after id, drop old_value" }
|
@@ -511,13 +534,408 @@ describe 'MysqlAlterTableParser' do
|
|
511
534
|
column: "value",
|
512
535
|
type: "varchar(78)",
|
513
536
|
after: 'id',
|
537
|
+
query: "add column value varchar(26) after id"
|
514
538
|
},{
|
515
539
|
action: :drop_column,
|
516
540
|
column: "old_value",
|
541
|
+
query: "drop old_value"
|
517
542
|
}]
|
518
543
|
})
|
519
544
|
end
|
520
545
|
end
|
521
546
|
end
|
547
|
+
|
548
|
+
let(:query) { "ALTER TABLE `test_schema`.`test_table` #{alter_table_action}" }
|
549
|
+
shared_examples "a parser parsing a single action alter table query" do
|
550
|
+
it do
|
551
|
+
is_expected.to eq({
|
552
|
+
type: :alter_table,
|
553
|
+
schema_name: "test_schema",
|
554
|
+
table_name: "test_table",
|
555
|
+
actions: [action_hash]
|
556
|
+
})
|
557
|
+
end
|
558
|
+
end
|
559
|
+
shared_examples "a parser parsing a nonbreaking query" do
|
560
|
+
let(:action_hash) {
|
561
|
+
{
|
562
|
+
action: action,
|
563
|
+
support_level: :nonbreaking,
|
564
|
+
query: alter_table_action,
|
565
|
+
}
|
566
|
+
}
|
567
|
+
it_behaves_like "a parser parsing a single action alter table query"
|
568
|
+
end
|
569
|
+
shared_examples "a parser parsing a breaking query" do
|
570
|
+
let(:action_hash) {
|
571
|
+
{
|
572
|
+
action: action,
|
573
|
+
query: alter_table_action,
|
574
|
+
}
|
575
|
+
}
|
576
|
+
it_behaves_like "a parser parsing a single action alter table query"
|
577
|
+
end
|
578
|
+
shared_examples "a debug parser" do
|
579
|
+
it do
|
580
|
+
puts query
|
581
|
+
result = parser.parse(query)
|
582
|
+
p result
|
583
|
+
puts "FAILURE: #{parser.failure_reason}"
|
584
|
+
end
|
585
|
+
end
|
586
|
+
shared_examples "test normal key options" do |*examples|
|
587
|
+
context "with normal key options" do
|
588
|
+
context "key_block_size" do
|
589
|
+
let(:normal_key_options) { " KEY_BLOCK_SIZE = 102400" }
|
590
|
+
it_behaves_like *examples
|
591
|
+
end
|
592
|
+
context "key_block_size with no space" do
|
593
|
+
let(:normal_key_options) { " KEY_BLOCK_SIZE=102400" }
|
594
|
+
it_behaves_like *examples
|
595
|
+
end
|
596
|
+
context "key_block_size no equal sign" do
|
597
|
+
let(:normal_key_options) { " KEY_BLOCK_SIZE 102400" }
|
598
|
+
it_behaves_like *examples
|
599
|
+
end
|
600
|
+
context "using" do
|
601
|
+
let(:normal_key_options) { " using btree" }
|
602
|
+
it_behaves_like *examples
|
603
|
+
end
|
604
|
+
context "comment" do
|
605
|
+
let(:normal_key_options) { " comment 'Hello World!'" }
|
606
|
+
it_behaves_like *examples
|
607
|
+
end
|
608
|
+
context "key_block_size and comment" do
|
609
|
+
let(:normal_key_options) { " KEY_BLOCK_SIZE 102400 comment 'Hello World!'" }
|
610
|
+
it_behaves_like *examples
|
611
|
+
end
|
612
|
+
context "none" do
|
613
|
+
it_behaves_like *examples do
|
614
|
+
let(:normal_key_options) { "" }
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
618
|
+
end
|
619
|
+
shared_examples "test key list" do |*examples|
|
620
|
+
context "with a single key" do
|
621
|
+
it_behaves_like *examples do
|
622
|
+
let(:key_list) { " testKey" }
|
623
|
+
let(:expected_key_list) { [ "testKey" ] }
|
624
|
+
end
|
625
|
+
end
|
626
|
+
context "with a quoted single key" do
|
627
|
+
it_behaves_like *examples do
|
628
|
+
let(:key_list) { " `testKey`" }
|
629
|
+
let(:expected_key_list) { [ "testKey" ] }
|
630
|
+
end
|
631
|
+
end
|
632
|
+
context "with multiple keys with order" do
|
633
|
+
it_behaves_like *examples do
|
634
|
+
let(:key_list) { " testKey1 ASC, testKey2 desc" }
|
635
|
+
let(:expected_key_list) { [ "testKey1 asc", "testKey2 desc" ] }
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
shared_examples "test constraint keyword" do |*examples|
|
641
|
+
context "with constraint keyword" do
|
642
|
+
context "with constraint name" do
|
643
|
+
it_behaves_like *examples do
|
644
|
+
let(:constraint_keyword) { " CONSTRAINT `chkName`" }
|
645
|
+
end
|
646
|
+
end
|
647
|
+
context "without constraint name" do
|
648
|
+
it_behaves_like *examples do
|
649
|
+
let(:constraint_keyword) { " CONSTRAINT" }
|
650
|
+
end
|
651
|
+
end
|
652
|
+
end
|
653
|
+
context "without constraint keyword" do
|
654
|
+
it_behaves_like *examples do
|
655
|
+
let(:constraint_keyword) { "" }
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
shared_examples "test key name" do |*examples|
|
660
|
+
context "with key name" do
|
661
|
+
it_behaves_like *examples do
|
662
|
+
let(:key_name) { " testKey" }
|
663
|
+
end
|
664
|
+
end
|
665
|
+
context "without key name" do
|
666
|
+
it_behaves_like *examples do
|
667
|
+
let(:key_name) { "" }
|
668
|
+
end
|
669
|
+
end
|
670
|
+
context "with quoted key name" do
|
671
|
+
it_behaves_like *examples do
|
672
|
+
let(:key_name) { " `testKey`" }
|
673
|
+
end
|
674
|
+
end
|
675
|
+
end
|
676
|
+
shared_examples "test key or index" do |*examples|
|
677
|
+
context "with key" do
|
678
|
+
it_behaves_like *examples do
|
679
|
+
let(:key_or_index) { " KEY" }
|
680
|
+
end
|
681
|
+
end
|
682
|
+
context "with index" do
|
683
|
+
it_behaves_like *examples do
|
684
|
+
let(:key_or_index) { " index" }
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
shared_examples "test optional key or index" do |*examples|
|
689
|
+
include_examples "test key or index", *examples
|
690
|
+
context "with none" do
|
691
|
+
it_behaves_like *examples do
|
692
|
+
let(:key_or_index) { "" }
|
693
|
+
end
|
694
|
+
end
|
695
|
+
end
|
696
|
+
shared_examples "test using option" do |*examples|
|
697
|
+
context "with BTREE" do
|
698
|
+
it_behaves_like *examples do
|
699
|
+
let(:using_option) { " USING BTREE" }
|
700
|
+
end
|
701
|
+
end
|
702
|
+
context "with hash" do
|
703
|
+
it_behaves_like *examples do
|
704
|
+
let(:using_option) { " using hash" }
|
705
|
+
end
|
706
|
+
end
|
707
|
+
context "with none" do
|
708
|
+
it_behaves_like *examples do
|
709
|
+
let(:using_option) { "" }
|
710
|
+
end
|
711
|
+
end
|
712
|
+
end
|
713
|
+
shared_examples "test field identifier" do |*examples|
|
714
|
+
context "without ." do
|
715
|
+
it_behaves_like "test identifier", *examples do
|
716
|
+
let(:field_ident) { " #{ident}" }
|
717
|
+
end
|
718
|
+
end
|
719
|
+
context "with single ." do
|
720
|
+
it_behaves_like "test identifier", *examples do
|
721
|
+
let(:field_ident) { " #{ident}.#{ident}"}
|
722
|
+
end
|
723
|
+
end
|
724
|
+
context "with two ." do
|
725
|
+
it_behaves_like "test identifier", *examples do
|
726
|
+
let(:field_ident) { " #{ident}.#{ident}.#{ident}" }
|
727
|
+
end
|
728
|
+
end
|
729
|
+
end
|
730
|
+
shared_examples "test identifier" do |*examples|
|
731
|
+
context "unquoted identifier" do
|
732
|
+
it_behaves_like *examples do
|
733
|
+
let(:ident) {"test_ident1"}
|
734
|
+
end
|
735
|
+
end
|
736
|
+
context "quoted identifier" do
|
737
|
+
it_behaves_like *examples do
|
738
|
+
let(:ident) {"`test_ident1`"}
|
739
|
+
end
|
740
|
+
end
|
741
|
+
end
|
742
|
+
|
743
|
+
context 'add index' do
|
744
|
+
let(:action) { :add_index }
|
745
|
+
context "with a simple add index" do
|
746
|
+
let(:alter_table_action) { "ADD INDEX `test` (`t_now`)" }
|
747
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
748
|
+
end
|
749
|
+
context "with a simple add index and without space before the opening bracket" do
|
750
|
+
let(:alter_table_action) { "ADD INDEX `test`(`t_now`)" }
|
751
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
752
|
+
end
|
753
|
+
context "with a simple add index with order" do
|
754
|
+
let(:alter_table_action) { "ADD INDEX `test` (`t_now` ASC)" }
|
755
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
756
|
+
end
|
757
|
+
context "with an add index with multiple fields" do
|
758
|
+
let(:key_list) { "`t_now` ASC, `t_timestamp` DESC" }
|
759
|
+
let(:alter_table_action) { "ADD INDEX `test` (#{key_list})" }
|
760
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
761
|
+
|
762
|
+
context "with spaces around key list" do
|
763
|
+
let(:key_list) { " `t_now` ASC, `t_timestamp` DESC " }
|
764
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
765
|
+
end
|
766
|
+
|
767
|
+
context "with a field without order" do
|
768
|
+
let(:key_list) { " `t_now` ASC, `t_timestamp`" }
|
769
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
770
|
+
end
|
771
|
+
end
|
772
|
+
context "with an add index with no index name" do
|
773
|
+
let(:alter_table_action) { "ADD INDEX (`t_now` ASC)" }
|
774
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
775
|
+
end
|
776
|
+
context "with an add index with USING" do
|
777
|
+
let(:using_option) { "USING BTREE" }
|
778
|
+
let(:alter_table_action) { "ADD INDEX `test` #{using_option} (`t_now` ASC)" }
|
779
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
780
|
+
|
781
|
+
context "without index name" do
|
782
|
+
let(:alter_table_action) { "ADD INDEX #{using_option} (`t_now` ASC)" }
|
783
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
784
|
+
end
|
785
|
+
|
786
|
+
context "without index name and without space before the opening bracket" do
|
787
|
+
let(:alter_table_action) { "ADD INDEX #{using_option}(`t_now` ASC)" }
|
788
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
789
|
+
end
|
790
|
+
|
791
|
+
context "with hash" do
|
792
|
+
let(:using_option) { "USING hash" }
|
793
|
+
it_behaves_like "a parser parsing a nonbreaking query"
|
794
|
+
end
|
795
|
+
end
|
796
|
+
context "with normal key options" do
|
797
|
+
let(:alter_table_action) { "ADD INDEX (`t_now` ASC)#{normal_key_options}" }
|
798
|
+
it_behaves_like "test normal key options", "a parser parsing a nonbreaking query"
|
799
|
+
end
|
800
|
+
end
|
801
|
+
context "fulltext or spatial" do
|
802
|
+
let(:action) { :add_index }
|
803
|
+
shared_examples "test all permutations" do |examples|
|
804
|
+
context "key_or_index" do
|
805
|
+
shared_examples "a parser parsing a nonbreaking query with key options" do
|
806
|
+
let(:alter_table_action) { "ADD #{fulltext_or_spatial} #{key_or_index} #{key_name} (test_column)#{key_options}" }
|
807
|
+
context "no key option" do
|
808
|
+
it_behaves_like "a parser parsing a nonbreaking query" do
|
809
|
+
let(:key_options) { "" }
|
810
|
+
end
|
811
|
+
end
|
812
|
+
context "key_block_size" do
|
813
|
+
it_behaves_like "a parser parsing a nonbreaking query" do
|
814
|
+
let(:key_options) { " KEY_BLOCK_SIZE 2048" }
|
815
|
+
end
|
816
|
+
end
|
817
|
+
context "comment" do
|
818
|
+
it_behaves_like "a parser parsing a nonbreaking query" do
|
819
|
+
let(:key_options) { " COMMENT 'Hello World!'" }
|
820
|
+
end
|
821
|
+
end
|
822
|
+
context "comment and key_block_size" do
|
823
|
+
it_behaves_like "a parser parsing a nonbreaking query" do
|
824
|
+
let(:key_options) { " KEY_BLOCK_SIZE = 1024 COMMENT 'Hello World!'" }
|
825
|
+
end
|
826
|
+
end
|
827
|
+
end
|
828
|
+
shared_examples "a parser parsing a nonbreaking query with key options fulltext" do
|
829
|
+
it_behaves_like "a parser parsing a nonbreaking query with key options"
|
830
|
+
let(:alter_table_action) { "ADD #{fulltext_or_spatial} #{key_or_index} #{key_name} (test_column)#{key_options}" }
|
831
|
+
context "with parser" do
|
832
|
+
it_behaves_like "a parser parsing a nonbreaking query" do
|
833
|
+
let(:key_options) { " WITH PARSER test_parser" }
|
834
|
+
end
|
835
|
+
end
|
836
|
+
end
|
837
|
+
shared_examples "a parser parsing a query with either key or index" do |*examples|
|
838
|
+
let(:alter_table_action) { "ADD #{fulltext_or_spatial} #{key_or_index} #{key_name} (test_column)" }
|
839
|
+
context "no key name" do
|
840
|
+
it_behaves_like *examples do
|
841
|
+
let(:key_name) { "" }
|
842
|
+
end
|
843
|
+
end
|
844
|
+
context "simple key name" do
|
845
|
+
it_behaves_like *examples do
|
846
|
+
let(:key_name) { "test_key" }
|
847
|
+
end
|
848
|
+
end
|
849
|
+
context "quoted key name" do
|
850
|
+
it_behaves_like *examples do
|
851
|
+
let(:key_name) { "`test_key`" }
|
852
|
+
end
|
853
|
+
end
|
854
|
+
end
|
855
|
+
it_behaves_like "test optional key or index", "a parser parsing a query with either key or index", examples
|
856
|
+
end
|
857
|
+
end
|
858
|
+
context "with fulltext" do
|
859
|
+
it_behaves_like "test all permutations", "a parser parsing a nonbreaking query with key options fulltext" do
|
860
|
+
let(:fulltext_or_spatial) { "FULLTEXT" }
|
861
|
+
end
|
862
|
+
end
|
863
|
+
context "with spatial" do
|
864
|
+
it_behaves_like "test all permutations", "a parser parsing a nonbreaking query with key options" do
|
865
|
+
let(:fulltext_or_spatial) { "SPATIAL" }
|
866
|
+
end
|
867
|
+
end
|
868
|
+
end
|
869
|
+
context "check constraint" do
|
870
|
+
let(:action) { :add_check_constraint }
|
871
|
+
let(:alter_table_action) { "ADD#{constraint_keyword} CHECK (#{constraint_expr})" }
|
872
|
+
shared_examples "test constraint expr" do
|
873
|
+
context "with constraint expr" do
|
874
|
+
it_behaves_like "test constraint keyword", "a parser parsing a nonbreaking query" do
|
875
|
+
let(:constraint_expr) { "P_Id>0 AND City='Sandnes'" }
|
876
|
+
end
|
877
|
+
end
|
878
|
+
end
|
879
|
+
|
880
|
+
context "test all" do
|
881
|
+
it_behaves_like "test constraint expr"
|
882
|
+
end
|
883
|
+
end
|
884
|
+
context "unique constraint" do
|
885
|
+
let(:action) { :add_unique_constraint }
|
886
|
+
let(:alter_table_action) { "ADD#{constraint_keyword} UNIQUE#{key_or_index}#{key_name}#{using_option} (#{key_list})#{normal_key_options}" }
|
887
|
+
|
888
|
+
it_behaves_like "test constraint keyword", "test optional key or index",
|
889
|
+
"test key name", "test using option", "test key list",
|
890
|
+
"test normal key options",
|
891
|
+
# "a debug parser"
|
892
|
+
"a parser parsing a nonbreaking query"
|
893
|
+
end
|
894
|
+
context "primary key constraint" do
|
895
|
+
let(:alter_table_action) { "ADD#{constraint_keyword} PRIMARY KEY#{key_name}#{using_option} (#{key_list})#{normal_key_options}" }
|
896
|
+
let(:action) { :add_primary_key_constraint }
|
897
|
+
let(:action_hash) {
|
898
|
+
{
|
899
|
+
action: action,
|
900
|
+
keys: expected_key_list,
|
901
|
+
query: alter_table_action,
|
902
|
+
}
|
903
|
+
}
|
904
|
+
|
905
|
+
it_behaves_like "test constraint keyword",
|
906
|
+
"test key name", "test using option", "test key list",
|
907
|
+
"test normal key options",
|
908
|
+
# "a debug parser"
|
909
|
+
"a parser parsing a single action alter table query"
|
910
|
+
end
|
911
|
+
context "enable keys" do
|
912
|
+
let(:alter_table_action) { "ENABLE KEYS" }
|
913
|
+
let(:action) { :enable_keys }
|
914
|
+
let(:action_hash) {
|
915
|
+
{
|
916
|
+
action: action,
|
917
|
+
support_level: :nonbreaking,
|
918
|
+
query: alter_table_action,
|
919
|
+
}
|
920
|
+
}
|
921
|
+
end
|
922
|
+
context "drop primary key" do
|
923
|
+
let(:alter_table_action) { "DROP PRIMARY KEY" }
|
924
|
+
let(:action) { :drop_primary_key }
|
925
|
+
|
926
|
+
it_behaves_like "a parser parsing a breaking query"
|
927
|
+
end
|
928
|
+
context "drop foreign key" do
|
929
|
+
let(:alter_table_action) { "DROP FOREIGN KEY#{field_ident}" }
|
930
|
+
let(:action) { :drop_foreign_key }
|
931
|
+
|
932
|
+
it_behaves_like "test field identifier", "a parser parsing a nonbreaking query"
|
933
|
+
end
|
934
|
+
context "drop key or index" do
|
935
|
+
let(:alter_table_action) { "DROP#{key_or_index}#{field_ident}" }
|
936
|
+
let(:action) { "drop_#{key_or_index.strip.downcase}".to_sym }
|
937
|
+
|
938
|
+
it_behaves_like "test key or index", "test field identifier", "a parser parsing a nonbreaking query"
|
939
|
+
end
|
522
940
|
end
|
523
941
|
end
|