Class Sequel::Postgres::PGArray::Parser
In: lib/sequel/extensions/pg_array.rb
Parent: Object

PostgreSQL array parser that handles both text and numeric input. Because PostgreSQL arrays can contain objects that can be literalized in any number of ways, it is not possible to make a fully generic parser.

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

Methods

new   new_entry   next_char   parse   record  

Attributes

pos  [R] 

Public Class methods

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.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 187
187:         def initialize(source, converter=nil)
188:           @source = source
189:           @source_length = source.length
190:           @converter = converter 
191:           @pos = -1
192:           @entries = []
193:           @recorded = ""
194:           @dimension = 0
195:         end

Public Instance methods

Take the buffer of recorded characters and add it to the array of entries, and use a new buffer for recorded characters.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 216
216:         def new_entry(include_empty=false)
217:           if !@recorded.empty? || include_empty
218:             entry = @recorded
219:             if entry == NULL && !include_empty
220:               entry = nil
221:             elsif @converter
222:               entry = @converter.call(entry)
223:             end
224:             @entries.push(entry)
225:             @recorded = ""
226:           end
227:         end

Return 2 objects, whether the next character in the input was escaped with a backslash, and what the next character is.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 199
199:         def next_char
200:           @pos += 1
201:           if (c = @source[@pos..@pos]) == BACKSLASH
202:             @pos += 1
203:             [true, @source[@pos..@pos]]
204:           else
205:             [false, c]
206:           end
207:         end

Parse the input character by character, returning an array of parsed (and potentially converted) objects.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 231
231:         def parse(nested=false)
232:           # quote sets whether we are inside of a quoted string.
233:           quote = false
234:           until @pos >= @source_length
235:             escaped, char = next_char
236:             if char == OPEN_BRACE && !quote
237:               @dimension += 1
238:               if (@dimension > 1)
239:                 # Multi-dimensional array encounter, use a subparser
240:                 # to parse the next level down.
241:                 subparser = self.class.new(@source[@pos..-1], @converter)
242:                 @entries.push(subparser.parse(true))
243:                 @pos += subparser.pos - 1
244:               end
245:             elsif char == CLOSE_BRACE && !quote
246:               @dimension -= 1
247:               if (@dimension == 0)
248:                 new_entry
249:                 # Exit early if inside a subparser, since the
250:                 # text after parsing the current level should be
251:                 # ignored as it is handled by the parent parser.
252:                 return @entries if nested
253:               end
254:             elsif char == QUOTE && !escaped
255:               # If already inside the quoted string, this is the
256:               # ending quote, so add the entry.  Otherwise, this
257:               # is the opening quote, so set the quote flag.
258:               new_entry(true) if quote
259:               quote = !quote
260:             elsif char == COMMA && !quote
261:               # If not inside a string and a comma occurs, it indicates
262:               # the end of the entry, so add the entry.
263:               new_entry
264:             else
265:               # Add the character to the recorded character buffer.
266:               record(char)
267:             end
268:           end
269:           raise Sequel::Error, "array dimensions not balanced" unless @dimension == 0
270:           @entries
271:         end

Add a new character to the buffer of recorded characters.

[Source]

     # File lib/sequel/extensions/pg_array.rb, line 210
210:         def record(c)
211:           @recorded << c
212:         end

[Validate]