ddl_parser 0.0.9 → 0.0.10
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.
- data/.gitignore +1 -0
- data/Vagrantfile +9 -0
- data/lib/ddl_parser/ddl/db2/parser.rb +112 -112
- data/lib/ddl_parser/translator/column.rb +132 -99
- data/lib/ddl_parser/version.rb +1 -1
- data/spec/ddl_parser/ddl/db2/create_table_spec.rb +518 -506
- data/spec/ddl_parser/translator/column_spec.rb +110 -99
- metadata +3 -2
@@ -1,506 +1,518 @@
|
|
1
|
-
require_relative '../../../../spec/spec_helper'
|
2
|
-
|
3
|
-
describe DDLParser::DDL::DB2::Parser do
|
4
|
-
let(:parser) { DDLParser::DDL::DB2::Parser.new }
|
5
|
-
|
6
|
-
context 'building blocks' do
|
7
|
-
|
8
|
-
it 'parses arglist' do
|
9
|
-
parser.arglist.parse('a').should == {:item=> 'a'}
|
10
|
-
parser.arglist.parse('a,b,c').should == [{:item=> 'a'}, {:item=> 'b'}, {:item=> 'c'}]
|
11
|
-
parser.arglist.parse('a, b, c').should == [{:item=> 'a'}, {:item=> 'b'}, {:item=> 'c'}]
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'column options parsing' do
|
17
|
-
it 'parses not null' do
|
18
|
-
expect(parser.column_options).to parse('not null')
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'parses default values' do
|
22
|
-
parser.column_options.parse('default 1').should == [{:default_clause=>[{:integer=> '1'}]}]
|
23
|
-
parser.column_options.parse('with default 1').should == [{:default_clause=>[{:integer=> '1'}]}]
|
24
|
-
parser.column_options.parse('default current timestamp').should == [{:default_clause=>[{:timestamp => "current timestamp"}]}]
|
25
|
-
parser.column_options.parse("default 'foobar'").should == [{:default_clause=>[{:string => "'foobar'"}]}]
|
26
|
-
parser.column_options.parse('default max(foo)').should == [{:default_clause=>[{:function=>{:name=>"max", :arguments=>{:item=>"foo"}}}]}]
|
27
|
-
|
28
|
-
expect(
|
29
|
-
parser.column_options.parse('default 1')
|
30
|
-
).to eq([{:default_clause=>[{:integer=> '1'}]}])
|
31
|
-
end
|
32
|
-
|
33
|
-
it 'parses generated by' do
|
34
|
-
sql = 'generated by default as identity (start with 1 increment by 1 cache 20 )'
|
35
|
-
begin
|
36
|
-
result = parser.column_options.parse(sql.downcase)
|
37
|
-
rescue Parslet::ParseFailed => error
|
38
|
-
puts error.cause.ascii_tree
|
39
|
-
end
|
40
|
-
result.should == [{:identity=>{:start_value=>{:integer=> '1'},
|
41
|
-
:increment_value=>{:integer=> '1'},
|
42
|
-
:cache_value=>{:integer=> '20'}}}]
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'parses
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
parser.
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
it 'parses
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
sql = <<EOF
|
248
|
-
CREATE TABLE
|
249
|
-
(
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
{:column=>
|
306
|
-
{:field=> '
|
307
|
-
:data_type=>
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
:
|
312
|
-
|
313
|
-
{:column=>
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
:
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
:
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
1
|
+
require_relative '../../../../spec/spec_helper'
|
2
|
+
|
3
|
+
describe DDLParser::DDL::DB2::Parser do
|
4
|
+
let(:parser) { DDLParser::DDL::DB2::Parser.new }
|
5
|
+
|
6
|
+
context 'building blocks' do
|
7
|
+
|
8
|
+
it 'parses arglist' do
|
9
|
+
parser.arglist.parse('a').should == {:item=> 'a'}
|
10
|
+
parser.arglist.parse('a,b,c').should == [{:item=> 'a'}, {:item=> 'b'}, {:item=> 'c'}]
|
11
|
+
parser.arglist.parse('a, b, c').should == [{:item=> 'a'}, {:item=> 'b'}, {:item=> 'c'}]
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'column options parsing' do
|
17
|
+
it 'parses not null' do
|
18
|
+
expect(parser.column_options).to parse('not null')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'parses default values' do
|
22
|
+
parser.column_options.parse('default 1').should == [{:default_clause=>[{:integer=> '1'}]}]
|
23
|
+
parser.column_options.parse('with default 1').should == [{:default_clause=>[{:integer=> '1'}]}]
|
24
|
+
parser.column_options.parse('default current timestamp').should == [{:default_clause=>[{:timestamp => "current timestamp"}]}]
|
25
|
+
parser.column_options.parse("default 'foobar'").should == [{:default_clause=>[{:string => "'foobar'"}]}]
|
26
|
+
parser.column_options.parse('default max(foo)').should == [{:default_clause=>[{:function=>{:name=>"max", :arguments=>{:item=>"foo"}}}]}]
|
27
|
+
|
28
|
+
expect(
|
29
|
+
parser.column_options.parse('default 1')
|
30
|
+
).to eq([{:default_clause=>[{:integer=> '1'}]}])
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'parses generated by' do
|
34
|
+
sql = 'generated by default as identity (start with 1 increment by 1 cache 20 )'
|
35
|
+
begin
|
36
|
+
result = parser.column_options.parse(sql.downcase)
|
37
|
+
rescue Parslet::ParseFailed => error
|
38
|
+
puts error.cause.ascii_tree
|
39
|
+
end
|
40
|
+
result.should == [{:identity=>{:start_value=>{:integer=> '1'},
|
41
|
+
:increment_value=>{:integer=> '1'},
|
42
|
+
:cache_value=>{:integer=> '20'}}}]
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'parses generated by' do
|
46
|
+
sql = 'generated by default as identity (start with 1, increment by 1, cache 20 )'
|
47
|
+
begin
|
48
|
+
result = parser.column_options.parse(sql.downcase)
|
49
|
+
rescue Parslet::ParseFailed => error
|
50
|
+
puts error.cause.ascii_tree
|
51
|
+
end
|
52
|
+
result.should == [{:identity=>{:start_value=>{:integer=> '1'},
|
53
|
+
:increment_value=>{:integer=> '1'},
|
54
|
+
:cache_value=>{:integer=> '20'}}}]
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'parses identity' do
|
58
|
+
expect(parser.column_options).to parse('as identity (start with 500, increment by 1)')
|
59
|
+
expect(
|
60
|
+
parser.column_options.parse('as identity (start with 500, increment by 1)')
|
61
|
+
).to eq([{:identity=>{:start_value=>{:integer=> '500'}, :increment_value=>{:integer=> '1'}}}])
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'parses multible' do
|
65
|
+
expect(parser.column_options).to parse('not null as identity (start with 500, increment by 1)')
|
66
|
+
|
67
|
+
result = parser.column_options.parse('not null as identity (start with 500, increment by 1)')
|
68
|
+
result.first.should include(:column_option)
|
69
|
+
result.last.should include(:identity)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'constraint' do
|
75
|
+
it 'parses primary key' do
|
76
|
+
sql = 'primary key (id)'
|
77
|
+
parser.primary_key.parse(sql).should == {:primary_key=>{:item=> 'id'}}
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'parses composed primary key' do
|
81
|
+
sql = 'primary key (id,foo)'
|
82
|
+
parser.primary_key.parse(sql).should == {:primary_key=>[{:item=> 'id'}, {:item=> 'foo'}]}
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'parses unique' do
|
86
|
+
sql = 'constraint emp_act_uniq unique (empno,projno,actno)'
|
87
|
+
|
88
|
+
parser.constraint.parse(sql).should == {:constraint=>{:column_name=> 'emp_act_uniq',
|
89
|
+
:constraint_type=> 'unique',
|
90
|
+
:constraint_arglist=>[{:item=> 'empno'},
|
91
|
+
{:item=> 'projno'},
|
92
|
+
{:item=> 'actno'}]}}
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'parses foreign key' do
|
96
|
+
sql = 'constraint fk_act_proj foreign key (projno) references project (projno) on delete cascade'
|
97
|
+
begin
|
98
|
+
result = parser.constraint.parse(sql)
|
99
|
+
rescue Parslet::ParseFailed => error
|
100
|
+
puts error.cause.ascii_tree
|
101
|
+
end
|
102
|
+
result.should == {:constraint=>{:column_name=> 'fk_act_proj',
|
103
|
+
:constraint_type=> 'foreign key',
|
104
|
+
:constraint_arglist=>{:item=> 'projno'},
|
105
|
+
:reference_arglist=>{:item=> 'projno'}}}
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'column definition' do
|
111
|
+
it 'parses char not null' do
|
112
|
+
sql = 'deptno char(3) not null'
|
113
|
+
parser.column_definition.parse(sql).should == {:column => {
|
114
|
+
:field=> 'deptno',
|
115
|
+
:data_type=>{:char=>{:length=>{:integer=> '3'}}},
|
116
|
+
:options=>[{:column_option=> 'not null'}]
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
end
|
121
|
+
it 'parses char not null - x' do
|
122
|
+
sql = 'BUDGET_AMOUNT_IN_CO DECIMAL(15,2) NOT NULL DEFAULT 0'
|
123
|
+
parser.column_definition.parse(sql.downcase).should == {:column => {
|
124
|
+
:field=> 'budget_amount_in_co',
|
125
|
+
:data_type=>{:decimal=>{:precision=>
|
126
|
+
{:total=>{:integer=> '15'},
|
127
|
+
:scale=>{:integer=> '2'}}}},
|
128
|
+
:options=>[{:column_option=> 'not null'}, {:default_clause=>[{:integer=> '0'}]}]
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'element list' do
|
137
|
+
it 'parses one element' do
|
138
|
+
sql = '(deptno char(3) not null)'
|
139
|
+
parser.element_list.parse(sql).should == {:elements => {:column=>{:field=> 'deptno',
|
140
|
+
:data_type=>{:char=>{:length=>{:integer=> '3'}}},
|
141
|
+
:options=>[{:column_option=> 'not null'}]}}}
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'parses two element' do
|
145
|
+
sql = '(field1 char(1) not null, field2 char(2))'
|
146
|
+
parser.element_list.parse(sql).should == {:elements => [{:column=>{:field=> 'field1',
|
147
|
+
:data_type=>{:char=>{:length=>{:integer=> '1'}}},
|
148
|
+
:options=>[{:column_option=> 'not null'}]}},
|
149
|
+
{:column=>{:field=> 'field2',
|
150
|
+
:data_type=>{:char=>{:length=>{:integer=> '2'}}},
|
151
|
+
:options=> ''}}]}
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'parses with new lines' do
|
155
|
+
sql = <<EOF
|
156
|
+
(
|
157
|
+
DEPTNO CHAR(3) NOT NULL,
|
158
|
+
DEPTNAME VARCHAR(36) NOT NULL
|
159
|
+
)
|
160
|
+
EOF
|
161
|
+
parser.element_list.parse(sql.downcase).should == {:elements => [{:column=>{:field=> 'deptno',
|
162
|
+
:data_type=>{:char=>{:length=>{:integer=> '3'}}},
|
163
|
+
:options=>[{:column_option=> 'not null'}]}},
|
164
|
+
{:column=>{:field=> 'deptname',
|
165
|
+
:data_type=>{:varchar=>{:length=>{:integer=> '36'}}},
|
166
|
+
:options=>[{:column_option=> 'not null'}]}}]}
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'create table' do
|
172
|
+
it 'parses simple create' do
|
173
|
+
expect(parser.create_table_statement).to parse('create table foobar')
|
174
|
+
expect(parser.create_table_statement).not_to parse('create table ')
|
175
|
+
|
176
|
+
parser.create_table_statement.parse('create table foobar').should == {:operation=> 'create table', :table_name => 'foobar'}
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
context 'simple statements' do
|
183
|
+
|
184
|
+
it 'parses Example 1' do
|
185
|
+
sql = <<EOF
|
186
|
+
CREATE TABLE TDEPT
|
187
|
+
(DEPTNO CHAR(3) NOT NULL,
|
188
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
189
|
+
MGRNO INT,
|
190
|
+
ADMRDEPT DECIMAL(3,1) NOT NULL)
|
191
|
+
IN DEPARTX
|
192
|
+
EOF
|
193
|
+
parser.create_table.parse(sql.downcase).should == {:operation=> 'create table',
|
194
|
+
:table_name=> 'tdept',
|
195
|
+
:elements => [
|
196
|
+
{:column=>{:field=> 'deptno',
|
197
|
+
:data_type=>{:char=>{:length=>{:integer=> '3'}}},
|
198
|
+
:options=>[{:column_option=> 'not null'}]}},
|
199
|
+
{:column=>{:field=> 'deptname',
|
200
|
+
:data_type=>{:varchar=>{:length=>{:integer=> '36'}}},
|
201
|
+
:options=>[{:column_option=> 'not null'}]}},
|
202
|
+
{:column=>{:field=> 'mgrno',
|
203
|
+
:data_type=> 'int',
|
204
|
+
:options=> ''}},
|
205
|
+
{:column=>{:field=> 'admrdept',
|
206
|
+
:data_type=>{:decimal=>{:precision=>{:total=>{:integer=> '3'}, :scale=>{:integer=> '1'}}}},
|
207
|
+
:options=>[{:column_option=> 'not null'}]}}
|
208
|
+
]}
|
209
|
+
end
|
210
|
+
|
211
|
+
it 'parses with primary key' do
|
212
|
+
sql = <<EOF
|
213
|
+
CREATE TABLE TEST
|
214
|
+
(ID INT,
|
215
|
+
PRIMARY KEY (ID))
|
216
|
+
EOF
|
217
|
+
parser.create_table.parse(sql.downcase).should == {:operation=> 'create table',
|
218
|
+
:table_name=> 'test',
|
219
|
+
:elements=>[
|
220
|
+
{:column => {:field=> 'id', :data_type=> 'int', :options=> ''}},
|
221
|
+
{:primary_key=>{:item=> 'id'}}
|
222
|
+
]
|
223
|
+
}
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
|
228
|
+
context 'full statements' do
|
229
|
+
|
230
|
+
it 'parses Example 2' do
|
231
|
+
sql = <<EOF
|
232
|
+
CREATE TABLE PROJ
|
233
|
+
(PROJNO CHAR(6) NOT NULL,
|
234
|
+
PROJNAME VARCHAR(24) NOT NULL,
|
235
|
+
DEPTNO CHAR(3) NOT NULL,
|
236
|
+
RESPEMP CHAR(6) NOT NULL,
|
237
|
+
PRSTAFF DECIMAL(5,2) ,
|
238
|
+
PRSTDATE DATE ,
|
239
|
+
PRENDATE DATE ,
|
240
|
+
MAJPROJ CHAR(6) NOT NULL)
|
241
|
+
IN SCHED
|
242
|
+
EOF
|
243
|
+
expect(parser).to parse(sql.downcase)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'parses Example 3' do
|
247
|
+
sql = <<EOF
|
248
|
+
CREATE TABLE EMPLOYEE_SALARY
|
249
|
+
(DEPTNO CHAR(3) NOT NULL,
|
250
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
251
|
+
EMPNO CHAR(6) NOT NULL,
|
252
|
+
SALARY DECIMAL(9,2) NOT NULL WITH DEFAULT)
|
253
|
+
EOF
|
254
|
+
expect(parser).to parse(sql.downcase)
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'parses Example 6' do
|
258
|
+
pending 'we do not support CHECK statements'
|
259
|
+
sql = <<EOF
|
260
|
+
CREATE TABLE EMPLOYEE
|
261
|
+
(ID SMALLINT NOT NULL,
|
262
|
+
NAME VARCHAR(9),
|
263
|
+
DEPT SMALLINT CHECK (DEPT BETWEEN 10 AND 100),
|
264
|
+
JOB CHAR(5) CHECK (JOB IN ('Sales','Mgr','Clerk')),
|
265
|
+
HIREDATE DATE,
|
266
|
+
SALARY DECIMAL(7,2),
|
267
|
+
COMM DECIMAL(7,2),
|
268
|
+
PRIMARY KEY (ID),
|
269
|
+
CONSTRAINT YEARSAL CHECK (YEAR(HIREDATE) > 1986
|
270
|
+
OR SALARY > 40500)
|
271
|
+
)
|
272
|
+
IN HUMRES
|
273
|
+
EOF
|
274
|
+
begin
|
275
|
+
result = parser.parse(sql.downcase)
|
276
|
+
# rescue Parslet::ParseFailed => error
|
277
|
+
# puts error.cause.ascii_tree
|
278
|
+
end
|
279
|
+
result.should == [{:operation=> 'create table', :table_name=> 'emp_act'}]
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'parses Example 11' do
|
283
|
+
sql = <<EOF
|
284
|
+
CREATE TABLE EMP_ACT
|
285
|
+
(EMPNO CHAR(6) NOT NULL,
|
286
|
+
PROJNO CHAR(6) NOT NULL,
|
287
|
+
ACTNO SMALLINT NOT NULL,
|
288
|
+
EMPTIME DECIMAL(5,2),
|
289
|
+
EMSTDATE DATE,
|
290
|
+
EMENDATE DATE,
|
291
|
+
CONSTRAINT EMP_ACT_UNIQ UNIQUE (EMPNO,PROJNO,ACTNO),
|
292
|
+
CONSTRAINT FK_ACT_PROJ FOREIGN KEY (PROJNO)
|
293
|
+
REFERENCES PROJECT (PROJNO) ON DELETE CASCADE
|
294
|
+
)
|
295
|
+
IN SCHED
|
296
|
+
EOF
|
297
|
+
begin
|
298
|
+
result = parser.parse(sql.downcase)
|
299
|
+
rescue Parslet::ParseFailed => error
|
300
|
+
puts error.cause.ascii_tree
|
301
|
+
end
|
302
|
+
result.should == {:operation=> 'create table',
|
303
|
+
:table_name=> 'emp_act',
|
304
|
+
:elements => [
|
305
|
+
{:column=>
|
306
|
+
{:field=> 'empno',
|
307
|
+
:data_type=>{:char=>{:length=>{:integer=> '6'}}},
|
308
|
+
:options=>[{:column_option=> 'not null'}]}},
|
309
|
+
{:column=>
|
310
|
+
{:field=> 'projno',
|
311
|
+
:data_type=>{:char=>{:length=>{:integer=> '6'}}},
|
312
|
+
:options=>[{:column_option=> 'not null'}]}},
|
313
|
+
{:column=>
|
314
|
+
{:field=> 'actno',
|
315
|
+
:data_type=> 'smallint',
|
316
|
+
:options=>[{:column_option=> 'not null'}]}},
|
317
|
+
{:column=>
|
318
|
+
{:field=> 'emptime',
|
319
|
+
:data_type=>
|
320
|
+
{:decimal=>
|
321
|
+
{:precision=>
|
322
|
+
{:total=>{:integer=> '5'}, :scale=>{:integer=> '2'}}}},
|
323
|
+
:options=> ''}},
|
324
|
+
{:column=>{:field=> 'emstdate', :data_type=> 'date', :options=> ''}},
|
325
|
+
{:column=>{:field=> 'emendate', :data_type=> 'date', :options=> ''}},
|
326
|
+
{:constraint=>
|
327
|
+
{:column_name=> 'emp_act_uniq',
|
328
|
+
:constraint_type=> 'unique',
|
329
|
+
:constraint_arglist=>
|
330
|
+
[{:item=> 'empno'}, {:item=> 'projno'}, {:item=> 'actno'}]}},
|
331
|
+
{:constraint=>
|
332
|
+
{:column_name=> 'fk_act_proj',
|
333
|
+
:constraint_type=> 'foreign key',
|
334
|
+
:constraint_arglist=>{:item=> 'projno'},
|
335
|
+
:reference_arglist=>{:item=> 'projno'}}}
|
336
|
+
]}
|
337
|
+
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'parses Example 12' do
|
341
|
+
sql = <<EOF
|
342
|
+
CREATE TABLE HOCKEY_GOALS
|
343
|
+
( BY_PLAYER VARCHAR(30) NOT NULL,
|
344
|
+
BY_TEAM VARCHAR(30) NOT NULL,
|
345
|
+
AGAINST_PLAYER VARCHAR(30) NOT NULL,
|
346
|
+
AGAINST_TEAM VARCHAR(30) NOT NULL,
|
347
|
+
DATE_OF_GOAL DATE NOT NULL,
|
348
|
+
DESCRIPTION CLOB(5000))
|
349
|
+
EOF
|
350
|
+
begin
|
351
|
+
result = parser.parse(sql.downcase)
|
352
|
+
rescue Parslet::ParseFailed => error
|
353
|
+
puts error.cause.ascii_tree
|
354
|
+
end
|
355
|
+
result.should == {:operation=> 'create table', :table_name=> 'hockey_goals',
|
356
|
+
:elements => [
|
357
|
+
{:column=>{:field=> 'by_player', :data_type=>{:varchar=>{:length=>{:integer=> '30'}}}, :options=>[{:column_option=> 'not null'}]}},
|
358
|
+
{:column=>{:field=> 'by_team', :data_type=>{:varchar=>{:length=>{:integer=> '30'}}}, :options=>[{:column_option=> 'not null'}]}},
|
359
|
+
{:column=>{:field=> 'against_player', :data_type=>{:varchar=>{:length=>{:integer=> '30'}}}, :options=>[{:column_option=> 'not null'}]}},
|
360
|
+
{:column=>{:field=> 'against_team', :data_type=>{:varchar=>{:length=>{:integer=> '30'}}}, :options=>[{:column_option=> 'not null'}]}},
|
361
|
+
{:column=>{:field=> 'date_of_goal', :data_type=> 'date', :options=>[{:column_option=> 'not null'}]}},
|
362
|
+
{:column=>{:field=> 'description', :data_type=>{:clob=>{:length=>{:integer=> '5000'}}}, :options=> ''}}]}
|
363
|
+
end
|
364
|
+
|
365
|
+
it 'parses Example 16' do
|
366
|
+
sql = <<EOF
|
367
|
+
CREATE TABLE DEPT
|
368
|
+
(DEPTNO SMALLINT NOT NULL
|
369
|
+
GENERATED ALWAYS AS IDENTITY
|
370
|
+
(START WITH 500, INCREMENT BY 1),
|
371
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
372
|
+
MGRNO CHAR(6),
|
373
|
+
ADMRDEPT SMALLINT NOT NULL,
|
374
|
+
LOCATION CHAR(30))
|
375
|
+
EOF
|
376
|
+
|
377
|
+
begin
|
378
|
+
result = parser.parse(sql.downcase)
|
379
|
+
rescue Parslet::ParseFailed => error
|
380
|
+
puts error.cause.ascii_tree
|
381
|
+
end
|
382
|
+
|
383
|
+
result.should == {:operation=> 'create table',
|
384
|
+
:table_name=> 'dept',
|
385
|
+
:elements => [
|
386
|
+
{:column=>{:field=> 'deptno',
|
387
|
+
:data_type=> 'smallint',
|
388
|
+
:options=>[{:column_option=> 'not null'},
|
389
|
+
{:identity=>{:start_value=>{:integer=> '500'}, :increment_value=>{:integer=> '1'}}}]}},
|
390
|
+
{:column=>{:field=> 'deptname',
|
391
|
+
:data_type=>{:varchar=>{:length=>{:integer=> '36'}}},
|
392
|
+
:options=>[{:column_option=> 'not null'}]}},
|
393
|
+
{:column=>{:field=> 'mgrno',
|
394
|
+
:data_type=>{:char=>{:length=>{:integer=> '6'}}},
|
395
|
+
:options=> ''}},
|
396
|
+
{:column=>{:field=> 'admrdept',
|
397
|
+
:data_type=> 'smallint',
|
398
|
+
:options=>[{:column_option=> 'not null'}]}},
|
399
|
+
{:column=>{:field=> 'location',
|
400
|
+
:data_type=>{:char=>{:length=>{:integer=> '30'}}},
|
401
|
+
:options=> ''}}]}
|
402
|
+
end
|
403
|
+
end
|
404
|
+
|
405
|
+
context 'real dsv examples 2' do
|
406
|
+
it 'parses Example 16a' do
|
407
|
+
sql = <<EOF
|
408
|
+
CREATE TABLE COSTINVOICE
|
409
|
+
(DOC_NO CHARACTER(8) NOT NULL,
|
410
|
+
STATUS CHARACTER(12))
|
411
|
+
EOF
|
412
|
+
|
413
|
+
begin
|
414
|
+
result = parser.parse(sql.downcase)
|
415
|
+
rescue Parslet::ParseFailed => error
|
416
|
+
puts error.cause.ascii_tree
|
417
|
+
end
|
418
|
+
|
419
|
+
result.should == {:operation=> 'create table',
|
420
|
+
:table_name=> 'costinvoice',
|
421
|
+
:elements => [
|
422
|
+
{:column=>{:field=> 'doc_no',
|
423
|
+
:data_type=>{:char=>{:length=>{:integer=> '8'}}},
|
424
|
+
:options=>[{:column_option=> 'not null'}]}},
|
425
|
+
{:column=>{:field=> 'status',
|
426
|
+
:data_type=>{:char=>{:length=>{:integer=> '12'}}},
|
427
|
+
:options=> ''}}]}
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'real dsv examples' do
|
432
|
+
it 'parses Example 16' do
|
433
|
+
|
434
|
+
sql = <<EOF
|
435
|
+
Create table USER (USER_RW CHAR(4) NOT NULL,
|
436
|
+
USER_NAME CHAR(20) NOT NULL,
|
437
|
+
SECURITY_REPORT CHAR(2) NOT NULL,
|
438
|
+
SECURITY_AUTH CHAR(2) NOT NULL,
|
439
|
+
SECURITY_CORRECT CHAR(2) NOT NULL,
|
440
|
+
SECURITY_REVIEW CHAR(2) NOT NULL,
|
441
|
+
SECURITY_CHIEF CHAR(2) NOT NULL,
|
442
|
+
PASSWORD CHAR(6) NOT NULL,
|
443
|
+
SORT_SEQUENTIAL CHAR(4) NOT NULL,
|
444
|
+
CREATE_TS TIMESTAMP NOT NULL With Default CURRENT TIMESTAMP,
|
445
|
+
UPDATE_TS TIMESTAMP NOT NULL With Default CURRENT TIMESTAMP,
|
446
|
+
UNIQUE_NO INTEGER NOT NULL
|
447
|
+
Generated By Default as Identity (Start with 1 Increment by 1 cache 20))
|
448
|
+
in CPH_TS001
|
449
|
+
EOF
|
450
|
+
|
451
|
+
begin
|
452
|
+
result = parser.parse(sql.downcase)
|
453
|
+
rescue Parslet::ParseFailed => error
|
454
|
+
puts error.cause.ascii_tree
|
455
|
+
end
|
456
|
+
|
457
|
+
result[:operation].should == 'create table'
|
458
|
+
result[:table_name].should == 'user'
|
459
|
+
end
|
460
|
+
it 'parses Example 17' do
|
461
|
+
|
462
|
+
sql = <<EOF
|
463
|
+
CREATE TABLE COST_INVOICE
|
464
|
+
(DOC_NO CHARACTER(8) NOT NULL,
|
465
|
+
STATUS CHARACTER(12) NOT NULL,
|
466
|
+
DISPUTE CHARACTER(8),
|
467
|
+
SAP_STATUS CHARACTER(1),
|
468
|
+
DEPT CHARACTER(5) NOT NULL,
|
469
|
+
FROM_DEPT CHARACTER(5) NOT NULL,
|
470
|
+
CUSTOMER_NO DECIMAL(12) NOT NULL,
|
471
|
+
SENDER_DOC_NO CHARACTER(8) NOT NULL,
|
472
|
+
INVOICE_DATE DATE NOT NULL,
|
473
|
+
DUE_DATE DATE NOT NULL,
|
474
|
+
LASTUSER CHARACTER(4) NOT NULL,
|
475
|
+
CREATE_TS TIMESTAMP NOT NULL,
|
476
|
+
UPDATE_TS TIMESTAMP NOT NULL,
|
477
|
+
UPDATE_TS_REAL_TIME TIMESTAMP NOT NULL,
|
478
|
+
UNIQUE_NO INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1 INCREMENT BY 1 CACHE 20))
|
479
|
+
IN CPH_TS001
|
480
|
+
EOF
|
481
|
+
|
482
|
+
begin
|
483
|
+
result = parser.parse(sql.downcase)
|
484
|
+
rescue Parslet::ParseFailed => error
|
485
|
+
puts error.cause.ascii_tree
|
486
|
+
end
|
487
|
+
|
488
|
+
result[:operation].should == 'create table'
|
489
|
+
result[:table_name].should == 'cost_invoice'
|
490
|
+
end
|
491
|
+
end
|
492
|
+
context 'real dsv examples 3' do
|
493
|
+
it 'parses Example 18' do
|
494
|
+
sql = <<EOF
|
495
|
+
CREATE TABLE COSTINVOICE
|
496
|
+
(DOC_NO CHARACTER(8) NOT NULL DEFAULT 'TEST DEFAULT',
|
497
|
+
STATUS CHARACTER(12))
|
498
|
+
|
499
|
+
EOF
|
500
|
+
|
501
|
+
begin
|
502
|
+
result = parser.parse(sql.downcase)
|
503
|
+
rescue Parslet::ParseFailed => error
|
504
|
+
puts error.cause.ascii_tree
|
505
|
+
end
|
506
|
+
|
507
|
+
result.should == {:operation=>"create table",
|
508
|
+
:table_name=>"costinvoice",
|
509
|
+
:elements=>[{:column=>{:field=>"doc_no",
|
510
|
+
:data_type=>{:char=>{:length=>{:integer=>"8"}}},
|
511
|
+
:options=>[{:column_option=>"not null"},
|
512
|
+
{:default_clause=>[{:string=>"'test default'"}]}]}},
|
513
|
+
{:column=>{:field=>"status",
|
514
|
+
:data_type=>{:char=>{:length=>{:integer=>"12"}}}, :options=>""}}]}
|
515
|
+
end
|
516
|
+
|
517
|
+
end
|
518
|
+
end
|