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.

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
334 def initialize(source, converter=nil)
335   super(source)
336   @converter = converter 
337   @stack = [[]]
338   @encoding = string.encoding
339   @recorded = String.new.force_encoding(@encoding)
340 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
344 def new_entry(include_empty=false)
345   if !@recorded.empty? || include_empty
346     entry = @recorded
347     if entry == 'NULL' && !include_empty
348       entry = nil
349     elsif @converter
350       entry = @converter.call(entry)
351     end
352     @stack.last.push(entry)
353     @recorded = String.new.force_encoding(@encoding)
354   end
355 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
359 def parse
360   raise Sequel::Error, "invalid array, empty string" if eos?
361   raise Sequel::Error, "invalid array, doesn't start with {" unless scan(/((\[\d+:\d+\])+=)?\{/)
362 
363   # :nocov:
364   while !eos?
365   # :nocov:
366     char = scan(/[{}",]|[^{}",]+/)
367     if char == ','
368       # Comma outside quoted string indicates end of current entry
369       new_entry
370     elsif char == '"'
371       raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty?
372       # :nocov:
373       while true
374       # :nocov:
375         char = scan(/["\\]|[^"\\]+/)
376         if char == '\\'
377           @recorded << getch
378         elsif char == '"'
379           n = peek(1)
380           raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == ',' || n == '}'
381           break
382         else
383           @recorded << char
384         end
385       end
386       new_entry(true)
387     elsif char == '{'
388       raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?
389 
390       # Start of new array, add it to the stack
391       new = []
392       @stack.last << new
393       @stack << new
394     elsif char == '}'
395       # End of current array, add current entry to the current array
396       new_entry
397 
398       if @stack.length == 1
399         raise Sequel::Error, "array parsing finished without parsing entire string" unless eos?
400 
401         # Top level of array, parsing should be over.
402         # Pop current array off stack and return it as result
403         return @stack.pop
404       else
405         # Nested array, pop current array off stack
406         @stack.pop
407       end
408     else
409       # Add the character to the recorded character buffer.
410       @recorded << char
411     end
412   end
413 
414   raise Sequel::Error, "array parsing finished with array unclosed"
415 end