ddl_parser 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,96 @@
1
+ require "spec_helper"
2
+
3
+ describe 'DDLParser::Parser' do
4
+
5
+ it "knows if it's valid" do
6
+ sql = "CREATE TABLE TEST (ID INT)"
7
+ parser = DDLParser::Parser.new(sql)
8
+ parser.valid?.should == true
9
+ end
10
+
11
+ it "knows if it's invalid" do
12
+ sql = "CREATE TABLE TEST ()"
13
+ parser = DDLParser::Parser.new(sql)
14
+ parser.valid?.should == false
15
+ end
16
+
17
+ it "can report errors" do
18
+ sql = "CREATE TABLE TEST ()"
19
+ parser = DDLParser::Parser.new(sql)
20
+ parser.errors.should include("CREATE_TABLE_STATEMENT")
21
+ end
22
+
23
+ it "statement_type" do
24
+ sql = "CREATE TABLE TEST (ID INT, FOO INT)"
25
+ parser = DDLParser::Parser.new(sql)
26
+ parser.statement_type.should == :create_table
27
+ end
28
+
29
+ it "returns the parse tree" do
30
+ sql = "CREATE TABLE TEST (ID INT, FOO INT)"
31
+ parser = DDLParser::Parser.new(sql)
32
+ parser.parse_tree.should == {:operation=>"CREATE TABLE", :table_name=>"TEST", :elements=>[
33
+ {:column=>{:field=>"ID", :data_type=>"INT", :options=>""}},
34
+ {:column=>{:field=>"FOO", :data_type=>"INT", :options=>""}}]}
35
+ end
36
+
37
+ context "create table translate" do
38
+ it "translate table_name" do
39
+ sql = "CREATE TABLE TEST (ID INT, FOO INT)"
40
+ parser = DDLParser::Parser.new(sql)
41
+ parser.translate.table_name.should == "TEST"
42
+ end
43
+
44
+
45
+ it "translate columns" do
46
+ sql = "CREATE TABLE TEST (ID INT, FOO INT)"
47
+ parser = DDLParser::Parser.new(sql)
48
+ parser.translate.columns.should == [{:field=>"ID", :data_type=>"INT", :options=>""}, {:field=>"FOO", :data_type=>"INT", :options=>""}]
49
+
50
+ sql = "CREATE TABLE TEST (ID INT)"
51
+ parser = DDLParser::Parser.new(sql)
52
+ parser.translate.columns.should == [{:field=>"ID", :data_type=>"INT", :options=>""}]
53
+ end
54
+
55
+ it "translate primary key" do
56
+ sql = "CREATE TABLE TEST (ID INT, PRIMARY KEY (ID))"
57
+ parser = DDLParser::Parser.new(sql)
58
+ parser.translate.primary_key.should == "ID"
59
+ end
60
+ end
61
+
62
+ context "alter table translate" do
63
+ let(:sql) {
64
+ sql = <<EOF
65
+ ALTER TABLE BUDGET
66
+ ADD COLUMN BUDGET_AMOUNT_IN_CO DECIMAL(15,2) NOT NULL DEFAULT 0
67
+ ADD COLUMN BUDGET_AMOUNT_CURR CHARACTER(4)
68
+ EOF
69
+ sql
70
+ }
71
+
72
+ it "translate table_name" do
73
+ parser = DDLParser::Parser.new(sql)
74
+ parser.translate.table_name.should == "BUDGET"
75
+ end
76
+
77
+
78
+ it "translate columns" do
79
+ parser = DDLParser::Parser.new(sql)
80
+ parser.translate.add_columns.should == [{:field=>"BUDGET_AMOUNT_IN_CO",
81
+ :data_type=>{:decimal=>{:precision=>{:total=>{:integer=>"15"}, :scale=>{:integer=>"2"}}}},
82
+ :options=>[{:column_option=>"NOT NULL"},
83
+ {:default_clause=>[{:integer=>"0"}]}]},
84
+ {:field=>"BUDGET_AMOUNT_CURR",
85
+ :data_type=>{:char=>{:length=>{:integer=>"4"}}},
86
+ :options=>""}]
87
+ end
88
+
89
+ it "translate primary key" do
90
+ sql = "CREATE TABLE TEST (ID INT, PRIMARY KEY (ID))"
91
+ parser = DDLParser::Parser.new(sql)
92
+ parser.translate.primary_key.should == "ID"
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,126 @@
1
+ require "spec_helper"
2
+
3
+ class DummyParser < Parslet::Parser
4
+ include DDLParser::SharedRules::Constants
5
+ end
6
+
7
+ describe DDLParser::SharedRules::Constants do
8
+ let(:parser) { DummyParser.new }
9
+
10
+ it "digits" do
11
+ (0..9).each do |digit|
12
+ expect(parser.digit).to parse(digit.to_s)
13
+ end
14
+ ("a".."z").each do |non_digit|
15
+ expect(parser.digit).not_to parse(non_digit.to_s)
16
+ end
17
+ end
18
+
19
+ it "integer" do
20
+ expect(parser.integer).to parse("1")
21
+ expect(parser.integer).to parse("123456789")
22
+ expect(parser.integer).to parse("-123456789")
23
+ expect(parser.integer).to parse("0123")
24
+ expect(parser.integer).not_to parse("1.2")
25
+ end
26
+
27
+ it "float" do
28
+ expect(parser.float).to parse("-1.1")
29
+ expect(parser.float).to parse("1.1")
30
+ expect(parser.float).to parse("123456.789")
31
+ expect(parser.float).to parse("-123456.789")
32
+ expect(parser.float).not_to parse("12")
33
+ end
34
+
35
+ it "space" do
36
+ expect(parser.space).to parse(" ")
37
+ expect(parser.space).to parse(" ")
38
+ expect(parser.space).to parse("\t")
39
+ expect(parser.space).not_to parse("")
40
+ expect(parser.space).not_to parse("1")
41
+ end
42
+
43
+ it "space?" do
44
+ expect(parser.space?).to parse("")
45
+ expect(parser.space?).to parse(" ")
46
+ expect(parser.space?).to parse(" ")
47
+ expect(parser.space?).not_to parse("1")
48
+ end
49
+
50
+ it "newline" do
51
+ expect(parser.newline).to parse("\n")
52
+ expect(parser.newline).not_to parse(" ")
53
+ expect(parser.newline).not_to parse("\t")
54
+ end
55
+
56
+ it "spaces" do
57
+ expect(parser.spaces).to parse("\n")
58
+ expect(parser.spaces).to parse(" \n \n")
59
+ expect(parser.spaces).to parse("\t ")
60
+ end
61
+
62
+ it "comment?" do
63
+ expect(parser.comment?).to parse("-- foobar")
64
+ expect(parser.comment?).not_to parse("--\nfoobar")
65
+ end
66
+
67
+ it "comma" do
68
+ expect(parser.comma).to parse(",")
69
+ expect(parser.comma).to parse(", ")
70
+ expect(parser.comma).not_to parse(" , ")
71
+ end
72
+
73
+ it "lparen" do
74
+ expect(parser.lparen).to parse("(")
75
+ expect(parser.lparen).to parse("( ")
76
+ expect(parser.lparen).not_to parse(" (")
77
+ end
78
+
79
+ it "rparen" do
80
+ expect(parser.rparen).to parse(")")
81
+ expect(parser.rparen).to parse(") ")
82
+ expect(parser.rparen).not_to parse(" )")
83
+ end
84
+
85
+ it "boolean" do
86
+ expect(parser.boolean).to parse("true")
87
+ expect(parser.boolean).to parse("false")
88
+ expect(parser.boolean).not_to parse("false ")
89
+ end
90
+
91
+ it "datetime" do
92
+ expect(parser.datetime).to parse("2014-02-28T12:01:02Z")
93
+ end
94
+
95
+ it "string" do
96
+ expect(parser.string).to parse("'foobar'")
97
+ expect(parser.string).to parse("'foo bar'")
98
+ expect(parser.string).not_to parse("'foo bar")
99
+ expect(parser.string).not_to parse('"foobar"')
100
+ end
101
+
102
+ it "const" do
103
+ expect(parser.const).to parse("'foobar'")
104
+ expect(parser.const).to parse("1")
105
+ expect(parser.const).to parse("1.1")
106
+ expect(parser.const).to parse("true")
107
+ expect(parser.const).to parse("2014-02-28T12:01:02Z")
108
+ expect(parser.const).not_to parse("(")
109
+ expect(parser.const).not_to parse(',')
110
+ end
111
+
112
+ it "identifier" do
113
+ expect(parser.identifier).to parse("foobar")
114
+ expect(parser.identifier).not_to parse("foo bar")
115
+ expect(parser.identifier).to parse("a")
116
+ expect(parser.identifier).to parse("aB")
117
+ expect(parser.identifier).to parse("A1")
118
+ expect(parser.identifier).to parse("A1_2")
119
+ expect(parser.identifier).not_to parse("A B")
120
+ end
121
+
122
+ it "current_timestamp" do
123
+ expect(parser.current_timestamp).to parse("current timestamp")
124
+ end
125
+
126
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ class DummyParser < Parslet::Parser
4
+ include DDLParser::SharedRules::DataTypes
5
+ end
6
+
7
+ describe DDLParser::SharedRules::DataTypes do
8
+ let(:parser) { DummyParser.new }
9
+
10
+ it "parses data types" do
11
+ parser.data_type.parse("smallint").should == {:data_type=>"smallint"}
12
+ parser.data_type.parse("int").should == {:data_type=>"int"}
13
+ parser.data_type.parse("decimal(1,2)").should == {:data_type=>{:decimal=>{:precision => {:total=>{:integer=>"1"}, :scale=>{:integer=>"2"}}}}}
14
+ parser.data_type.parse("float(1)").should == {:data_type=>{:float=>{:precision=>{:integer=>"1"}}}}
15
+ parser.data_type.parse("real").should == {:data_type=>"real"}
16
+ parser.data_type.parse("double").should == {:data_type=>"double"}
17
+ parser.data_type.parse("char(1)").should == {:data_type=>{:char=>{:length=>{:integer=>"1"}}}}
18
+ parser.data_type.parse("varchar(1)").should == {:data_type=>{:varchar=>{:length=>{:integer=>"1"}}}}
19
+ parser.data_type.parse("clob(50000)").should == {:data_type=>{:clob=>{:length=>{:integer=>"50000"}}}}
20
+ parser.data_type.parse("date").should == {:data_type=>"date"}
21
+ parser.data_type.parse("time").should == {:data_type=>"time"}
22
+ parser.data_type.parse("timestamp").should == {:data_type=>"timestamp"}
23
+ end
24
+
25
+
26
+ end
27
+
@@ -0,0 +1,166 @@
1
+ require "spec_helper"
2
+
3
+ describe DDLParser::SQL::DB2::SelectParser do
4
+ let(:parser) { DDLParser::SQL::DB2::SelectParser.new }
5
+
6
+ context "value parsing" do
7
+
8
+ it "parses integers" do
9
+ expect(parser.const).to parse("1")
10
+ expect(parser.const).to parse("-123")
11
+ expect(parser.const).to parse("120381")
12
+ expect(parser.const).to parse("181")
13
+ expect(parser.const).to parse("0181")
14
+ end
15
+
16
+ it "parses floats" do
17
+ expect(parser.const).to parse("0.1")
18
+ expect(parser.const).to parse("3.14159")
19
+ expect(parser.const).to parse("-0.00001")
20
+ expect(parser.const).to_not parse(".1")
21
+ end
22
+
23
+ it "parses booleans" do
24
+ expect(parser.const).to parse("true")
25
+ expect(parser.const).to parse("false")
26
+ expect(parser.const).to_not parse("truefalse")
27
+ end
28
+
29
+ it "parses datetimes" do
30
+ expect(parser.const).to parse("1979-05-27T07:32:00Z")
31
+ expect(parser.const).to parse("2013-02-24T17:26:21Z")
32
+ expect(parser.const).to_not parse("1979l05-27 07:32:00")
33
+ end
34
+
35
+ it "parses strings" do
36
+ expect(parser.const).to parse("''")
37
+ expect(parser.const).to parse("'hello world'")
38
+ expect(parser.const).to parse("'120.0, ~!@#$\%^&*+_\}{ asdfasf'")
39
+ expect(parser.const).not_to parse('"hello world"')
40
+ end
41
+
42
+ end
43
+
44
+ context "namelist parsing" do
45
+ it "simple" do
46
+ expect(parser.namelist).to parse('a,b,c')
47
+ expect(parser.namelist).to parse('a, b, C')
48
+ end
49
+
50
+ it "not parse invalid" do
51
+ expect(parser.namelist).not_to parse('a b')
52
+ expect(parser.namelist).not_to parse('a: b')
53
+ expect(parser.namelist).not_to parse("a; b" )
54
+ expect(parser.namelist).not_to parse("a, b, 'foo'" )
55
+ expect(parser.namelist).not_to parse("a, b, max(c)" )
56
+ end
57
+
58
+ end
59
+
60
+ context "arglist parsing" do
61
+ it "simple" do
62
+ expect(parser.arglist).to parse('a,b,c')
63
+ expect(parser.arglist).to parse('a, b, c')
64
+ expect(parser.arglist).to parse("a, b, 'foo'" )
65
+ expect(parser.arglist).to parse("a, b, max(c)" )
66
+ end
67
+
68
+ it "not parse invalid" do
69
+ expect(parser.arglist).not_to parse('a b')
70
+ expect(parser.arglist).not_to parse('a: b')
71
+ expect(parser.arglist).not_to parse("a; b" )
72
+ end
73
+
74
+ end
75
+
76
+ context "between parsing" do
77
+ it "should parse between" do
78
+ expect(parser.single_cond).to parse("a between 1 and 2")
79
+ expect(parser.single_cond).to parse("a between 1 and 2")
80
+ expect(parser.single_cond.parse("a between 1 and 2")).to eq(:lhs=>"a", :op=>"between", :rhs=>{:btw_from=>{:integer=>"1"}, :btw_to=>{:integer=>"2"}})
81
+ end
82
+ end
83
+
84
+ context "like parsing" do
85
+ it "should parse" do
86
+ expect(parser.single_cond).to parse("a like '%foo%bar'")
87
+ end
88
+
89
+ end
90
+
91
+ context "condition parsing" do
92
+ it "should parse single" do
93
+ expect(parser.condition).to parse("a = a")
94
+ expect(parser.condition).to parse("a=a")
95
+ expect(parser.condition).to parse("a > a")
96
+ expect(parser.condition).to parse("a < a")
97
+ expect(parser.condition).to parse("a between 1 and 2")
98
+ expect(parser.condition).to parse("a like '%foo%bar'")
99
+ end
100
+
101
+ it "should parse multible" do
102
+ expect(parser.condition).to parse("a = a or b = b")
103
+ expect(parser.condition).to parse("a = a and b = b")
104
+ expect(parser.condition).to parse("a > a and a between 'foo' and 'bar'")
105
+ expect(parser.condition).to parse("a < a and a like '%foo%bar'")
106
+ end
107
+
108
+ end
109
+
110
+ context "select statements" do
111
+ it "parse simple statements" do
112
+ [
113
+ 'select a from b',
114
+ 'select a, b from comme',
115
+ 'select b from far',
116
+ 'select c from d',
117
+ 'select a, c, d,e,f,f from b ',
118
+ 'select count(a) from d',
119
+ ].each do |sql|
120
+ expect(parser).to parse(sql)
121
+ end
122
+ end
123
+
124
+ it "parse statements with where" do
125
+ [
126
+ 'select a from b where a > 20',
127
+ 'select a,b from c where a = 20',
128
+ 'select a,b from c where 20 < a and b < 234',
129
+ 'select a,b from c where 20 < a or b = 234',
130
+ 'select a, b from c where a = ''oo''',
131
+ 'select a, b from c where a = ''oo'' and c > 235',
132
+ ].each do |sql|
133
+ expect(parser).to parse(sql)
134
+ end
135
+ end
136
+
137
+ it "parse statements with group by" do
138
+ [
139
+ 'select a from b group by c',
140
+ 'select a from b where a > 345 group by c',
141
+ 'select a from b where a > 345 and foo = ''hoge'' group by c',
142
+ ].each do |sql|
143
+ expect(parser).to parse(sql)
144
+ end
145
+ end
146
+
147
+ it "not to parse bad selects" do
148
+ [
149
+ 'select',
150
+ 'select a, b from c where a = "120.0, ~!@#$%^&*+_\}{\" asdfa"sf"',
151
+ ].each do |sql|
152
+ expect(parser).not_to parse(sql)
153
+ end
154
+ end
155
+
156
+ end
157
+
158
+ context "extract" do
159
+ it "should fetch select" do
160
+ result = parser.parse("select a from b where a = b")
161
+ #result[:select].should
162
+ end
163
+ end
164
+
165
+
166
+ end
@@ -0,0 +1,23 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.run_all_when_everything_filtered = true
4
+ config.filter_run :focus
5
+
6
+ #config.expect_with :rspec do |c|
7
+ # c.syntax = :expect
8
+ #end
9
+
10
+ # Run specs in random order to surface order dependencies. If you find an
11
+ # order dependency and want to debug it, you can fix the order by providing
12
+ # the seed, which is printed after each run.
13
+ # --seed 1234
14
+ config.order = 'random'
15
+ end
16
+
17
+ require "parslet/rig/rspec"
18
+ require "ddl_parser"
19
+ require "yaml"
20
+
21
+ def fixture(filename)
22
+ File.read("spec/fixtures/#{filename}")
23
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ddl_parser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rasmus Bergholdt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parslet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '2.2'
69
+ description: Parse SQL and DDL statements
70
+ email:
71
+ - raber@eg.dk
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .rspec
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - ddl_parser.gemspec
83
+ - lib/ddl_parser.rb
84
+ - lib/ddl_parser/ddl.rb
85
+ - lib/ddl_parser/ddl/db2.rb
86
+ - lib/ddl_parser/ddl/db2/parser.rb
87
+ - lib/ddl_parser/parser.rb
88
+ - lib/ddl_parser/shared_rules.rb
89
+ - lib/ddl_parser/shared_rules/constants.rb
90
+ - lib/ddl_parser/shared_rules/data_types.rb
91
+ - lib/ddl_parser/shared_rules/logical_operators.rb
92
+ - lib/ddl_parser/sql.rb
93
+ - lib/ddl_parser/sql/db2.rb
94
+ - lib/ddl_parser/sql/db2/select_parser.rb
95
+ - lib/ddl_parser/translater.rb
96
+ - lib/ddl_parser/translater/alter_table.rb
97
+ - lib/ddl_parser/translater/create_index.rb
98
+ - lib/ddl_parser/translater/create_table.rb
99
+ - lib/ddl_parser/version.rb
100
+ - lib/parslet_extentions.rb
101
+ - spec/ddl_parser/ddl/db2/alter_table_spec.rb
102
+ - spec/ddl_parser/ddl/db2/create_index_spec.rb
103
+ - spec/ddl_parser/ddl/db2/create_table_spec.rb
104
+ - spec/ddl_parser/parser_spec.rb
105
+ - spec/ddl_parser/shared_rules/constants_spec.rb
106
+ - spec/ddl_parser/shared_rules/data_types_spec.rb
107
+ - spec/ddl_parser/sql/db2/select_parser_spec.rb
108
+ - spec/spec_helper.rb
109
+ homepage: ''
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: will parse statements and make it possible to extract content
133
+ test_files:
134
+ - spec/ddl_parser/ddl/db2/alter_table_spec.rb
135
+ - spec/ddl_parser/ddl/db2/create_index_spec.rb
136
+ - spec/ddl_parser/ddl/db2/create_table_spec.rb
137
+ - spec/ddl_parser/parser_spec.rb
138
+ - spec/ddl_parser/shared_rules/constants_spec.rb
139
+ - spec/ddl_parser/shared_rules/data_types_spec.rb
140
+ - spec/ddl_parser/sql/db2/select_parser_spec.rb
141
+ - spec/spec_helper.rb
142
+ has_rdoc: