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.



366
367
368
369
370
371
372
373
374
# File 'lib/sequel/extensions/pg_array.rb', line 366

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.



360
361
362
# File 'lib/sequel/extensions/pg_array.rb', line 360

def pos
  @pos
end

Instance Method Details

#new_entry(include_empty = false) ⇒ Object



395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/sequel/extensions/pg_array.rb', line 395

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



378
379
380
381
382
383
384
385
386
# File 'lib/sequel/extensions/pg_array.rb', line 378

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:



410
411
412
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
# File 'lib/sequel/extensions/pg_array.rb', line 410

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



389
390
391
# File 'lib/sequel/extensions/pg_array.rb', line 389

def record(c)
  @recorded << c
end