Class Sequel::Postgres::PGArray::Parser
In: lib/sequel/extensions/pg_array.rb
Parent: StringScanner

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.

Methods

new   new_entry   parse  

Constants

UNQUOTED_RE = /[{}",]|[^{}",]+/
QUOTED_RE = /["\\]|[^"\\]+/
NULL_RE = /NULL",/
OPEN_RE = /((\[\d+:\d+\])+=)?\{/

Public Class methods

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.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 351
351:         def initialize(source, converter=nil)
352:           super(source)
353:           @converter = converter 
354:           @stack = [[]]
355:           @recorded = String.new
356:         end

Public Instance methods

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

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 360
360:         def new_entry(include_empty=false)
361:           if !@recorded.empty? || include_empty
362:             entry = @recorded
363:             if entry == NULL && !include_empty
364:               entry = nil
365:             elsif @converter
366:               entry = @converter.call(entry)
367:             end
368:             @stack.last.push(entry)
369:             @recorded = String.new
370:           end
371:         end

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

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 375
375:         def parse
376:           raise Sequel::Error, "invalid array, empty string" if eos?
377:           raise Sequel::Error, "invalid array, doesn't start with {" unless scan(OPEN_RE)
378: 
379:           while !eos?
380:             char = scan(UNQUOTED_RE)
381:             if char == COMMA
382:               # Comma outside quoted string indicates end of current entry
383:               new_entry
384:             elsif char == QUOTE
385:               raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty?
386:               while true
387:                 char = scan(QUOTED_RE)
388:                 if char == BACKSLASH
389:                   @recorded << getch
390:                 elsif char == QUOTE
391:                   n = peek(1)
392:                   raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == COMMA || n == CLOSE_BRACE
393:                   break
394:                 else
395:                   @recorded << char
396:                 end
397:               end
398:               new_entry(true)
399:             elsif char == OPEN_BRACE
400:               raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?
401: 
402:               # Start of new array, add it to the stack
403:               new = []
404:               @stack.last << new
405:               @stack << new
406:             elsif char == CLOSE_BRACE
407:               # End of current array, add current entry to the current array
408:               new_entry
409: 
410:               if @stack.length == 1
411:                 raise Sequel::Error, "array parsing finished without parsing entire string" unless eos?
412: 
413:                 # Top level of array, parsing should be over.
414:                 # Pop current array off stack and return it as result
415:                 return @stack.pop
416:               else
417:                 # Nested array, pop current array off stack
418:                 @stack.pop
419:               end
420:             else
421:               # Add the character to the recorded character buffer.
422:               @recorded << char
423:             end
424:           end
425: 
426:           raise Sequel::Error, "array parsing finished with array unclosed"
427:         end

[Validate]