lib/each_sql.rb in each_sql-0.2.5 vs lib/each_sql.rb in each_sql-0.3.0
- old
+ new
@@ -1,126 +1,62 @@
# encoding: UTF-8
# Junegunn Choi (junegunn.c@gmail.com)
+require 'rubygems'
require 'each_sql/each_sql'
+require 'each_sql/parser'
# Shortcut method for creating a Enumerable EachSQL object for the given input.
# @param[String] input Input script.
# @param[Symbol] The type of the input SQL script. :default, :mysql, and :oracle (or :plsql)
-# @return[EachSQL] Enumerable
+# @yield[String] Executable SQL statement or block.
+# @return[Array] Array of executable SQL statements and blocks.
def EachSQL input, type = :default
- esql = EachSQL.new(input, EachSQL::Defaults[type])
+ esql = EachSQL.new(type)
+ ret = []
+ result = {}
- if block_given?
- esql.each do |sql|
- yield sql
+ process = lambda {
+ return if esql.empty?
+ result = esql.shift
+ sqls = result[:sqls]
+ sqls.each do |sql|
+ if block_given?
+ yield sql
+ else
+ ret << sql
+ end
end
- else
- esql
+ }
+
+ input.to_s.each_line do |line|
+ case line
+ when /^\s*delimiter\s+(\S+)/i
+ process.call
+ if esql.empty?
+ esql.delimiter = $1
+ else
+ esql << line
+ end
+ when /#{Regexp.escape esql.delimiter}/
+ esql << line
+ process.call
+ else
+ esql << line
+ end
end
-end
-class EachSQL
- # EachSQL::Default Hash is a set of pre-defined parsing rules
- # - :default: Default parsing rules for vendor-independent SQL scripts
- # - :mysql: Parsing rules for MySQL scripts. Understands `delimiter' statements.
- # - :oracle: Parsing rules for Oracle scripts. Removes trailing slashes after begin-end blocks.
- Defaults = {
- :default => {
- :delimiter => /;+/,
- :blocks => {
- /`/ => /`/,
- /"/ => /"/,
- /'/ => /'/,
- /\/\*[^+]/ => /\*\//,
- /--+/ => $/,
- },
- :nesting_blocks => {
- /\bdeclare.*?;\s*?begin\b/im => /;\s*?end\b/i,
- /\bbegin\b/i => /;\s*?end\b/i,
- },
- :nesting_context => [
- /\A\s*(begin|declare|create\b[^;]+?\b(procedure|function|trigger|package))\b/im
- ],
- :callbacks => {},
- :ignore => [],
- :replace => {},
- # Let's assume we don't change delimiters within usual sql scripts
- :strip_delimiter => lambda { |obj, stmt| stmt.sub(/\A;+/, '').sub(/;+\Z/, '') }
- },
+ if !esql.empty?
+ process.call
+ end
- :mysql => {
- :delimiter => /;+|delimiter\s+\S+/i,
- :blocks => {
- /`/ => /`/,
- /"/ => /"/,
- /'/ => /'/,
- /\/\*[^+]/ => /\*\//,
- /--+/ => $/,
- },
- :nesting_blocks => {
- /\bbegin\b/i => /\bend\b/i
- },
- :nesting_context => [
- /\A\s*(begin|create\b[^;]+?\b(procedure|function|trigger))\b/im
- ],
- # We need to change delimiter on `delimiter' command
- :callbacks => {
- /^\s*delimiter\s+(\S+)/i => lambda { |obj, stmt, md|
- new_delimiter = Regexp.new(Regexp.escape md[1])
- obj.delimiter = /(#{new_delimiter})+|delimiter\s+\S+/i
- obj.delimiter_string = md[1]
- }
- },
- :ignore => [
- /^delimiter\s+\S+$/i
- ],
- :replace => {},
- :strip_delimiter => lambda { |obj, stmt|
- stmt.gsub(/(#{Regexp.escape(obj.delimiter_string || ';')})+\Z/, '')
- }
- },
+ if sql = result[:leftover]
+ if block_given?
+ yield sql
+ else
+ ret << sql
+ end
+ end
- :oracle => {
- :delimiter => /;+/,
- :blocks => {
- /`/ => /`/,
- /"/ => /"/,
- /'/ => /'/,
- /\/\*[^+]/ => /\*\//,
- /--+/ => $/,
- },
- :nesting_blocks => {
- /\bbegin\b/i => /\bend\b/i,
- /\bdeclare.*?;\s*?begin\b/im => {
- :closer => %r{;\s*/}m,
- # Stops immediately
- :pop => true
- },
- /\bcreate[^;]+?\b(procedure|function|trigger|package)\b/im => {
- :closer => %r{;\s*/}m,
- # Stops immediately
- :pop => true
- }
- },
- :nesting_context => [
- /\A\s*(\/\s*)*(begin|declare|create\b[^;]+?\b(procedure|function|trigger|package))\b/im
- ],
- :callbacks => {
- /\Abegin\b/ => lambda { |obj, stmt, md|
- # Oracle needs this
- stmt << ';' if stmt !~ /;\Z/
- }
- },
- :ignore => [],
- :replace => { %r[\A/] => '' },
- :strip_delimiter => lambda { |obj, stmt|
- stmt.gsub(/(#{stmt =~ /;\s*\// ? '/' : ';'})+\Z/, '')
- }
- }
- }
- Defaults[:plsql] = Defaults[:oracle] # alias
-
- # Freeze the Hash
- Defaults.freeze
+ ret
end