1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
require_relative "spec_helper"
begin
require 'active_support'
require 'active_support/duration'
begin
require 'active_support/gem_version'
rescue LoadError
end
begin
require 'active_support/version'
rescue LoadError
end
rescue LoadError
warn "Skipping test of pg_interval plugin: can't load active_support/duration"
else
describe "pg_interval extension" do
before do
@db = Sequel.connect('mock://postgres')
@db.extend_datasets{def quote_identifiers?; false end}
@db.extension(:pg_array, :pg_interval)
end
it "should literalize ActiveSupport::Duration instances to strings correctly" do
@db.literal(ActiveSupport::Duration.new(0, [])).must_equal "'0'::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 0]])).must_equal "'0'::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 10], [:minutes, 20], [:days, 3], [:months, 4], [:years, 6]])).must_equal "'6 years 4 months 3 days 20 minutes 10 seconds '::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 10], [:minutes, 20], [:hours, 8], [:days, 3], [:weeks, 2], [:months, 4], [:years, 6]])).must_equal "'6 years 4 months 2 weeks 3 days 8 hours 20 minutes 10 seconds '::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]])).must_equal "'-6 years -4 months -3 days -20 minutes -10.000001 seconds '::interval"
end
it "should literalize ActiveSupport::Duration instances with repeated parts correctly" do
if defined?(ActiveSupport::VERSION::STRING) && ActiveSupport::VERSION::STRING >= '5.1' && ActiveSupport::VERSION::STRING < '6.1'
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1]])).must_equal "'1 seconds '::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1], [:days, 1], [:days, 4]])).must_equal "'4 days 1 seconds '::interval"
else
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1]])).must_equal "'3 seconds '::interval"
@db.literal(ActiveSupport::Duration.new(0, [[:seconds, 2], [:seconds, 1], [:days, 1], [:days, 4]])).must_equal "'5 days 3 seconds '::interval"
end
end
it "should set up conversion procs correctly" do
cp = @db.conversion_procs
cp[1186].call("1 sec").must_equal ActiveSupport::Duration.new(1, [[:seconds, 1]])
end
it "should set up conversion procs for arrays correctly" do
cp = @db.conversion_procs
cp[1187].call("{1 sec}").must_equal [ActiveSupport::Duration.new(1, [[:seconds, 1]])]
end
it "should setup conversion proc without array conversion proc if pg_array extension is not loaded" do
@db = Sequel.connect('mock://postgres')
@db.extension(:pg_interval, :pg_array)
cp = @db.conversion_procs
cp[1186].call("1 sec").must_equal ActiveSupport::Duration.new(1, [[:seconds, 1]])
cp[1187].must_be_nil
end
it "should not affect literalization of custom objects" do
o = Object.new
def o.sql_literal(ds) 'v' end
@db.literal(o).must_equal 'v'
end
it "should support using ActiveSupport::Duration instances as bound variables" do
@db.bound_variable_arg(1, nil).must_equal 1
@db.bound_variable_arg(ActiveSupport::Duration.new(0, [[:seconds, 0]]), nil).must_equal '0'
@db.bound_variable_arg(ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]]), nil).must_equal '-6 years -4 months -3 days -20 minutes -10.000001 seconds '
end
it "should support using ActiveSupport::Duration instances in array types in bound variables" do
@db.bound_variable_arg(Sequel.pg_array([ActiveSupport::Duration.new(0, [[:seconds, 0]])]), nil).must_equal '{"0"}'
@db.bound_variable_arg(Sequel.pg_array([ActiveSupport::Duration.new(0, [[:seconds, -10.000001], [:minutes, -20], [:days, -3], [:months, -4], [:years, -6]])]), nil).must_equal '{"-6 years -4 months -3 days -20 minutes -10.000001 seconds "}'
end
it "should parse interval type from the schema correctly" do
@db.fetch = [{:name=>'id', :db_type=>'integer'}, {:name=>'i', :db_type=>'interval'}]
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :interval]
end
it "should set :ruby_default schema entries if default value is recognized" do
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'t', :db_type=>'interval', :default=>"'3 days'::interval"}]
s = @db.schema(:items)
s[1][1][:ruby_default].must_equal ActiveSupport::Duration.new(3*86400, :days=>3)
end
it "should automatically parameterize pg_interval values" do
@db.extension :pg_auto_parameterize
v = ActiveSupport::Duration.new(3*86400, :days=>3)
sql = @db[:table].insert_sql(v)
sql.must_equal 'INSERT INTO table VALUES ($1::interval)'
sql.args.length.must_equal 1
sql.args[0].must_equal v
end
it "should automatically parameterize pg_interval values when loading pg_inet after" do
@db.extension :pg_auto_parameterize, :pg_inet
v = ActiveSupport::Duration.new(3*86400, :days=>3)
sql = @db[:table].insert_sql(v)
sql.must_equal 'INSERT INTO table VALUES ($1::interval)'
sql.args.length.must_equal 1
sql.args[0].must_equal v
end
it "should support typecasting for the interval type" do
m = Sequel::Postgres::IntervalDatabaseMethods::Parser
seconds = m::SECONDS_PER_YEAR + 2*m::SECONDS_PER_MONTH + 3*86400*7 + 4*86400 + 5*3600 + 6*60 + 7
parts = {:years => 1, :months => 2, :days => 25, :seconds => 18367}
if !defined?(ActiveSupport::VERSION::STRING) || ActiveSupport::VERSION::STRING < '5.1'
parts = parts.to_a
end
d = ActiveSupport::Duration.new(seconds, parts)
@db.typecast_value(:interval, d).object_id.must_equal d.object_id
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").is_a?(ActiveSupport::Duration).must_equal true
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").must_equal d
@db.typecast_value(:interval, "1 year 2 mons 25 days -05:06:07").is_a?(ActiveSupport::Duration).must_equal true
@db.typecast_value(:interval, "1 year 2 mons 25 days -05:06:07").must_equal(d-10*3600-12*60-14)
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07").parts.sort_by{|k,v| k.to_s}.must_equal d.parts.sort_by{|k,v| k.to_s}
@db.typecast_value(:interval, "1 year 2 mons 25 days 05:06:07.0").parts.sort_by{|k,v| k.to_s}.must_equal d.parts.sort_by{|k,v| k.to_s}
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins").is_a?(ActiveSupport::Duration).must_equal true
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins").must_equal(d-7)
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").is_a?(ActiveSupport::Duration).must_equal true
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").must_equal d
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7 secs").parts.sort_by{|k,v| k.to_s}.must_equal d.parts.sort_by{|k,v| k.to_s}
@db.typecast_value(:interval, "1 year 2 mons 25 days 5 hours 6 mins 7.0 secs").parts.sort_by{|k,v| k.to_s}.must_equal d.parts.sort_by{|k,v| k.to_s}
d2 = ActiveSupport::Duration.new(1, [[:seconds, 1]])
@db.typecast_value(:interval, 1).is_a?(ActiveSupport::Duration).must_equal true
@db.typecast_value(:interval, 1).must_equal d2
@db.typecast_value(:interval, 1).parts.sort_by{|k,v| k.to_s}.must_equal d2.parts.sort_by{|k,v| k.to_s}
proc{@db.typecast_value(:interval, 'foo')}.must_raise(Sequel::InvalidValue)
proc{@db.typecast_value(:interval, Object.new)}.must_raise(Sequel::InvalidValue)
proc{@db.typecast_value(:interval, '1'*1000+' secs')}.must_raise(Sequel::InvalidValue)
@db.check_string_typecast_bytesize = false
@db.typecast_value(:interval, '1'*1000+' secs').must_be_kind_of ActiveSupport::Duration
end
it "should return correct results for Database#schema_type_class" do
@db.schema_type_class(:interval).must_equal ActiveSupport::Duration
@db.schema_type_class(:integer).must_equal Integer
end
end
end
|