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