ddl_parser 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/ddl_parser.gemspec +26 -0
- data/lib/ddl_parser/ddl/db2/parser.rb +112 -0
- data/lib/ddl_parser/ddl/db2.rb +4 -0
- data/lib/ddl_parser/ddl.rb +4 -0
- data/lib/ddl_parser/parser.rb +48 -0
- data/lib/ddl_parser/shared_rules/constants.rb +50 -0
- data/lib/ddl_parser/shared_rules/data_types.rb +33 -0
- data/lib/ddl_parser/shared_rules/logical_operators.rb +17 -0
- data/lib/ddl_parser/shared_rules.rb +6 -0
- data/lib/ddl_parser/sql/db2/select_parser.rb +67 -0
- data/lib/ddl_parser/sql/db2.rb +4 -0
- data/lib/ddl_parser/sql.rb +4 -0
- data/lib/ddl_parser/translater/alter_table.rb +20 -0
- data/lib/ddl_parser/translater/create_index.rb +24 -0
- data/lib/ddl_parser/translater/create_table.rb +27 -0
- data/lib/ddl_parser/translater.rb +6 -0
- data/lib/ddl_parser/version.rb +3 -0
- data/lib/ddl_parser.rb +16 -0
- data/lib/parslet_extentions.rb +17 -0
- data/spec/ddl_parser/ddl/db2/alter_table_spec.rb +156 -0
- data/spec/ddl_parser/ddl/db2/create_index_spec.rb +26 -0
- data/spec/ddl_parser/ddl/db2/create_table_spec.rb +427 -0
- data/spec/ddl_parser/parser_spec.rb +96 -0
- data/spec/ddl_parser/shared_rules/constants_spec.rb +126 -0
- data/spec/ddl_parser/shared_rules/data_types_spec.rb +27 -0
- data/spec/ddl_parser/sql/db2/select_parser_spec.rb +166 -0
- data/spec/spec_helper.rb +23 -0
- metadata +142 -0
@@ -0,0 +1,156 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe 'Alter table parsing' do
|
4
|
+
let(:parser) { DDLParser::DDL::DB2::Parser.new }
|
5
|
+
context "alter table" do
|
6
|
+
it "parses alter_table add column" do
|
7
|
+
sql = <<EOF
|
8
|
+
ALTER TABLE BUDGET
|
9
|
+
ADD COLUMN BUDGET_AMOUNT_IN_CO DECIMAL(15,2) NOT NULL DEFAULT 0
|
10
|
+
ADD COLUMN BUDGET_AMOUNT_CURR CHARACTER(4)
|
11
|
+
EOF
|
12
|
+
begin
|
13
|
+
result = parser.parse(sql.downcase)
|
14
|
+
rescue Parslet::ParseFailed => error
|
15
|
+
puts error.cause.ascii_tree
|
16
|
+
end
|
17
|
+
|
18
|
+
#puts result.inspect
|
19
|
+
result.count.should == 3
|
20
|
+
result.should include(:operation, :table_name)
|
21
|
+
result.should include(:operation => "alter table")
|
22
|
+
result[:elements].first[:add][:column].should include(:field, :data_type)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "parses alter_table foreign key constraint without on" do
|
26
|
+
sql = <<EOF
|
27
|
+
ALTER TABLE REPLAN_ADDR
|
28
|
+
ADD CONSTRAINT REPLAN_ADDR_FK
|
29
|
+
FOREIGN KEY
|
30
|
+
(CONSIGNMENT,
|
31
|
+
EVENT)
|
32
|
+
REFERENCES REPLAN_MAIN
|
33
|
+
(CONSIGNMENT,
|
34
|
+
EVENT)
|
35
|
+
EOF
|
36
|
+
begin
|
37
|
+
result = parser.parse(sql.downcase)
|
38
|
+
rescue Parslet::ParseFailed => error
|
39
|
+
puts error.cause.ascii_tree
|
40
|
+
end
|
41
|
+
|
42
|
+
#puts result.inspect #.count.should == 3
|
43
|
+
result.should include({:operation => "alter table" , :table_name=>"replan_addr"})
|
44
|
+
result[:elements].first[:add_constraint].should include({:constraint_name=>"replan_addr_fk"})
|
45
|
+
end
|
46
|
+
|
47
|
+
it "parses foreign key clause" do
|
48
|
+
sql = <<EOF
|
49
|
+
FOREIGN KEY
|
50
|
+
(CONSIGNMENT,
|
51
|
+
EVENT)
|
52
|
+
REFERENCES REPLAN_MAIN
|
53
|
+
(CONSIGNMENT,
|
54
|
+
EVENT)
|
55
|
+
ON DELETE RESTRICT
|
56
|
+
ON UPDATE NO ACTION
|
57
|
+
EOF
|
58
|
+
begin
|
59
|
+
result = parser.foreign_key_clause.parse(sql.downcase)
|
60
|
+
rescue Parslet::ParseFailed => error
|
61
|
+
puts error.cause.ascii_tree
|
62
|
+
end
|
63
|
+
|
64
|
+
#puts result.inspect
|
65
|
+
result.count.should == 2
|
66
|
+
result.should include(:reference_clause)
|
67
|
+
result[:member_fields][0][:field].should == "consignment"
|
68
|
+
result[:member_fields][1][:field].should == "event"
|
69
|
+
result[:reference_clause][:reference_arglist][0][:item].should == "consignment"
|
70
|
+
result[:reference_clause][:reference_arglist][1][:item].should == "event"
|
71
|
+
end
|
72
|
+
it "parses reference_clause" do
|
73
|
+
sql = <<EOF
|
74
|
+
REFERENCES REPLAN_MAIN
|
75
|
+
(CONSIGNMENT,
|
76
|
+
EVENT)
|
77
|
+
|
78
|
+
EOF
|
79
|
+
begin
|
80
|
+
result = parser.reference_clause.parse(sql.downcase)
|
81
|
+
rescue Parslet::ParseFailed => error
|
82
|
+
puts error.cause.ascii_tree
|
83
|
+
end
|
84
|
+
|
85
|
+
#puts result.inspect
|
86
|
+
result.should include(:reference_arglist)
|
87
|
+
result[:reference_arglist][0][:item].should == "consignment"
|
88
|
+
result[:reference_arglist][1][:item].should == "event"
|
89
|
+
end
|
90
|
+
it "parses on_delete_clause" do
|
91
|
+
sql = <<EOF
|
92
|
+
ON DELETE RESTRICT
|
93
|
+
EOF
|
94
|
+
begin
|
95
|
+
result = parser.on_delete_clause.parse(sql.downcase)
|
96
|
+
rescue Parslet::ParseFailed => error
|
97
|
+
puts error.cause.ascii_tree
|
98
|
+
end
|
99
|
+
|
100
|
+
#puts result.inspect
|
101
|
+
result.should include(:on_delete_option => 'restrict')
|
102
|
+
end
|
103
|
+
|
104
|
+
it "parses on_update_clause" do
|
105
|
+
sql = <<EOF
|
106
|
+
ON UPDATE NO ACTION
|
107
|
+
EOF
|
108
|
+
begin
|
109
|
+
result = parser.on_update_clause.parse(sql.downcase)
|
110
|
+
rescue Parslet::ParseFailed => error
|
111
|
+
puts error.cause.ascii_tree
|
112
|
+
end
|
113
|
+
|
114
|
+
#puts result.inspect
|
115
|
+
result.should include(:on_update_option => 'no action')
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
it "parses complete alter_table" do
|
120
|
+
sql = <<EOF
|
121
|
+
ALTER TABLE REPLAN_ADDR
|
122
|
+
ADD CONSTRAINT REPLAN_ADDR_FK
|
123
|
+
FOREIGN KEY
|
124
|
+
(CONSIGNMENT,
|
125
|
+
EVENT)
|
126
|
+
REFERENCES REPLAN_MAIN
|
127
|
+
(CONSIGNMENT,
|
128
|
+
EVENT)
|
129
|
+
ON DELETE RESTRICT
|
130
|
+
ON UPDATE RESTRICT
|
131
|
+
EOF
|
132
|
+
begin
|
133
|
+
result = parser.parse(sql.downcase)
|
134
|
+
rescue Parslet::ParseFailed => error
|
135
|
+
puts error.cause.ascii_tree
|
136
|
+
end
|
137
|
+
|
138
|
+
#puts result.inspect
|
139
|
+
result.should include(:operation, :table_name)
|
140
|
+
result.should include(:operation => "alter table")
|
141
|
+
result.should include(:table_name => "replan_addr")
|
142
|
+
result[:elements].first.should include(:add_constraint)
|
143
|
+
result[:elements].first[:add_constraint].should include(:constraint_name => 'replan_addr_fk')
|
144
|
+
result[:elements].first[:add_constraint].should include(:foreign_key_clause)
|
145
|
+
result[:elements].first[:add_constraint][:foreign_key_clause].should include(:member_fields)
|
146
|
+
result[:elements].first[:add_constraint][:foreign_key_clause][:member_fields][0].should include(:field=>'consignment')
|
147
|
+
result[:elements].first[:add_constraint][:foreign_key_clause][:member_fields][1].should include(:field=>'event')
|
148
|
+
result[:elements].first[:add_constraint][:foreign_key_clause].should include(:reference_clause)
|
149
|
+
result[:elements].first[:add_constraint][:foreign_key_clause][:reference_clause].should include(:reference_arglist)
|
150
|
+
result[:elements].first[:add_constraint][:foreign_key_clause][:reference_clause][:reference_arglist][0].should include(:item=>'consignment')
|
151
|
+
result[:elements].first[:add_constraint][:foreign_key_clause][:reference_clause][:reference_arglist][1].should include(:item=>'event')
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe 'Create index parsing' do
|
4
|
+
let(:parser) { DDLParser::DDL::DB2::Parser.new }
|
5
|
+
it "parses create_unique_index" do
|
6
|
+
sql = <<EOF
|
7
|
+
CREATE UNIQUE INDEX REPLAN_ADDR_1 ON REPLAN_ADDR
|
8
|
+
(CONSIGNMENT ASCENDING, COLLI DESCENDING )
|
9
|
+
EOF
|
10
|
+
begin
|
11
|
+
result = parser.parse(sql.downcase)
|
12
|
+
rescue Parslet::ParseFailed => error
|
13
|
+
puts error.cause.ascii_tree
|
14
|
+
end
|
15
|
+
|
16
|
+
result.count.should == 3
|
17
|
+
result[0].should include(:operation, :object_property, :object_type, :index_name)
|
18
|
+
result[0].should include(:operation => "create")
|
19
|
+
result[0].should include(:object_property => "unique")
|
20
|
+
result[0].should include(:object_type => "index")
|
21
|
+
result[1].should include(:field)
|
22
|
+
result[1].should include(:sort_id)
|
23
|
+
result[2].should include(:field)
|
24
|
+
result[2].should include(:sort_id)
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,427 @@
|
|
1
|
+
require "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
|
+
expect(parser.column_options).to parse("default 1")
|
23
|
+
expect(parser.column_options).to parse("with default 1")
|
24
|
+
expect(parser.column_options).to parse("default current timestamp")
|
25
|
+
expect(parser.column_options).to parse("default 'foobar'")
|
26
|
+
expect(parser.column_options).to parse("default max(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 identity" do
|
46
|
+
expect(parser.column_options).to parse("as identity (start with 500, increment by 1)")
|
47
|
+
expect(
|
48
|
+
parser.column_options.parse("as identity (start with 500, increment by 1)")
|
49
|
+
).to eq([{:identity=>{:start_value=>{:integer=>"500"}, :increment_value=>{:integer=>"1"}}}])
|
50
|
+
end
|
51
|
+
|
52
|
+
it "parses multible" do
|
53
|
+
expect(parser.column_options).to parse("not null as identity (start with 500, increment by 1)")
|
54
|
+
|
55
|
+
result = parser.column_options.parse("not null as identity (start with 500, increment by 1)")
|
56
|
+
result.first.should include(:column_option)
|
57
|
+
result.last.should include(:identity)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
context "constraint" do
|
63
|
+
it "parses primary key" do
|
64
|
+
sql = "primary key (id)"
|
65
|
+
parser.primary_key.parse(sql).should == {:primary_key=>{:item=>"id"}}
|
66
|
+
end
|
67
|
+
|
68
|
+
it "parses composed primary key" do
|
69
|
+
sql = "primary key (id,foo)"
|
70
|
+
parser.primary_key.parse(sql).should == {:primary_key=>[{:item=>"id"}, {:item=>"foo"}]}
|
71
|
+
end
|
72
|
+
|
73
|
+
it "parses unique" do
|
74
|
+
sql = "constraint emp_act_uniq unique (empno,projno,actno)"
|
75
|
+
|
76
|
+
parser.constraint.parse(sql).should == {:constraint=>{:column_name=>"emp_act_uniq",
|
77
|
+
:constraint_type=>"unique",
|
78
|
+
:constraint_arglist=>[{:item=>"empno"},
|
79
|
+
{:item=>"projno"},
|
80
|
+
{:item=>"actno"}]}}
|
81
|
+
end
|
82
|
+
|
83
|
+
it "parses foreign key" do
|
84
|
+
sql = "constraint fk_act_proj foreign key (projno) references project (projno) on delete cascade"
|
85
|
+
begin
|
86
|
+
result = parser.constraint.parse(sql)
|
87
|
+
rescue Parslet::ParseFailed => error
|
88
|
+
puts error.cause.ascii_tree
|
89
|
+
end
|
90
|
+
result.should == {:constraint=>{:column_name=>"fk_act_proj",
|
91
|
+
:constraint_type=>"foreign key",
|
92
|
+
:constraint_arglist=>{:item=>"projno"},
|
93
|
+
:reference_arglist=>{:item=>"projno"}}}
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
context "column definition" do
|
99
|
+
it "parses char not null" do
|
100
|
+
sql = "deptno char(3) not null"
|
101
|
+
parser.column_definition.parse(sql).should == {:column => {
|
102
|
+
:field=>"deptno",
|
103
|
+
:data_type=>{:char=>{:length=>{:integer=>"3"}}},
|
104
|
+
:options=>[{:column_option=>"not null"}]
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
end
|
109
|
+
it "parses char not null - x" do
|
110
|
+
sql = "BUDGET_AMOUNT_IN_CO DECIMAL(15,2) NOT NULL DEFAULT 0"
|
111
|
+
parser.column_definition.parse(sql.downcase).should == {:column => {
|
112
|
+
:field=>"budget_amount_in_co",
|
113
|
+
:data_type=>{:decimal=>{:precision=>
|
114
|
+
{:total=>{:integer=>"15"},
|
115
|
+
:scale=>{:integer=>"2"}}}},
|
116
|
+
:options=>[{:column_option=>"not null"}, {:default_clause=>[{:integer=>"0"}]}]
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
context "element list" do
|
125
|
+
it "parses one element" do
|
126
|
+
sql = "(deptno char(3) not null)"
|
127
|
+
parser.element_list.parse(sql).should == {:elements => {:column=>{:field=>"deptno",
|
128
|
+
:data_type=>{:char=>{:length=>{:integer=>"3"}}},
|
129
|
+
:options=>[{:column_option=>"not null"}]}}}
|
130
|
+
end
|
131
|
+
|
132
|
+
it "parses two element" do
|
133
|
+
sql = "(field1 char(1) not null, field2 char(2))"
|
134
|
+
parser.element_list.parse(sql).should == {:elements => [{:column=>{:field=>"field1",
|
135
|
+
:data_type=>{:char=>{:length=>{:integer=>"1"}}},
|
136
|
+
:options=>[{:column_option=>"not null"}]}},
|
137
|
+
{:column=>{:field=>"field2",
|
138
|
+
:data_type=>{:char=>{:length=>{:integer=>"2"}}},
|
139
|
+
:options=>""}}]}
|
140
|
+
end
|
141
|
+
|
142
|
+
it "parses with new lines" do
|
143
|
+
sql = <<EOF
|
144
|
+
(
|
145
|
+
DEPTNO CHAR(3) NOT NULL,
|
146
|
+
DEPTNAME VARCHAR(36) NOT NULL
|
147
|
+
)
|
148
|
+
EOF
|
149
|
+
parser.element_list.parse(sql.downcase).should == {:elements => [{:column=>{:field=>"deptno",
|
150
|
+
:data_type=>{:char=>{:length=>{:integer=>"3"}}},
|
151
|
+
:options=>[{:column_option=>"not null"}]}},
|
152
|
+
{:column=>{:field=>"deptname",
|
153
|
+
:data_type=>{:varchar=>{:length=>{:integer=>"36"}}},
|
154
|
+
:options=>[{:column_option=>"not null"}]}}]}
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "create table" do
|
160
|
+
it "parses simple create" do
|
161
|
+
expect(parser.create_table_statement).to parse("create table foobar")
|
162
|
+
expect(parser.create_table_statement).not_to parse("create table ")
|
163
|
+
|
164
|
+
parser.create_table_statement.parse("create table foobar").should == {:operation=>"create table", :table_name => "foobar"}
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
|
170
|
+
context "simple statements" do
|
171
|
+
|
172
|
+
it "parses Example 1"do
|
173
|
+
sql = <<EOF
|
174
|
+
CREATE TABLE TDEPT
|
175
|
+
(DEPTNO CHAR(3) NOT NULL,
|
176
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
177
|
+
MGRNO INT,
|
178
|
+
ADMRDEPT DECIMAL(3,1) NOT NULL)
|
179
|
+
IN DEPARTX
|
180
|
+
EOF
|
181
|
+
parser.create_table.parse(sql.downcase).should == {:operation=>"create table",
|
182
|
+
:table_name=>"tdept",
|
183
|
+
:elements => [
|
184
|
+
{:column=>{:field=>"deptno",
|
185
|
+
:data_type=>{:char=>{:length=>{:integer=>"3"}}},
|
186
|
+
:options=>[{:column_option=>"not null"}]}},
|
187
|
+
{:column=>{:field=>"deptname",
|
188
|
+
:data_type=>{:varchar=>{:length=>{:integer=>"36"}}},
|
189
|
+
:options=>[{:column_option=>"not null"}]}},
|
190
|
+
{:column=>{:field=>"mgrno",
|
191
|
+
:data_type=>"int",
|
192
|
+
:options=>""}},
|
193
|
+
{:column=>{:field=>"admrdept",
|
194
|
+
:data_type=>{:decimal=>{:precision=>{:total=>{:integer=>"3"}, :scale=>{:integer=>"1"}}}},
|
195
|
+
:options=>[{:column_option=>"not null"}]}}
|
196
|
+
]}
|
197
|
+
end
|
198
|
+
|
199
|
+
it "parses with primary key" do
|
200
|
+
sql = <<EOF
|
201
|
+
CREATE TABLE TEST
|
202
|
+
(ID INT,
|
203
|
+
PRIMARY KEY (ID))
|
204
|
+
EOF
|
205
|
+
parser.create_table.parse(sql.downcase).should == {:operation=>"create table",
|
206
|
+
:table_name=>"test",
|
207
|
+
:elements=>[
|
208
|
+
{:column => {:field=>"id", :data_type=>"int", :options=>""}},
|
209
|
+
{:primary_key=>{:item=>"id"}}
|
210
|
+
]
|
211
|
+
}
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
context "full statements" do
|
217
|
+
|
218
|
+
it "parses Example 2" do
|
219
|
+
sql = <<EOF
|
220
|
+
CREATE TABLE PROJ
|
221
|
+
(PROJNO CHAR(6) NOT NULL,
|
222
|
+
PROJNAME VARCHAR(24) NOT NULL,
|
223
|
+
DEPTNO CHAR(3) NOT NULL,
|
224
|
+
RESPEMP CHAR(6) NOT NULL,
|
225
|
+
PRSTAFF DECIMAL(5,2) ,
|
226
|
+
PRSTDATE DATE ,
|
227
|
+
PRENDATE DATE ,
|
228
|
+
MAJPROJ CHAR(6) NOT NULL)
|
229
|
+
IN SCHED
|
230
|
+
EOF
|
231
|
+
expect(parser).to parse(sql.downcase)
|
232
|
+
end
|
233
|
+
|
234
|
+
it "parses Example 3" do
|
235
|
+
sql = <<EOF
|
236
|
+
CREATE TABLE EMPLOYEE_SALARY
|
237
|
+
(DEPTNO CHAR(3) NOT NULL,
|
238
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
239
|
+
EMPNO CHAR(6) NOT NULL,
|
240
|
+
SALARY DECIMAL(9,2) NOT NULL WITH DEFAULT)
|
241
|
+
EOF
|
242
|
+
expect(parser).to parse(sql.downcase)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "parses Example 6" do
|
246
|
+
pending "we do not support CHECK statements"
|
247
|
+
sql = <<EOF
|
248
|
+
CREATE TABLE EMPLOYEE
|
249
|
+
(ID SMALLINT NOT NULL,
|
250
|
+
NAME VARCHAR(9),
|
251
|
+
DEPT SMALLINT CHECK (DEPT BETWEEN 10 AND 100),
|
252
|
+
JOB CHAR(5) CHECK (JOB IN ('Sales','Mgr','Clerk')),
|
253
|
+
HIREDATE DATE,
|
254
|
+
SALARY DECIMAL(7,2),
|
255
|
+
COMM DECIMAL(7,2),
|
256
|
+
PRIMARY KEY (ID),
|
257
|
+
CONSTRAINT YEARSAL CHECK (YEAR(HIREDATE) > 1986
|
258
|
+
OR SALARY > 40500)
|
259
|
+
)
|
260
|
+
IN HUMRES
|
261
|
+
EOF
|
262
|
+
begin
|
263
|
+
result = parser.parse(sql.downcase)
|
264
|
+
rescue Parslet::ParseFailed => error
|
265
|
+
puts error.cause.ascii_tree
|
266
|
+
end
|
267
|
+
result.should == [{:operation=>"create table", :table_name=>"emp_act"}]
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
it "parses Example 11" do
|
272
|
+
sql = <<EOF
|
273
|
+
CREATE TABLE EMP_ACT
|
274
|
+
(EMPNO CHAR(6) NOT NULL,
|
275
|
+
PROJNO CHAR(6) NOT NULL,
|
276
|
+
ACTNO SMALLINT NOT NULL,
|
277
|
+
EMPTIME DECIMAL(5,2),
|
278
|
+
EMSTDATE DATE,
|
279
|
+
EMENDATE DATE,
|
280
|
+
CONSTRAINT EMP_ACT_UNIQ UNIQUE (EMPNO,PROJNO,ACTNO),
|
281
|
+
CONSTRAINT FK_ACT_PROJ FOREIGN KEY (PROJNO)
|
282
|
+
REFERENCES PROJECT (PROJNO) ON DELETE CASCADE
|
283
|
+
)
|
284
|
+
IN SCHED
|
285
|
+
EOF
|
286
|
+
begin
|
287
|
+
result = parser.parse(sql.downcase)
|
288
|
+
rescue Parslet::ParseFailed => error
|
289
|
+
puts error.cause.ascii_tree
|
290
|
+
end
|
291
|
+
result.should == {:operation=>"create table",
|
292
|
+
:table_name=>"emp_act",
|
293
|
+
:elements => [
|
294
|
+
{:column=>
|
295
|
+
{:field=>"empno",
|
296
|
+
:data_type=>{:char=>{:length=>{:integer=>"6"}}},
|
297
|
+
:options=>[{:column_option=>"not null"}]}},
|
298
|
+
{:column=>
|
299
|
+
{:field=>"projno",
|
300
|
+
:data_type=>{:char=>{:length=>{:integer=>"6"}}},
|
301
|
+
:options=>[{:column_option=>"not null"}]}},
|
302
|
+
{:column=>
|
303
|
+
{:field=>"actno",
|
304
|
+
:data_type=>"smallint",
|
305
|
+
:options=>[{:column_option=>"not null"}]}},
|
306
|
+
{:column=>
|
307
|
+
{:field=>"emptime",
|
308
|
+
:data_type=>
|
309
|
+
{:decimal=>
|
310
|
+
{:precision=>
|
311
|
+
{:total=>{:integer=>"5"}, :scale=>{:integer=>"2"}}}},
|
312
|
+
:options=>""}},
|
313
|
+
{:column=>{:field=>"emstdate", :data_type=>"date", :options=>""}},
|
314
|
+
{:column=>{:field=>"emendate", :data_type=>"date", :options=>""}},
|
315
|
+
{:constraint=>
|
316
|
+
{:column_name=>"emp_act_uniq",
|
317
|
+
:constraint_type=>"unique",
|
318
|
+
:constraint_arglist=>
|
319
|
+
[{:item=>"empno"}, {:item=>"projno"}, {:item=>"actno"}]}},
|
320
|
+
{:constraint=>
|
321
|
+
{:column_name=>"fk_act_proj",
|
322
|
+
:constraint_type=>"foreign key",
|
323
|
+
:constraint_arglist=>{:item=>"projno"},
|
324
|
+
:reference_arglist=>{:item=>"projno"}}}
|
325
|
+
]}
|
326
|
+
|
327
|
+
end
|
328
|
+
|
329
|
+
it "parses Example 12" do
|
330
|
+
sql = <<EOF
|
331
|
+
CREATE TABLE HOCKEY_GOALS
|
332
|
+
( BY_PLAYER VARCHAR(30) NOT NULL,
|
333
|
+
BY_TEAM VARCHAR(30) NOT NULL,
|
334
|
+
AGAINST_PLAYER VARCHAR(30) NOT NULL,
|
335
|
+
AGAINST_TEAM VARCHAR(30) NOT NULL,
|
336
|
+
DATE_OF_GOAL DATE NOT NULL,
|
337
|
+
DESCRIPTION CLOB(5000))
|
338
|
+
EOF
|
339
|
+
begin
|
340
|
+
result = parser.parse(sql.downcase)
|
341
|
+
rescue Parslet::ParseFailed => error
|
342
|
+
puts error.cause.ascii_tree
|
343
|
+
end
|
344
|
+
result.should == {:operation=>"create table", :table_name=>"hockey_goals",
|
345
|
+
:elements => [
|
346
|
+
{:column=>{:field=>"by_player", :data_type=>{:varchar=>{:length=>{:integer=>"30"}}}, :options=>[{:column_option=>"not null"}]}},
|
347
|
+
{:column=>{:field=>"by_team", :data_type=>{:varchar=>{:length=>{:integer=>"30"}}}, :options=>[{:column_option=>"not null"}]}},
|
348
|
+
{:column=>{:field=>"against_player", :data_type=>{:varchar=>{:length=>{:integer=>"30"}}}, :options=>[{:column_option=>"not null"}]}},
|
349
|
+
{:column=>{:field=>"against_team", :data_type=>{:varchar=>{:length=>{:integer=>"30"}}}, :options=>[{:column_option=>"not null"}]}},
|
350
|
+
{:column=>{:field=>"date_of_goal", :data_type=>"date", :options=>[{:column_option=>"not null"}]}},
|
351
|
+
{:column=>{:field=>"description", :data_type=>{:clob=>{:length=>{:integer=>"5000"}}}, :options=>""}}]}
|
352
|
+
end
|
353
|
+
|
354
|
+
it "parses Example 16" do
|
355
|
+
sql = <<EOF
|
356
|
+
CREATE TABLE DEPT
|
357
|
+
(DEPTNO SMALLINT NOT NULL
|
358
|
+
GENERATED ALWAYS AS IDENTITY
|
359
|
+
(START WITH 500, INCREMENT BY 1),
|
360
|
+
DEPTNAME VARCHAR(36) NOT NULL,
|
361
|
+
MGRNO CHAR(6),
|
362
|
+
ADMRDEPT SMALLINT NOT NULL,
|
363
|
+
LOCATION CHAR(30))
|
364
|
+
EOF
|
365
|
+
|
366
|
+
begin
|
367
|
+
result = parser.parse(sql.downcase)
|
368
|
+
rescue Parslet::ParseFailed => error
|
369
|
+
puts error.cause.ascii_tree
|
370
|
+
end
|
371
|
+
|
372
|
+
result.should == {:operation=>"create table",
|
373
|
+
:table_name=>"dept",
|
374
|
+
:elements => [
|
375
|
+
{:column=>{:field=>"deptno",
|
376
|
+
:data_type=>"smallint",
|
377
|
+
:options=>[{:column_option=>"not null"},
|
378
|
+
{:identity=>{:start_value=>{:integer=>"500"}, :increment_value=>{:integer=>"1"}}}]}},
|
379
|
+
{:column=>{:field=>"deptname",
|
380
|
+
:data_type=>{:varchar=>{:length=>{:integer=>"36"}}},
|
381
|
+
:options=>[{:column_option=>"not null"}]}},
|
382
|
+
{:column=>{:field=>"mgrno",
|
383
|
+
:data_type=>{:char=>{:length=>{:integer=>"6"}}},
|
384
|
+
:options=>""}},
|
385
|
+
{:column=>{:field=>"admrdept",
|
386
|
+
:data_type=>"smallint",
|
387
|
+
:options=>[{:column_option=>"not null"}]}},
|
388
|
+
{:column=>{:field=>"location",
|
389
|
+
:data_type=>{:char=>{:length=>{:integer=>"30"}}},
|
390
|
+
:options=>""}}]}
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
context "real dsv examples" do
|
396
|
+
it "parses Example 16" do
|
397
|
+
|
398
|
+
sql = <<EOF
|
399
|
+
Create table USER (USER_RW CHAR(4) NOT NULL,
|
400
|
+
USER_NAME CHAR(20) NOT NULL,
|
401
|
+
SECURITY_REPORT CHAR(2) NOT NULL,
|
402
|
+
SECURITY_AUTH CHAR(2) NOT NULL,
|
403
|
+
SECURITY_CORRECT CHAR(2) NOT NULL,
|
404
|
+
SECURITY_REVIEW CHAR(2) NOT NULL,
|
405
|
+
SECURITY_CHIEF CHAR(2) NOT NULL,
|
406
|
+
PASSWORD CHAR(6) NOT NULL,
|
407
|
+
SORT_SEQUENTIAL CHAR(4) NOT NULL,
|
408
|
+
CREATE_TS TIMESTAMP NOT NULL With Default CURRENT TIMESTAMP,
|
409
|
+
UPDATE_TS TIMESTAMP NOT NULL With Default CURRENT TIMESTAMP,
|
410
|
+
UNIQUE_NO INTEGER NOT NULL
|
411
|
+
Generated By Default as Identity (Start with 1 Increment by 1 cache 20))
|
412
|
+
in CPH_TS001
|
413
|
+
EOF
|
414
|
+
|
415
|
+
begin
|
416
|
+
result = parser.parse(sql.downcase)
|
417
|
+
rescue Parslet::ParseFailed => error
|
418
|
+
puts error.cause.ascii_tree
|
419
|
+
end
|
420
|
+
|
421
|
+
result[:operation].should == "create table"
|
422
|
+
result[:table_name].should == "user"
|
423
|
+
end
|
424
|
+
|
425
|
+
|
426
|
+
end
|
427
|
+
end
|