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

new(source, converter=nil)

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 299
    299:         def initialize(source, converter=nil)
    300:           @source = source
    301:           @source_length = source.length
    302:           @converter = converter
    303:           @pos = -1
    304:           @entries = []
    305:           @recorded = ""
    306:           @dimension = 0
    307:         end

### Public Instance methods

new_entry(include_empty=false)

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 328
    328:         def new_entry(include_empty=false)
    329:           if !@recorded.empty? || include_empty
    330:             entry = @recorded
    331:             if entry == NULL && !include_empty
    332:               entry = nil
    333:             elsif @converter
    334:               entry = @converter.call(entry)
    335:             end
    336:             @entries.push(entry)
    337:             @recorded = ""
    338:           end
    339:         end

next_char()

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 311
    311:         def next_char
    312:           @pos += 1
    313:           if (c = @source[@pos..@pos]) == BACKSLASH
    314:             @pos += 1
    315:             [true, @source[@pos..@pos]]
    316:           else
    317:             [false, c]
    318:           end
    319:         end

parse(nested=false)

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

[Source]

         # File lib/sequel/extensions/pg_array.rb, line 343
    343:         def parse(nested=false)
    344:           # quote sets whether we are inside of a quoted string.
    345:           quote = false
    346:           until @pos >= @source_length
    347:             escaped, char = next_char
    348:             if char == OPEN_BRACE && !quote
    349:               @dimension += 1
    350:               if (@dimension > 1)
    351:                 # Multi-dimensional array encounter, use a subparser
    352:                 # to parse the next level down.
    353:                 subparser = self.class.new(@source[@pos..-1], @converter)
    354:                 @entries.push(subparser.parse(true))
    355:                 @pos += subparser.pos - 1
    356:               end
    357:             elsif char == CLOSE_BRACE && !quote
    358:               @dimension -= 1
    359:               if (@dimension == 0)
    360:                 new_entry
    361:                 # Exit early if inside a subparser, since the
    362:                 # text after parsing the current level should be
    363:                 # ignored as it is handled by the parent parser.
    364:                 return @entries if nested
    365:               end
    366:             elsif char == QUOTE && !escaped
    367:               # If already inside the quoted string, this is the
    368:               # ending quote, so add the entry.  Otherwise, this
    369:               # is the opening quote, so set the quote flag.
    370:               new_entry(true) if quote
    371:               quote = !quote
    372:             elsif char == COMMA && !quote
    373:               # If not inside a string and a comma occurs, it indicates
    374:               # the end of the entry, so add the entry.
    375:               new_entry
    376:             else
    377:               # Add the character to the recorded character buffer.
    378:               record(char)
    379:             end
    380:           end
    381:           raise Sequel::Error, "array dimensions not balanced" unless @dimension == 0
    382:           @entries
    383:         end

record(c)

Add a new character to the buffer of recorded characters.

[Source]

         # File lib/sequel/extensions/pg_array.rb, line 322
    322:         def record(c)
    323:           @recorded << c
    324:         end

[Validate]