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