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 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

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

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 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

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]