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