oracle-sql-parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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