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