class Sequel::Postgres::PGArray::Parser
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.
Public Class Methods
new(source, converter=nil)
click to toggle source
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.
Calls superclass method
# File lib/sequel/extensions/pg_array.rb 314 def initialize(source, converter=nil) 315 super(source) 316 @converter = converter 317 @stack = [[]] 318 @encoding = string.encoding 319 @recorded = String.new.force_encoding(@encoding) 320 end
Public Instance Methods
new_entry(include_empty=false)
click to toggle source
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 324 def new_entry(include_empty=false) 325 if !@recorded.empty? || include_empty 326 entry = @recorded 327 if entry == 'NULL' && !include_empty 328 entry = nil 329 elsif @converter 330 entry = @converter.call(entry) 331 end 332 @stack.last.push(entry) 333 @recorded = String.new.force_encoding(@encoding) 334 end 335 end
parse()
click to toggle source
Parse the input character by character, returning an array of parsed (and potentially converted) objects.
# File lib/sequel/extensions/pg_array.rb 339 def parse 340 raise Sequel::Error, "invalid array, empty string" if eos? 341 raise Sequel::Error, "invalid array, doesn't start with {" unless scan(/((\[\d+:\d+\])+=)?\{/) 342 343 # :nocov: 344 while !eos? 345 # :nocov: 346 char = scan(/[{}",]|[^{}",]+/) 347 if char == ',' 348 # Comma outside quoted string indicates end of current entry 349 new_entry 350 elsif char == '"' 351 raise Sequel::Error, "invalid array, opening quote with existing recorded data" unless @recorded.empty? 352 # :nocov: 353 while true 354 # :nocov: 355 char = scan(/["\\]|[^"\\]+/) 356 if char == '\\' 357 @recorded << getch 358 elsif char == '"' 359 n = peek(1) 360 raise Sequel::Error, "invalid array, closing quote not followed by comma or closing brace" unless n == ',' || n == '}' 361 break 362 else 363 @recorded << char 364 end 365 end 366 new_entry(true) 367 elsif char == '{' 368 raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty? 369 370 # Start of new array, add it to the stack 371 new = [] 372 @stack.last << new 373 @stack << new 374 elsif char == '}' 375 # End of current array, add current entry to the current array 376 new_entry 377 378 if @stack.length == 1 379 raise Sequel::Error, "array parsing finished without parsing entire string" unless eos? 380 381 # Top level of array, parsing should be over. 382 # Pop current array off stack and return it as result 383 return @stack.pop 384 else 385 # Nested array, pop current array off stack 386 @stack.pop 387 end 388 else 389 # Add the character to the recorded character buffer. 390 @recorded << char 391 end 392 end 393 394 raise Sequel::Error, "array parsing finished with array unclosed" 395 end