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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/README.md +58 -0
  6. data/Rakefile +41 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/lib/oracle-sql-parser.rb +7 -0
  10. data/lib/oracle-sql-parser/ast.rb +38 -0
  11. data/lib/oracle-sql-parser/ast/array.rb +37 -0
  12. data/lib/oracle-sql-parser/ast/base.rb +89 -0
  13. data/lib/oracle-sql-parser/ast/between_condition.rb +4 -0
  14. data/lib/oracle-sql-parser/ast/current_of.rb +4 -0
  15. data/lib/oracle-sql-parser/ast/delete_statement.rb +5 -0
  16. data/lib/oracle-sql-parser/ast/delete_target.rb +6 -0
  17. data/lib/oracle-sql-parser/ast/exists_condition.rb +4 -0
  18. data/lib/oracle-sql-parser/ast/for_update_clause.rb +4 -0
  19. data/lib/oracle-sql-parser/ast/function_expression.rb +4 -0
  20. data/lib/oracle-sql-parser/ast/group_by_clause.rb +4 -0
  21. data/lib/oracle-sql-parser/ast/hash.rb +44 -0
  22. data/lib/oracle-sql-parser/ast/identifier.rb +7 -0
  23. data/lib/oracle-sql-parser/ast/in_condition.rb +4 -0
  24. data/lib/oracle-sql-parser/ast/insert_statement.rb +5 -0
  25. data/lib/oracle-sql-parser/ast/keyword.rb +8 -0
  26. data/lib/oracle-sql-parser/ast/like_condition.rb +4 -0
  27. data/lib/oracle-sql-parser/ast/logical_condition.rb +4 -0
  28. data/lib/oracle-sql-parser/ast/null_condition.rb +4 -0
  29. data/lib/oracle-sql-parser/ast/number_literal.rb +8 -0
  30. data/lib/oracle-sql-parser/ast/order_by_clause.rb +4 -0
  31. data/lib/oracle-sql-parser/ast/order_by_clause_item.rb +4 -0
  32. data/lib/oracle-sql-parser/ast/query_block.rb +17 -0
  33. data/lib/oracle-sql-parser/ast/regexp_condition.rb +4 -0
  34. data/lib/oracle-sql-parser/ast/rollup_cube_clause.rb +4 -0
  35. data/lib/oracle-sql-parser/ast/searched_case_expression.rb +8 -0
  36. data/lib/oracle-sql-parser/ast/select_statement.rb +5 -0
  37. data/lib/oracle-sql-parser/ast/simple_case_expression.rb +7 -0
  38. data/lib/oracle-sql-parser/ast/simple_comparision_condition.rb +4 -0
  39. data/lib/oracle-sql-parser/ast/subquery.rb +5 -0
  40. data/lib/oracle-sql-parser/ast/text_literal.rb +7 -0
  41. data/lib/oracle-sql-parser/ast/update_set_column.rb +4 -0
  42. data/lib/oracle-sql-parser/ast/update_statement.rb +4 -0
  43. data/lib/oracle-sql-parser/ast/where_clause.rb +4 -0
  44. data/lib/oracle-sql-parser/grammar.rb +10 -0
  45. data/lib/oracle-sql-parser/grammar/condition.treetop +224 -0
  46. data/lib/oracle-sql-parser/grammar/delete.treetop +68 -0
  47. data/lib/oracle-sql-parser/grammar/expression.treetop +236 -0
  48. data/lib/oracle-sql-parser/grammar/grammar.treetop +166 -0
  49. data/lib/oracle-sql-parser/grammar/insert.treetop +112 -0
  50. data/lib/oracle-sql-parser/grammar/reserved_word_generator.rb +233 -0
  51. data/lib/oracle-sql-parser/grammar/select.treetop +388 -0
  52. data/lib/oracle-sql-parser/grammar/update.treetop +113 -0
  53. data/lib/oracle-sql-parser/treetop_ext.rb +11 -0
  54. data/lib/oracle-sql-parser/version.rb +3 -0
  55. data/oracle-sql-parser.gemspec +28 -0
  56. 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
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sql_parser.gemspec
4
+ gemspec
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
+ => #&lt;SqlParser::Ast::SelectStatement
36
+ :subquery =&gt; #&lt;SqlParser::Ast::Subquery
37
+ :query_block =&gt; #&lt;SqlParser::Ast::QueryBlock
38
+ :hint =&gt; nil,
39
+ :modifier =&gt; nil,
40
+ :select_list =&gt; #&lt;SqlParser::Ast::Array [
41
+ #&lt;SqlParser::Ast::NumberLiteral {:value=&gt;"1"}>
42
+ ]>
43
+ ,
44
+ :select_sources =&gt; #&lt;SqlParser::Ast::Identifier {:name=&gt;"dual"}>,
45
+ :where_clause =&gt; nil,
46
+ :group_by_clause =&gt; nil,
47
+ :model_clause =&gt; nil}>
48
+ ,
49
+ :order_by_clause =&gt; nil}>
50
+ ,
51
+ :for_update_clause =&gt; 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,8 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+ rake gen
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ module OracleSqlParser
2
+ end
3
+ require 'treetop'
4
+ require 'oracle-sql-parser/version.rb'
5
+ require 'oracle-sql-parser/ast.rb'
6
+ require 'oracle-sql-parser/treetop_ext.rb'
7
+ require 'oracle-sql-parser/grammar.rb'
@@ -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,4 @@
1
+ module OracleSqlParser::Ast
2
+ class BetweenCondition < Hash
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module OracleSqlParser::Ast
2
+ class CurrentOf < Hash
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module OracleSqlParser::Ast
2
+ class DeleteStatement < Hash
3
+
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ module OracleSqlParser::Ast
2
+ class DeleteTarget < Hash
3
+
4
+ end
5
+ end
6
+
@@ -0,0 +1,4 @@
1
+ module OracleSqlParser::Ast
2
+ class ExistsCondition < Hash
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module OracleSqlParser::Ast
2
+ class ForUpdateClause < Hash
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module OracleSqlParser::Ast
2
+ class FunctionExpressoin < Hash
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module OracleSqlParser::Ast
2
+ class GroupByClause < Hash
3
+ end
4
+ 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