Class: Sequel::Postgres::PGArray::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/sequel/extensions/pg_array.rb

Overview

PostgreSQL array parser that handles all types of input.

This parser is very simple and unoptimized, but should still be O(n) where n is the length of the input string.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, converter = nil) ⇒ Parser

Returns a new instance of Parser.



369
370
371
372
373
374
375
376
377
# File 'lib/sequel/extensions/pg_array.rb', line 369

def initialize(source, converter=nil)
  @source = source
  @source_length = source.length
  @converter = converter 
  @pos = -1
  @entries = []
  @recorded = ""
  @dimension = 0
end

Instance Attribute Details

#posObject (readonly)

Returns the value of attribute pos.



363
364
365
# File 'lib/sequel/extensions/pg_array.rb', line 363

def pos
  @pos
end

Instance Method Details

#new_entry(include_empty = false) ⇒ Object



398
399
400
401
402
403
404
405
406
407
408
409
# File 'lib/sequel/extensions/pg_array.rb', line 398

def new_entry(include_empty=false)
  if !@recorded.empty? || include_empty
    entry = @recorded
    if entry == NULL && !include_empty
      entry = nil
    elsif @converter
      entry = @converter.call(entry)
    end
    @entries.push(entry)
    @recorded = ""
  end
end

#next_charObject



381
382
383
384
385
386
387
388
389
# File 'lib/sequel/extensions/pg_array.rb', line 381

def next_char
  @pos += 1
  if (c = @source[@pos..@pos]) == BACKSLASH
    @pos += 1
    [true, @source[@pos..@pos]]
  else
    [false, c]
  end
end

#parse(nested = false) ⇒ Object

Raises:



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/sequel/extensions/pg_array.rb', line 413

def parse(nested=false)
  # quote sets whether we are inside of a quoted string.
  quote = false
  until @pos >= @source_length
    escaped, char = next_char
    if char == OPEN_BRACE && !quote
      @dimension += 1
      if (@dimension > 1)
        # Multi-dimensional array encounter, use a subparser
        # to parse the next level down.
        subparser = self.class.new(@source[@pos..-1], @converter)
        @entries.push(subparser.parse(true))
        @pos += subparser.pos - 1
      end
    elsif char == CLOSE_BRACE && !quote
      @dimension -= 1
      if (@dimension == 0)
        new_entry
        # Exit early if inside a subparser, since the
        # text after parsing the current level should be
        # ignored as it is handled by the parent parser.
        return @entries if nested
      end
    elsif char == QUOTE && !escaped
      # If already inside the quoted string, this is the
      # ending quote, so add the entry.  Otherwise, this
      # is the opening quote, so set the quote flag.
      new_entry(true) if quote
      quote = !quote
    elsif char == COMMA && !quote
      # If not inside a string and a comma occurs, it indicates
      # the end of the entry, so add the entry.
      new_entry
    else
      # Add the character to the recorded character buffer.
      record(char)
    end
  end
  raise Sequel::Error, "array dimensions not balanced" unless @dimension == 0
  @entries
end

#record(c) ⇒ Object



392
393
394
# File 'lib/sequel/extensions/pg_array.rb', line 392

def record(c)
  @recorded << c
end