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