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

PostgreSQL array parser that handles all types of input.

This parser is very simple and unoptimized, but should still be O(n) where n is the length of the input string.

Methods

new   new_entry   next_char   parse   record  

Attributes

pos  [R]  Current position in the input string.

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 364
364:         def initialize(source, converter=nil)
365:           @source = source
366:           @source_length = source.length
367:           @converter = converter 
368:           @pos = -1
369:           @entries = []
370:           @recorded = ""
371:           @dimension = 0
372:         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 393
393:         def new_entry(include_empty=false)
394:           if !@recorded.empty? || include_empty
395:             entry = @recorded
396:             if entry == NULL && !include_empty
397:               entry = nil
398:             elsif @converter
399:               entry = @converter.call(entry)
400:             end
401:             @entries.push(entry)
402:             @recorded = ""
403:           end
404:         end

Return 2 objects, whether the next character in the input was escaped with a backslash, and what the next character is.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 376
376:         def next_char
377:           @pos += 1
378:           if (c = @source[@pos..@pos]) == BACKSLASH
379:             @pos += 1
380:             [true, @source[@pos..@pos]]
381:           else
382:             [false, c]
383:           end
384:         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 408
408:         def parse(nested=false)
409:           # quote sets whether we are inside of a quoted string.
410:           quote = false
411:           until @pos >= @source_length
412:             escaped, char = next_char
413:             if char == OPEN_BRACE && !quote
414:               @dimension += 1
415:               if (@dimension > 1)
416:                 # Multi-dimensional array encounter, use a subparser
417:                 # to parse the next level down.
418:                 subparser = self.class.new(@source[@pos..-1], @converter)
419:                 @entries.push(subparser.parse(true))
420:                 @pos += subparser.pos - 1
421:               end
422:             elsif char == CLOSE_BRACE && !quote
423:               @dimension -= 1
424:               if (@dimension == 0)
425:                 new_entry
426:                 # Exit early if inside a subparser, since the
427:                 # text after parsing the current level should be
428:                 # ignored as it is handled by the parent parser.
429:                 return @entries if nested
430:               end
431:             elsif char == QUOTE && !escaped
432:               # If already inside the quoted string, this is the
433:               # ending quote, so add the entry.  Otherwise, this
434:               # is the opening quote, so set the quote flag.
435:               new_entry(true) if quote
436:               quote = !quote
437:             elsif char == COMMA && !quote
438:               # If not inside a string and a comma occurs, it indicates
439:               # the end of the entry, so add the entry.
440:               new_entry
441:             else
442:               # Add the character to the recorded character buffer.
443:               record(char)
444:             end
445:           end
446:           raise Sequel::Error, "array dimensions not balanced" unless @dimension == 0
447:           @entries
448:         end

Add a new character to the buffer of recorded characters.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 387
387:         def record(c)
388:           @recorded << c
389:         end

[Validate]