class Sequel::Postgres::PGRange
Constants
- ENDLESS_RANGE_NOT_SUPPORTED
- STARTLESS_RANGE_NOT_SUPPORTED
Attributes
The beginning of the range. If nil, the range has an unbounded beginning.
The PostgreSQL database type for the range (e.g. 'int4range').
The end of the range. If nil, the range has an unbounded ending.
Public Class Methods
Create an empty PGRange
with the given database type.
# File lib/sequel/extensions/pg_range.rb 337 def self.empty(db_type=nil) 338 new(nil, nil, :empty=>true, :db_type=>db_type) 339 end
Initialize a new PGRange
instance. Accepts the following options:
- :db_type
-
The PostgreSQL database type for the range.
- :empty
-
Whether the range is empty (has no points)
- :exclude_begin
-
Whether the beginning element is excluded from the range.
- :exclude_end
-
Whether the ending element is excluded from the range.
# File lib/sequel/extensions/pg_range.rb 347 def initialize(beg, en, opts=OPTS) 348 @begin = beg 349 @end = en 350 @empty = !!opts[:empty] 351 @exclude_begin = !!opts[:exclude_begin] 352 @exclude_end = !!opts[:exclude_end] 353 @db_type = opts[:db_type] 354 if @empty 355 raise(Error, 'cannot have an empty range with either a beginning or ending') unless @begin.nil? && @end.nil? && opts[:exclude_begin].nil? && opts[:exclude_end].nil? 356 end 357 end
Public Instance Methods
Allow PGRange
values in case statements, where they return true if they are equal to each other using eql?, or if this PGRange
can be converted to a Range
, delegating to that range.
# File lib/sequel/extensions/pg_range.rb 417 def ===(other) 418 if eql?(other) 419 true 420 else 421 if valid_ruby_range? 422 to_range === other 423 else 424 false 425 end 426 end 427 end
Return whether the value is inside the range.
# File lib/sequel/extensions/pg_range.rb 366 def cover?(value) 367 return false if empty? 368 b = self.begin 369 return false if b && b.public_send(exclude_begin? ? :>= : :>, value) 370 e = self.end 371 return false if e && e.public_send(exclude_end? ? :<= : :<, value) 372 true 373 end
Whether this range is empty (has no points). Note that for manually created ranges (ones not retrieved from the database), this will only be true if the range was created using the :empty option.
# File lib/sequel/extensions/pg_range.rb 432 def empty? 433 @empty 434 end
Consider the receiver equal to other PGRange
instances with the same beginning, ending, exclusions, and database type. Also consider it equal to Range
instances if this PGRange
can be converted to a a Range
and those ranges are equal.
# File lib/sequel/extensions/pg_range.rb 379 def eql?(other) 380 case other 381 when PGRange 382 if db_type == other.db_type 383 if empty? 384 other.empty? 385 elsif other.empty? 386 false 387 else 388 [:@begin, :@end, :@exclude_begin, :@exclude_end].all?{|v| instance_variable_get(v) == other.instance_variable_get(v)} 389 end 390 else 391 false 392 end 393 when Range 394 if valid_ruby_range? 395 to_range.eql?(other) 396 else 397 false 398 end 399 else 400 false 401 end 402 end
Whether the beginning element is excluded from the range.
# File lib/sequel/extensions/pg_range.rb 437 def exclude_begin? 438 @exclude_begin 439 end
Whether the ending element is excluded from the range.
# File lib/sequel/extensions/pg_range.rb 442 def exclude_end? 443 @exclude_end 444 end
Make sure equal ranges have the same hash.
# File lib/sequel/extensions/pg_range.rb 406 def hash 407 if @empty 408 @db_type.hash 409 else 410 [@begin, @end, @exclude_begin, @exclude_end, @db_type].hash 411 end 412 end
Append a literalize version of the receiver to the sql.
# File lib/sequel/extensions/pg_range.rb 447 def sql_literal_append(ds, sql) 448 if (s = @db_type) && !empty? 449 sql << s.to_s << "(" 450 ds.literal_append(sql, self.begin) 451 sql << ',' 452 ds.literal_append(sql, self.end) 453 sql << ',' 454 ds.literal_append(sql, "#{exclude_begin? ? "(" : "["}#{exclude_end? ? ")" : "]"}") 455 sql << ")" 456 else 457 ds.literal_append(sql, unquoted_literal(ds)) 458 if s 459 sql << '::' << s.to_s 460 end 461 end 462 end
Return a ruby Range
object for this instance, if one can be created.
# File lib/sequel/extensions/pg_range.rb 468 def to_range 469 return @range if @range 470 raise(Error, "cannot create ruby range for an empty PostgreSQL range") if empty? 471 raise(Error, "cannot create ruby range when PostgreSQL range excludes beginning element") if exclude_begin? 472 raise(Error, "cannot create ruby range when PostgreSQL range has unbounded beginning") if STARTLESS_RANGE_NOT_SUPPORTED && !self.begin 473 raise(Error, "cannot create ruby range when PostgreSQL range has unbounded ending") if ENDLESS_RANGE_NOT_SUPPORTED && !self.end 474 @range = Range.new(self.begin, self.end, exclude_end?) 475 end
Whether the beginning of the range is unbounded.
# File lib/sequel/extensions/pg_range.rb 485 def unbounded_begin? 486 self.begin.nil? && !empty? 487 end
Whether the end of the range is unbounded.
# File lib/sequel/extensions/pg_range.rb 490 def unbounded_end? 491 self.end.nil? && !empty? 492 end
Return a string containing the unescaped version of the range. Separated out for use by the bound argument code.
# File lib/sequel/extensions/pg_range.rb 496 def unquoted_literal(ds) 497 if empty? 498 'empty' 499 else 500 "#{exclude_begin? ? "(" : "["}#{escape_value(self.begin, ds)},#{escape_value(self.end, ds)}#{exclude_end? ? ")" : "]"}" 501 end 502 end
Whether or not this PGRange
is a valid ruby range. In order to be a valid ruby range, it must have a beginning and an ending (no unbounded ranges), and it cannot exclude the beginning element.
# File lib/sequel/extensions/pg_range.rb 480 def valid_ruby_range? 481 !(empty? || exclude_begin? || (STARTLESS_RANGE_NOT_SUPPORTED && !self.begin) || (ENDLESS_RANGE_NOT_SUPPORTED && !self.end)) 482 end
Private Instance Methods
Escape common range types. Instead of quoting, just backslash escape all special characters.
# File lib/sequel/extensions/pg_range.rb 508 def escape_value(k, ds) 509 case k 510 when nil 511 '' 512 when Date, Time 513 ds.literal(k)[1...-1] 514 when Integer, Float 515 k.to_s 516 when BigDecimal 517 k.to_s('F') 518 when LiteralString 519 k 520 when String 521 if k.empty? 522 '""' 523 else 524 k.gsub(/("|,|\\|\[|\]|\(|\))/, '\\\\\1') 525 end 526 else 527 ds.literal(k).gsub(/("|,|\\|\[|\]|\(|\))/, '\\\\\1') 528 end 529 end