oracle-sql-parser 0.1.0
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 +7 -0
- data/.gitignore +19 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +58 -0
- data/Rakefile +41 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/oracle-sql-parser.rb +7 -0
- data/lib/oracle-sql-parser/ast.rb +38 -0
- data/lib/oracle-sql-parser/ast/array.rb +37 -0
- data/lib/oracle-sql-parser/ast/base.rb +89 -0
- data/lib/oracle-sql-parser/ast/between_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/current_of.rb +4 -0
- data/lib/oracle-sql-parser/ast/delete_statement.rb +5 -0
- data/lib/oracle-sql-parser/ast/delete_target.rb +6 -0
- data/lib/oracle-sql-parser/ast/exists_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/for_update_clause.rb +4 -0
- data/lib/oracle-sql-parser/ast/function_expression.rb +4 -0
- data/lib/oracle-sql-parser/ast/group_by_clause.rb +4 -0
- data/lib/oracle-sql-parser/ast/hash.rb +44 -0
- data/lib/oracle-sql-parser/ast/identifier.rb +7 -0
- data/lib/oracle-sql-parser/ast/in_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/insert_statement.rb +5 -0
- data/lib/oracle-sql-parser/ast/keyword.rb +8 -0
- data/lib/oracle-sql-parser/ast/like_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/logical_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/null_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/number_literal.rb +8 -0
- data/lib/oracle-sql-parser/ast/order_by_clause.rb +4 -0
- data/lib/oracle-sql-parser/ast/order_by_clause_item.rb +4 -0
- data/lib/oracle-sql-parser/ast/query_block.rb +17 -0
- data/lib/oracle-sql-parser/ast/regexp_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/rollup_cube_clause.rb +4 -0
- data/lib/oracle-sql-parser/ast/searched_case_expression.rb +8 -0
- data/lib/oracle-sql-parser/ast/select_statement.rb +5 -0
- data/lib/oracle-sql-parser/ast/simple_case_expression.rb +7 -0
- data/lib/oracle-sql-parser/ast/simple_comparision_condition.rb +4 -0
- data/lib/oracle-sql-parser/ast/subquery.rb +5 -0
- data/lib/oracle-sql-parser/ast/text_literal.rb +7 -0
- data/lib/oracle-sql-parser/ast/update_set_column.rb +4 -0
- data/lib/oracle-sql-parser/ast/update_statement.rb +4 -0
- data/lib/oracle-sql-parser/ast/where_clause.rb +4 -0
- data/lib/oracle-sql-parser/grammar.rb +10 -0
- data/lib/oracle-sql-parser/grammar/condition.treetop +224 -0
- data/lib/oracle-sql-parser/grammar/delete.treetop +68 -0
- data/lib/oracle-sql-parser/grammar/expression.treetop +236 -0
- data/lib/oracle-sql-parser/grammar/grammar.treetop +166 -0
- data/lib/oracle-sql-parser/grammar/insert.treetop +112 -0
- data/lib/oracle-sql-parser/grammar/reserved_word_generator.rb +233 -0
- data/lib/oracle-sql-parser/grammar/select.treetop +388 -0
- data/lib/oracle-sql-parser/grammar/update.treetop +113 -0
- data/lib/oracle-sql-parser/treetop_ext.rb +11 -0
- data/lib/oracle-sql-parser/version.rb +3 -0
- data/oracle-sql-parser.gemspec +28 -0
- metadata +176 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ec4ae7a3a58995d3526662584d0bfce9b1e8e12a
|
4
|
+
data.tar.gz: aeb8943ab1e0d845be0d9413dae2390073757d2d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6be02b972cc72b5b2d8cdb5e958bc1378156cda08f9bec5ac751bda59bee71aa762692e6da98c03e612e0841489045df6c16cbc34239128fbdb20079bff28f95
|
7
|
+
data.tar.gz: 701d2a80fc8a992bd139f8669922109899fcb075ae7cec80b57cb2de5339fc357dde2cc0fa5ff6425fc57c11cdaabd62b43ca97d5231fddb18554f5ed2854f2f
|
data/.gitignore
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
lib/oracle-sql-parser/grammar/condition.rb
|
11
|
+
lib/oracle-sql-parser/grammar/delete.rb
|
12
|
+
lib/oracle-sql-parser/grammar/expression.rb
|
13
|
+
lib/oracle-sql-parser/grammar/grammar.rb
|
14
|
+
lib/oracle-sql-parser/grammar/insert.rb
|
15
|
+
lib/oracle-sql-parser/grammar/reserved_word.rb
|
16
|
+
lib/oracle-sql-parser/grammar/reserved_word.treetop
|
17
|
+
lib/oracle-sql-parser/grammar/select.rb
|
18
|
+
lib/oracle-sql-parser/grammar/update.rb
|
19
|
+
*.sw?
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# SqlParser
|
2
|
+
|
3
|
+
SQL Parser for Oracle
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'sql_parser'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install sql_parser
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
query = "select 1 from dual"
|
25
|
+
parser = SqlParser::Oracle::OracleParser.new
|
26
|
+
syntax_tree = parser.parse query
|
27
|
+
if syntax_tree
|
28
|
+
message = "\n#{query}\n" + " " * (parser.failure_column.to_i-1) + "*\n"
|
29
|
+
raise parser.failure_reason + message
|
30
|
+
end
|
31
|
+
ast = syntax_tree.ast
|
32
|
+
```
|
33
|
+
<pre>
|
34
|
+
irb(main):008:0> ast
|
35
|
+
=> #<SqlParser::Ast::SelectStatement
|
36
|
+
:subquery => #<SqlParser::Ast::Subquery
|
37
|
+
:query_block => #<SqlParser::Ast::QueryBlock
|
38
|
+
:hint => nil,
|
39
|
+
:modifier => nil,
|
40
|
+
:select_list => #<SqlParser::Ast::Array [
|
41
|
+
#<SqlParser::Ast::NumberLiteral {:value=>"1"}>
|
42
|
+
]>
|
43
|
+
,
|
44
|
+
:select_sources => #<SqlParser::Ast::Identifier {:name=>"dual"}>,
|
45
|
+
:where_clause => nil,
|
46
|
+
:group_by_clause => nil,
|
47
|
+
:model_clause => nil}>
|
48
|
+
,
|
49
|
+
:order_by_clause => nil}>
|
50
|
+
,
|
51
|
+
:for_update_clause => nil}>
|
52
|
+
</pre>
|
53
|
+
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/jksy/sql_parser.
|
58
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
task :gen do
|
6
|
+
sh "ruby lib/oracle-sql-parser/grammar/reserved_word_generator.rb"
|
7
|
+
tt "lib/oracle-sql-parser/grammar/reserved_word.treetop"
|
8
|
+
tt "lib/oracle-sql-parser/grammar/expression.treetop"
|
9
|
+
tt "lib/oracle-sql-parser/grammar/condition.treetop"
|
10
|
+
tt "lib/oracle-sql-parser/grammar/select.treetop"
|
11
|
+
tt "lib/oracle-sql-parser/grammar/update.treetop"
|
12
|
+
tt "lib/oracle-sql-parser/grammar/delete.treetop"
|
13
|
+
tt "lib/oracle-sql-parser/grammar/insert.treetop"
|
14
|
+
tt "lib/oracle-sql-parser/grammar/grammar.treetop"
|
15
|
+
end
|
16
|
+
|
17
|
+
def tt(f, force = false)
|
18
|
+
output_file_name = "#{f.gsub(/\.treetop$/,'')}.rb"
|
19
|
+
|
20
|
+
force = true unless File.exists?(output_file_name)
|
21
|
+
if force || File::Stat.new(f).mtime >= File::Stat.new(output_file_name).mtime
|
22
|
+
sh "tt #{f} -f -o #{output_file_name}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
#task :test => [:generate]
|
28
|
+
|
29
|
+
Rake::TestTask.new do |t|
|
30
|
+
t.libs << "test"
|
31
|
+
t.test_files = FileList[
|
32
|
+
'test/grammar/select_test.rb',
|
33
|
+
'test/grammar/update_test.rb',
|
34
|
+
'test/grammar/expression_test.rb',
|
35
|
+
'test/grammar/condition_test.rb',
|
36
|
+
'test/grammar/delete_test.rb',
|
37
|
+
'test/grammar/insert_test.rb',
|
38
|
+
]
|
39
|
+
t.verbose = true
|
40
|
+
end
|
41
|
+
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "sql_parser"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module OracleSqlParser
|
2
|
+
module Ast
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'oracle-sql-parser/ast/base.rb'
|
7
|
+
require 'oracle-sql-parser/ast/array.rb'
|
8
|
+
require 'oracle-sql-parser/ast/hash.rb'
|
9
|
+
require 'oracle-sql-parser/ast/select_statement.rb'
|
10
|
+
require 'oracle-sql-parser/ast/subquery.rb'
|
11
|
+
require 'oracle-sql-parser/ast/query_block.rb'
|
12
|
+
require 'oracle-sql-parser/ast/where_clause.rb'
|
13
|
+
require 'oracle-sql-parser/ast/simple_comparision_condition.rb'
|
14
|
+
require 'oracle-sql-parser/ast/logical_condition.rb'
|
15
|
+
require 'oracle-sql-parser/ast/like_condition.rb'
|
16
|
+
require 'oracle-sql-parser/ast/regexp_condition.rb'
|
17
|
+
require 'oracle-sql-parser/ast/null_condition.rb'
|
18
|
+
require 'oracle-sql-parser/ast/between_condition.rb'
|
19
|
+
require 'oracle-sql-parser/ast/exists_condition.rb'
|
20
|
+
require 'oracle-sql-parser/ast/in_condition.rb'
|
21
|
+
require 'oracle-sql-parser/ast/group_by_clause.rb'
|
22
|
+
require 'oracle-sql-parser/ast/rollup_cube_clause.rb'
|
23
|
+
require 'oracle-sql-parser/ast/for_update_clause.rb'
|
24
|
+
require 'oracle-sql-parser/ast/order_by_clause.rb'
|
25
|
+
require 'oracle-sql-parser/ast/order_by_clause_item.rb'
|
26
|
+
require 'oracle-sql-parser/ast/update_statement.rb'
|
27
|
+
require 'oracle-sql-parser/ast/update_set_column.rb'
|
28
|
+
require 'oracle-sql-parser/ast/simple_case_expression.rb'
|
29
|
+
require 'oracle-sql-parser/ast/searched_case_expression.rb'
|
30
|
+
require 'oracle-sql-parser/ast/function_expression.rb'
|
31
|
+
require 'oracle-sql-parser/ast/current_of.rb'
|
32
|
+
require 'oracle-sql-parser/ast/delete_statement.rb'
|
33
|
+
require 'oracle-sql-parser/ast/delete_target.rb'
|
34
|
+
require 'oracle-sql-parser/ast/insert_statement.rb'
|
35
|
+
require 'oracle-sql-parser/ast/identifier.rb'
|
36
|
+
require 'oracle-sql-parser/ast/text_literal.rb'
|
37
|
+
require 'oracle-sql-parser/ast/number_literal.rb'
|
38
|
+
require 'oracle-sql-parser/ast/keyword.rb'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module OracleSqlParser::Ast
|
4
|
+
class Array < Base
|
5
|
+
extend Forwardable
|
6
|
+
def_delegator :@ast, :each, :[]
|
7
|
+
def self.[](*values)
|
8
|
+
self.new(*values)
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(*args)
|
12
|
+
@ast = args
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_sql
|
16
|
+
@ast.map do |v|
|
17
|
+
if v.respond_to? :to_sql
|
18
|
+
v.to_sql
|
19
|
+
else
|
20
|
+
v.to_s
|
21
|
+
end
|
22
|
+
end.compact.join(" ")
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_nil_values!
|
26
|
+
@ast.delete_if{|v| v.nil?}
|
27
|
+
@ast.each {|v| v.remove_nil_values! if v.respond_to? :remove_nil_values!}
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def inspect
|
32
|
+
"#<#{self.class.name} [\n" +
|
33
|
+
@ast.map{|v| "#{v.inspect}"}.join(",\n").gsub(/^/, ' ') +
|
34
|
+
"\n]>\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
def nil.ast
|
2
|
+
nil
|
3
|
+
end
|
4
|
+
|
5
|
+
def nil.to_sql
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
class String
|
10
|
+
def to_sql
|
11
|
+
self
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module OracleSqlParser::Ast
|
16
|
+
class Base
|
17
|
+
def initialize(arg)
|
18
|
+
if arg.instance_of?(Array) || arg.instance_of?(Hash)
|
19
|
+
raise "cant assign #{arg.class} Base.new()"
|
20
|
+
end
|
21
|
+
@ast = arg
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_nil_values!
|
25
|
+
@ast.remove_nil_values! if @ast.respond_to? :remove_nil_values!
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
"#<#{self.class.name} #{@ast.inspect}>"
|
31
|
+
end
|
32
|
+
alias :to_s :inspect
|
33
|
+
|
34
|
+
def ast
|
35
|
+
raise "do not call ast method"
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_sql
|
39
|
+
if @ast.respond_to? :to_sql
|
40
|
+
@ast.to_sql
|
41
|
+
else
|
42
|
+
@ast.to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.[](value)
|
47
|
+
self.new(value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.find_different_value(left, right, &block)
|
51
|
+
if left.class != right.class
|
52
|
+
block.call(left, right) if block_given?
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
|
56
|
+
result = false
|
57
|
+
case left
|
58
|
+
when Base
|
59
|
+
result ||= self.find_different_value(
|
60
|
+
left.instance_variable_get(:@ast),
|
61
|
+
right.instance_variable_get(:@ast),
|
62
|
+
&block)
|
63
|
+
when Hash
|
64
|
+
(left.keys + right.keys).uniq.each do |key|
|
65
|
+
result ||= self.find_different_value(left[key], right[key], &block)
|
66
|
+
end
|
67
|
+
when OracleSqlParser::Ast::Array
|
68
|
+
if left.size == right.size
|
69
|
+
left.each_with_index do |value, index|
|
70
|
+
result ||= self.find_different_value(value, right[index], &block)
|
71
|
+
end
|
72
|
+
else
|
73
|
+
block.call(left, right) if block_given?
|
74
|
+
result = true
|
75
|
+
end
|
76
|
+
else
|
77
|
+
if left != right
|
78
|
+
block.call(left, right) if block_given?
|
79
|
+
result = true
|
80
|
+
end
|
81
|
+
end
|
82
|
+
result
|
83
|
+
end
|
84
|
+
|
85
|
+
def ==(value)
|
86
|
+
self.class.find_different_value(self, value) != true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module OracleSqlParser::Ast
|
4
|
+
class Hash < Base
|
5
|
+
extend Forwardable
|
6
|
+
def_delegator :@ast, :keys, :[]
|
7
|
+
|
8
|
+
def initialize(value)
|
9
|
+
raise "only ::Hash instance" unless value.instance_of? ::Hash
|
10
|
+
@ast = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_nil_values!
|
14
|
+
@ast.delete_if{|k, v| v.nil?}
|
15
|
+
@ast.each {|k, v| v.remove_nil_values! if v.respond_to? :remove_nil_values!}
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#<#{self.class.name}\n" +
|
21
|
+
@ast.map{|k,v| "#{k.inspect} => #{v.inspect}"}.join(",\n").gsub(/^/, ' ') +
|
22
|
+
"}>\n"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_sql
|
26
|
+
@ast.map do |k,v|
|
27
|
+
if v.respond_to? :to_sql
|
28
|
+
v.to_sql
|
29
|
+
else
|
30
|
+
v.to_s
|
31
|
+
end
|
32
|
+
end.compact.join(" ")
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.[](value)
|
36
|
+
self.new(value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(name, *args)
|
40
|
+
return @ast.send(:[], name) if @ast.has_key? name
|
41
|
+
raise "no method:#{name}, #{@ast.class} in #{self.class}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|