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  

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

[Validate]