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.
UNQUOTED_RE | = | /[{}",]|[^{}",]+/ |
QUOTED_RE | = | /["\\]|[^"\\]+/ |
NULL_RE | = | /NULL",/ |
OPEN_RE | = | /\{/ |
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.
# File lib/sequel/extensions/pg_array.rb, line 343 343: def initialize(source, converter=nil) 344: super(source) 345: @converter = converter 346: @stack = [[]] 347: @recorded = "" 348: end
Take the buffer of recorded characters and add it to the array of entries, and use a new buffer for recorded characters.
# File lib/sequel/extensions/pg_array.rb, line 352 352: def new_entry(include_empty=false) 353: if !@recorded.empty? || include_empty 354: entry = @recorded 355: if entry == NULL && !include_empty 356: entry = nil 357: elsif @converter 358: entry = @converter.call(entry) 359: end 360: @stack.last.push(entry) 361: @recorded = "" 362: end 363: end
Parse the input character by character, returning an array of parsed (and potentially converted) objects.
# File lib/sequel/extensions/pg_array.rb, line 367 367: def parse 368: raise Sequel::Error, "invalid array, empty string" if eos? 369: raise Sequel::Error, "invalid array, doesn't start with {" unless scan(OPEN_RE) 370: 371: while !eos? 372: char = scan(UNQUOTED_RE) 373: if char == COMMA 374: # Comma outside quoted string indicates end of current entry 375: new_entry 376: elsif char == QUOTE 377: raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty? 378: while true 379: char = scan(QUOTED_RE) 380: if char == BACKSLASH 381: @recorded << getch 382: elsif char == QUOTE 383: n = peek(1) 384: raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == COMMA || n == CLOSE_BRACE 385: break 386: else 387: @recorded << char 388: end 389: end 390: new_entry(true) 391: elsif char == OPEN_BRACE 392: raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty? 393: 394: # Start of new array, add it to the stack 395: new = [] 396: @stack.last << new 397: @stack << new 398: elsif char == CLOSE_BRACE 399: # End of current array, add current entry to the current array 400: new_entry 401: 402: if @stack.length == 1 403: raise Sequel::Error, "array parsing finished without parsing entire string" unless eos? 404: 405: # Top level of array, parsing should be over. 406: # Pop current array off stack and return it as result 407: return @stack.pop 408: else 409: # Nested array, pop current array off stack 410: @stack.pop 411: end 412: else 413: # Add the character to the recorded character buffer. 414: @recorded << char 415: end 416: end 417: 418: raise Sequel::Error, "array parsing finished with array unclosed" 419: end