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