class Sequel::Postgres::PGArray::Parser

PostgreSQL array parser that handles PostgreSQL array output format. Note that does not handle all forms out input that PostgreSQL will accept, and it will not raise an error for all forms of invalid input.

Constants

NULL_RE
OPEN_RE
QUOTED_RE
UNQUOTED_RE

Public Class Methods

new(source, converter=nil) click to toggle source

Set the source for the input, and any converter callable to call with objects to be created. For nested parsers the source may contain text after the end current parse, which will be ignored.

Calls superclass method
# File lib/sequel/extensions/pg_array.rb, line 357
def initialize(source, converter=nil)
  super(source)
  @converter = converter 
  @stack = [[]]
  @recorded = String.new
end

Public Instance Methods

new_entry(include_empty=false) click to toggle source

Take the buffer of recorded characters and add it to the array of entries, and use a new buffer for recorded characters.

# File lib/sequel/extensions/pg_array.rb, line 366
def new_entry(include_empty=false)
  if !@recorded.empty? || include_empty
    entry = @recorded
    if entry == NULL && !include_empty
      entry = nil
    elsif @converter
      entry = @converter.call(entry)
    end
    @stack.last.push(entry)
    @recorded = String.new
  end
end
parse() click to toggle source

Parse the input character by character, returning an array of parsed (and potentially converted) objects.

# File lib/sequel/extensions/pg_array.rb, line 381
def parse
  raise Sequel::Error, "invalid array, empty string" if eos?
  raise Sequel::Error, "invalid array, doesn't start with {" unless scan(OPEN_RE)

  while !eos?
    char = scan(UNQUOTED_RE)
    if char == COMMA
      # Comma outside quoted string indicates end of current entry
      new_entry
    elsif char == QUOTE
      raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty?
      while true
        char = scan(QUOTED_RE)
        if char == BACKSLASH
          @recorded << getch
        elsif char == QUOTE
          n = peek(1)
          raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == COMMA || n == CLOSE_BRACE
          break
        else
          @recorded << char
        end
      end
      new_entry(true)
    elsif char == OPEN_BRACE
      raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?

      # Start of new array, add it to the stack
      new = []
      @stack.last << new
      @stack << new
    elsif char == CLOSE_BRACE
      # End of current array, add current entry to the current array
      new_entry

      if @stack.length == 1
        raise Sequel::Error, "array parsing finished without parsing entire string" unless eos?

        # Top level of array, parsing should be over.
        # Pop current array off stack and return it as result
        return @stack.pop
      else
        # Nested array, pop current array off stack
        @stack.pop
      end
    else
      # Add the character to the recorded character buffer.
      @recorded << char
    end
  end

  raise Sequel::Error, "array parsing finished with array unclosed"
end