sequel 5.8.0 → 5.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -0
- data/doc/release_notes/5.9.0.txt +99 -0
- data/doc/testing.rdoc +10 -10
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/amalgalite.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +19 -7
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -5
- data/lib/sequel/adapters/postgres.rb +3 -3
- data/lib/sequel/adapters/shared/access.rb +5 -6
- data/lib/sequel/adapters/shared/mysql.rb +28 -2
- data/lib/sequel/adapters/shared/postgres.rb +16 -6
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +2 -2
- data/lib/sequel/connection_pool.rb +2 -1
- data/lib/sequel/connection_pool/sharded_threaded.rb +12 -4
- data/lib/sequel/connection_pool/threaded.rb +19 -7
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/connecting.rb +6 -6
- data/lib/sequel/database/misc.rb +3 -3
- data/lib/sequel/database/query.rb +2 -2
- data/lib/sequel/database/schema_generator.rb +9 -3
- data/lib/sequel/database/schema_methods.rb +12 -5
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +4 -4
- data/lib/sequel/dataset/query.rb +5 -0
- data/lib/sequel/dataset/sql.rb +8 -6
- data/lib/sequel/extensions/escaped_like.rb +100 -0
- data/lib/sequel/extensions/eval_inspect.rb +3 -1
- data/lib/sequel/extensions/looser_typecasting.rb +3 -3
- data/lib/sequel/extensions/pg_extended_date_support.rb +23 -10
- data/lib/sequel/model/associations.rb +18 -4
- data/lib/sequel/model/base.rb +9 -2
- data/lib/sequel/plugins/defaults_setter.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +2 -2
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +5 -7
- data/lib/sequel/plugins/sharding.rb +2 -2
- data/lib/sequel/plugins/tactical_eager_loading.rb +1 -1
- data/lib/sequel/plugins/tree.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +4 -1
- data/spec/adapters/mysql_spec.rb +24 -0
- data/spec/adapters/postgres_spec.rb +9 -9
- data/spec/adapters/sqlite_spec.rb +10 -10
- data/spec/core/connection_pool_spec.rb +22 -0
- data/spec/core/database_spec.rb +6 -6
- data/spec/core/dataset_spec.rb +16 -5
- data/spec/core/expression_filters_spec.rb +1 -1
- data/spec/core/schema_spec.rb +1 -1
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/connection_expiration_spec.rb +20 -2
- data/spec/extensions/connection_validator_spec.rb +20 -3
- data/spec/extensions/escaped_like_spec.rb +40 -0
- data/spec/extensions/eval_inspect_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +6 -0
- data/spec/extensions/pg_array_spec.rb +13 -13
- data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -1
- data/spec/extensions/pg_range_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +2 -2
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +2 -2
- data/spec/extensions/validation_helpers_spec.rb +1 -1
- data/spec/integration/associations_test.rb +12 -0
- data/spec/integration/dataset_test.rb +21 -0
- data/spec/integration/type_test.rb +4 -4
- data/spec/model/base_spec.rb +9 -0
- data/spec/model/eager_loading_spec.rb +25 -0
- data/spec/model/record_spec.rb +1 -1
- metadata +6 -2
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe "escaped_like extension" do
|
4
|
+
before do
|
5
|
+
Sequel.extension(:escaped_like)
|
6
|
+
@ds = Sequel.mock[:t]
|
7
|
+
@c = Sequel[:c]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "escaped_like should support creating case sensitive pattern matches" do
|
11
|
+
@ds.where(@c.escaped_like('?', 'a')).sql.must_equal "SELECT * FROM t WHERE (c LIKE 'a' ESCAPE '\\')"
|
12
|
+
@ds.where(@c.escaped_like('?%', 'a')).sql.must_equal "SELECT * FROM t WHERE (c LIKE 'a%' ESCAPE '\\')"
|
13
|
+
@ds.where(@c.escaped_like('?', 'a%')).sql.must_equal "SELECT * FROM t WHERE (c LIKE 'a\\%' ESCAPE '\\')"
|
14
|
+
@ds.where(@c.escaped_like('?', ['a%'])).sql.must_equal "SELECT * FROM t WHERE (c LIKE 'a\\%' ESCAPE '\\')"
|
15
|
+
@ds.where(@c.escaped_like('??', ['a', '%'])).sql.must_equal "SELECT * FROM t WHERE (c LIKE 'a\\%' ESCAPE '\\')"
|
16
|
+
end
|
17
|
+
|
18
|
+
it "escaped_ilike should support creating case insensitive pattern matches" do
|
19
|
+
@ds.where(@c.escaped_ilike('?', 'a')).sql.must_equal "SELECT * FROM t WHERE (UPPER(c) LIKE UPPER('a') ESCAPE '\\')"
|
20
|
+
@ds.where(@c.escaped_ilike('?%', 'a')).sql.must_equal "SELECT * FROM t WHERE (UPPER(c) LIKE UPPER('a%') ESCAPE '\\')"
|
21
|
+
@ds.where(@c.escaped_ilike('?', 'a%')).sql.must_equal "SELECT * FROM t WHERE (UPPER(c) LIKE UPPER('a\\%') ESCAPE '\\')"
|
22
|
+
@ds.where(@c.escaped_ilike('?', ['a%'])).sql.must_equal "SELECT * FROM t WHERE (UPPER(c) LIKE UPPER('a\\%') ESCAPE '\\')"
|
23
|
+
@ds.where(@c.escaped_ilike('??', ['a', '%'])).sql.must_equal "SELECT * FROM t WHERE (UPPER(c) LIKE UPPER('a\\%') ESCAPE '\\')"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise an Error for a mismatched number of placeholders" do
|
27
|
+
proc{@ds.where(@c.escaped_like('?', [])).sql}.must_raise Sequel::Error
|
28
|
+
proc{@ds.where(@c.escaped_like('??', ['a'])).sql}.must_raise Sequel::Error
|
29
|
+
proc{@ds.where(@c.escaped_ilike('', ['a'])).sql}.must_raise Sequel::Error
|
30
|
+
proc{@ds.where(@c.escaped_ilike('?', ['a', 'a'])).sql}.must_raise Sequel::Error
|
31
|
+
end
|
32
|
+
|
33
|
+
it "escaped_like and escaped_ilike should return expressions" do
|
34
|
+
@ds.select(@c.escaped_like('?', 'a').as(:b)).sql.must_equal "SELECT (c LIKE 'a' ESCAPE '\\') AS b FROM t"
|
35
|
+
@ds.select(@c.escaped_like('?', 'a').cast(String)).sql.must_equal "SELECT CAST((c LIKE 'a' ESCAPE '\\') AS varchar(255)) FROM t"
|
36
|
+
@ds.order(@c.escaped_like('?', 'a').desc).sql.must_equal "SELECT * FROM t ORDER BY (c LIKE 'a' ESCAPE '\\') DESC"
|
37
|
+
@ds.where(@c.escaped_like('?', 'a') | @c.escaped_like('?', 'b')).sql.must_equal "SELECT * FROM t WHERE ((c LIKE 'a' ESCAPE '\\') OR (c LIKE 'b' ESCAPE '\\'))"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -62,7 +62,7 @@ describe "eval_inspect extension" do
|
|
62
62
|
Sequel::SQL::AliasedExpression.new(Time.local(2011, 9, 11, 10, 20, 30, 500000.125), :a),
|
63
63
|
Sequel::SQL::AliasedExpression.new(Time.utc(2011, 9, 11, 10, 20, 30), :a),
|
64
64
|
Sequel::SQL::AliasedExpression.new(Time.utc(2011, 9, 11, 10, 20, 30, 500000.125), :a),
|
65
|
-
Sequel::SQL::AliasedExpression.new(BigDecimal
|
65
|
+
Sequel::SQL::AliasedExpression.new(BigDecimal('1.000000000000000000000000000000000000000000000001'), :a),
|
66
66
|
Sequel::SQL::AliasedExpression.new(Sequel::CURRENT_DATE, :a),
|
67
67
|
Sequel::SQL::AliasedExpression.new(Sequel::CURRENT_TIMESTAMP, :a),
|
68
68
|
].each do |o|
|
@@ -49,6 +49,12 @@ describe "NestedAttributes plugin" do
|
|
49
49
|
@db.sqls
|
50
50
|
end
|
51
51
|
|
52
|
+
it "should not modify options hash when loading plugin" do
|
53
|
+
h = {}
|
54
|
+
@Concert.nested_attributes :albums, h
|
55
|
+
h.must_equal({})
|
56
|
+
end
|
57
|
+
|
52
58
|
it "should support creating new many_to_one objects" do
|
53
59
|
a = @Album.new({:name=>'Al', :artist_attributes=>{:name=>'Ar'}})
|
54
60
|
@db.sqls.must_equal []
|
@@ -92,30 +92,30 @@ describe "pg_array extension" do
|
|
92
92
|
it "should parse single dimensional decimal arrays" do
|
93
93
|
c = @converter[1231]
|
94
94
|
c.call("{}").to_a.must_equal []
|
95
|
-
c.call("{1.5}").to_a.must_equal [BigDecimal
|
96
|
-
c.call('{2.5,3.5}').to_a.must_equal [BigDecimal
|
97
|
-
c.call('{3.5,4.5,5.5}').to_a.must_equal [BigDecimal
|
95
|
+
c.call("{1.5}").to_a.must_equal [BigDecimal('1.5')]
|
96
|
+
c.call('{2.5,3.5}').to_a.must_equal [BigDecimal('2.5'), BigDecimal('3.5')]
|
97
|
+
c.call('{3.5,4.5,5.5}').to_a.must_equal [BigDecimal('3.5'), BigDecimal('4.5'), BigDecimal('5.5')]
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should parse multiple dimensional decimal arrays" do
|
101
101
|
c = @converter[1231]
|
102
102
|
c.call("{{}}").to_a.must_equal [[]]
|
103
|
-
c.call("{{1.5}}").to_a.must_equal [[BigDecimal
|
104
|
-
c.call('{{2.5},{3.5}}').to_a.must_equal [[BigDecimal
|
105
|
-
c.call('{{{1.5,2.5},{3.5,4.5}},{{5.5,6.5},{7.5,8.5}}}').to_a.must_equal [[[BigDecimal
|
103
|
+
c.call("{{1.5}}").to_a.must_equal [[BigDecimal('1.5')]]
|
104
|
+
c.call('{{2.5},{3.5}}').to_a.must_equal [[BigDecimal('2.5')], [BigDecimal('3.5')]]
|
105
|
+
c.call('{{{1.5,2.5},{3.5,4.5}},{{5.5,6.5},{7.5,8.5}}}').to_a.must_equal [[[BigDecimal('1.5'), BigDecimal('2.5')], [BigDecimal('3.5'), BigDecimal('4.5')]], [[BigDecimal('5.5'), BigDecimal('6.5')], [BigDecimal('7.5'), BigDecimal('8.5')]]]
|
106
106
|
end
|
107
107
|
|
108
108
|
it "should parse decimal values with arbitrary precision" do
|
109
109
|
c = @converter[1231]
|
110
|
-
c.call("{1.000000000000000000005}").to_a.must_equal [BigDecimal
|
111
|
-
c.call("{{1.000000000000000000005,2.000000000000000000005},{3.000000000000000000005,4.000000000000000000005}}").to_a.must_equal [[BigDecimal
|
110
|
+
c.call("{1.000000000000000000005}").to_a.must_equal [BigDecimal('1.000000000000000000005')]
|
111
|
+
c.call("{{1.000000000000000000005,2.000000000000000000005},{3.000000000000000000005,4.000000000000000000005}}").to_a.must_equal [[BigDecimal('1.000000000000000000005'), BigDecimal('2.000000000000000000005')], [BigDecimal('3.000000000000000000005'), BigDecimal('4.000000000000000000005')]]
|
112
112
|
end
|
113
113
|
|
114
114
|
it "should parse integers in decimal arrays as BigDecimals" do
|
115
115
|
c = @converter[1231]
|
116
116
|
c.call("{1}").to_a.first.must_be_kind_of(BigDecimal)
|
117
|
-
c.call("{1}").to_a.must_equal [BigDecimal
|
118
|
-
c.call('{{{1,2},{3,4}},{{5,6},{7,8}}}').to_a.must_equal [[[BigDecimal
|
117
|
+
c.call("{1}").to_a.must_equal [BigDecimal('1')]
|
118
|
+
c.call('{{{1,2},{3,4}},{{5,6},{7,8}}}').to_a.must_equal [[[BigDecimal('1'), BigDecimal('2')], [BigDecimal('3'), BigDecimal('4')]], [[BigDecimal('5'), BigDecimal('6')], [BigDecimal('7'), BigDecimal('8')]]]
|
119
119
|
end
|
120
120
|
|
121
121
|
it "should parse arrays with NULL values" do
|
@@ -149,7 +149,7 @@ describe "pg_array extension" do
|
|
149
149
|
@db.literal(@m::PGArray.new([nil])).must_equal 'ARRAY[NULL]'
|
150
150
|
@db.literal(@m::PGArray.new([nil, 1])).must_equal 'ARRAY[NULL,1]'
|
151
151
|
@db.literal(@m::PGArray.new([1.0, 2.5])).must_equal 'ARRAY[1.0,2.5]'
|
152
|
-
@db.literal(@m::PGArray.new([BigDecimal
|
152
|
+
@db.literal(@m::PGArray.new([BigDecimal('1'), BigDecimal('2.000000000000000000005')])).must_equal 'ARRAY[1.0,2.000000000000000000005]'
|
153
153
|
@db.literal(@m::PGArray.new([nil, "NULL"])).must_equal "ARRAY[NULL,'NULL']"
|
154
154
|
@db.literal(@m::PGArray.new([nil, "{},[]'\""])).must_equal "ARRAY[NULL,'{},[]''\"']"
|
155
155
|
end
|
@@ -169,7 +169,7 @@ describe "pg_array extension" do
|
|
169
169
|
@db.literal(@m::PGArray.new([nil], :text)).must_equal 'ARRAY[NULL]::text[]'
|
170
170
|
@db.literal(@m::PGArray.new([nil, 1], :int8)).must_equal 'ARRAY[NULL,1]::int8[]'
|
171
171
|
@db.literal(@m::PGArray.new([1.0, 2.5], :real)).must_equal 'ARRAY[1.0,2.5]::real[]'
|
172
|
-
@db.literal(@m::PGArray.new([BigDecimal
|
172
|
+
@db.literal(@m::PGArray.new([BigDecimal('1'), BigDecimal('2.000000000000000000005')], :decimal)).must_equal 'ARRAY[1.0,2.000000000000000000005]::decimal[]'
|
173
173
|
@db.literal(@m::PGArray.new([nil, "NULL"], :varchar)).must_equal "ARRAY[NULL,'NULL']::varchar[]"
|
174
174
|
@db.literal(@m::PGArray.new([nil, "{},[]'\""], :"varchar(255)")).must_equal "ARRAY[NULL,'{},[]''\"']::varchar(255)[]"
|
175
175
|
end
|
@@ -224,7 +224,7 @@ describe "pg_array extension" do
|
|
224
224
|
{
|
225
225
|
:integer=>{:class=>Integer, :convert=>['1', 1, '1']},
|
226
226
|
:float=>{:db_type=>'double precision', :class=>Float, :convert=>['1.1', 1.1, '1.1']},
|
227
|
-
:decimal=>{:db_type=>'numeric', :class=>BigDecimal, :convert=>['1.00000000000000000000000001', BigDecimal
|
227
|
+
:decimal=>{:db_type=>'numeric', :class=>BigDecimal, :convert=>['1.00000000000000000000000001', BigDecimal('1.00000000000000000000000001'), '1.00000000000000000000000001']},
|
228
228
|
:string=>{:db_type=>'text', :class=>String, :convert=>[1, '1', "'1'"]},
|
229
229
|
:bigint=>{:class=>Integer, :convert=>['1', 1, '1']},
|
230
230
|
:boolean=>{:class=>TrueClass, :convert=>['t', true, 'true']},
|
@@ -12,7 +12,6 @@ describe "pg_auto_constraint_validations plugin" do
|
|
12
12
|
|
13
13
|
before do
|
14
14
|
info = @info = {:schema=>'public', :table=>'items'}
|
15
|
-
error = @error = []
|
16
15
|
@db = Sequel.mock(:host=>'postgres')
|
17
16
|
def @db.schema(*) [[:i, {}], [:id, {}]] end
|
18
17
|
@set_error = lambda{|ec, ei| @db.fetch = @db.autoid = @db.numrows = ec; info.merge!(ei)}
|
@@ -43,7 +43,7 @@ describe "pg_range extension" do
|
|
43
43
|
@db.literal(DateTime.new(2011, 1, 2, 10, 20, 30)...DateTime.new(2011, 2, 3, 10, 20, 30)).must_equal "'[2011-01-02 10:20:30,2011-02-03 10:20:30)'"
|
44
44
|
@db.literal(1..2).must_equal "'[1,2]'"
|
45
45
|
@db.literal(1.0..2.0).must_equal "'[1.0,2.0]'"
|
46
|
-
@db.literal(BigDecimal
|
46
|
+
@db.literal(BigDecimal('1.0')..BigDecimal('2.0')).must_equal "'[1.0,2.0]'"
|
47
47
|
@db.literal(Sequel.lit('a')..Sequel.lit('z')).must_equal "'[a,z]'"
|
48
48
|
@db.literal(''..'()[]",\\2').must_equal "'[\"\",\\(\\)\\[\\]\\\"\\,\\\\2]'"
|
49
49
|
end
|
@@ -673,8 +673,8 @@ END_MIG
|
|
673
673
|
s
|
674
674
|
end
|
675
675
|
e = RUBY_VERSION >= '2.4' ? 'e' : 'E'
|
676
|
-
@d.dump_table_schema(:t4).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').must_equal "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal
|
677
|
-
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').must_equal "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal
|
676
|
+
@d.dump_table_schema(:t4).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').must_equal "create_table(:t4) do\n TrueClass :c1, :default=>false\n String :c2, :default=>\"blah\"\n Integer :c3, :default=>-1\n Float :c4, :default=>1.0\n BigDecimal :c5, :default=>BigDecimal(\"0.1005#{e}3\")\n File :c6, :default=>Sequel::SQL::Blob.new(\"blah\")\n Date :c7, :default=>Date.new(2008, 10, 29)\n DateTime :c8, :default=>DateTime.parse(\"2008-10-29T10:20:30.0\")\n Time :c9, :default=>Sequel::SQLTime.parse(\"10:20:30.0\"), :only_time=>true\n String :c10\n Date :c11, :default=>Sequel::CURRENT_DATE\n DateTime :c12, :default=>Sequel::CURRENT_TIMESTAMP\nend"
|
677
|
+
@d.dump_table_schema(:t4, :same_db=>true).gsub(/[+-]\d\d\d\d"\)/, '")').gsub(/\.0+/, '.0').must_equal "create_table(:t4) do\n column :c1, \"boolean\", :default=>false\n column :c2, \"varchar\", :default=>\"blah\"\n column :c3, \"integer\", :default=>-1\n column :c4, \"float\", :default=>1.0\n column :c5, \"decimal\", :default=>BigDecimal(\"0.1005#{e}3\")\n column :c6, \"blob\", :default=>Sequel::SQL::Blob.new(\"blah\")\n column :c7, \"date\", :default=>Date.new(2008, 10, 29)\n column :c8, \"datetime\", :default=>DateTime.parse(\"2008-10-29T10:20:30.0\")\n column :c9, \"time\", :default=>Sequel::SQLTime.parse(\"10:20:30.0\")\n column :c10, \"foo\", :default=>Sequel::LiteralString.new(\"'6 weeks'\")\n column :c11, \"date\", :default=>Sequel::CURRENT_DATE\n column :c12, \"timestamp\", :default=>Sequel::CURRENT_TIMESTAMP\nend"
|
678
678
|
end
|
679
679
|
|
680
680
|
it "should not use a literal string as a fallback if using MySQL with the :same_db option" do
|
@@ -24,7 +24,7 @@ describe "Sequel sql_expr extension" do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "Numeric#sql_expr should wrap the object in a NumericExpression" do
|
27
|
-
[1, 2.0, 2^70, BigDecimal
|
27
|
+
[1, 2.0, 2^70, BigDecimal('1.0')].each do |o|
|
28
28
|
@ds.literal(o.sql_expr).must_equal @ds.literal(o)
|
29
29
|
@ds.literal(o.sql_expr + 1).must_equal "(#{@ds.literal(o)} + 1)"
|
30
30
|
end
|
@@ -79,7 +79,7 @@ describe "string_agg extension" do
|
|
79
79
|
it "should handle operations on object" do
|
80
80
|
ds = dbf.call(:postgres).dataset.with_quote_identifiers(false)
|
81
81
|
ds.literal(@sa1 + 'b').must_equal "(string_agg(c, ',') || 'b')"
|
82
|
-
ds.literal(@sa1.like('b')).must_equal "(string_agg(c, ',') LIKE 'b'
|
82
|
+
ds.literal(@sa1.like('b')).must_equal "(string_agg(c, ',') LIKE 'b')"
|
83
83
|
ds.literal(@sa1 < 'b').must_equal "(string_agg(c, ',') < 'b')"
|
84
84
|
ds.literal(@sa1.as(:b)).must_equal "string_agg(c, ',') AS b"
|
85
85
|
ds.literal(@sa1.cast(:b)).must_equal "CAST(string_agg(c, ',') AS b)"
|
@@ -63,9 +63,9 @@ describe "Sequel::Plugins::Timestamps" do
|
|
63
63
|
it "should work with current_datetime_timestamp extension" do
|
64
64
|
Sequel.datetime_class = Time
|
65
65
|
@c.dataset = @c.dataset.extension(:current_datetime_timestamp)
|
66
|
-
|
66
|
+
@c.create
|
67
67
|
@c.db.sqls.must_equal ["INSERT INTO t (created_at) VALUES (CURRENT_TIMESTAMP)"]
|
68
|
-
|
68
|
+
@c.load(:id=>1).save
|
69
69
|
@c.db.sqls.must_equal ["UPDATE t SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
|
70
70
|
end
|
71
71
|
|
@@ -293,7 +293,7 @@ describe "Sequel::Plugins::ValidationHelpers" do
|
|
293
293
|
@m.must_be :valid?
|
294
294
|
@m.value = 1.0
|
295
295
|
@m.must_be :valid?
|
296
|
-
@m.value = BigDecimal
|
296
|
+
@m.value = BigDecimal('1.0')
|
297
297
|
@m.wont_be :valid?
|
298
298
|
@m.errors.full_messages.must_equal ['value is not a valid integer or float']
|
299
299
|
end
|
@@ -2059,6 +2059,18 @@ describe "Sequel::Model Simple Associations" do
|
|
2059
2059
|
artist.albums.first.tags.must_equal [tag2]
|
2060
2060
|
end
|
2061
2061
|
|
2062
|
+
it "should not produce duplicates when eager graphing many_to_one=>one_to_many association" do
|
2063
|
+
@pr.call
|
2064
|
+
@album.update(:artist => @artist)
|
2065
|
+
album2 = Album.last
|
2066
|
+
album2.update(:artist => @artist)
|
2067
|
+
|
2068
|
+
a = Album.eager_graph(:artist=>:albums).order{[albums[:id], albums_0[:id]]}.all
|
2069
|
+
a.must_equal [@album, album2]
|
2070
|
+
a.map(&:artist).must_equal [@artist, @artist]
|
2071
|
+
a.map(&:artist).map(&:albums).must_equal [[@album, album2], [@album, album2]]
|
2072
|
+
end
|
2073
|
+
|
2062
2074
|
it "should have remove method raise an error for one_to_many records if the object isn't already associated" do
|
2063
2075
|
proc{@artist.remove_album(@album.id)}.must_raise(Sequel::Error)
|
2064
2076
|
proc{@artist.remove_album(@album)}.must_raise(Sequel::Error)
|
@@ -1698,6 +1698,27 @@ describe "Dataset string methods" do
|
|
1698
1698
|
@ds.filter(Sequel.expr(:b).ilike(@ds.escape_like('[Bar%]'))).select_order_map(:b).must_equal ['[bar%]']
|
1699
1699
|
@ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}_")).select_order_map(:b).must_equal ['bar%.']
|
1700
1700
|
@ds.filter(Sequel.expr(:b).ilike("#{@ds.escape_like('Bar%')}%")).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
|
1701
|
+
|
1702
|
+
Sequel.extension(:escaped_like)
|
1703
|
+
@ds.filter(Sequel.expr(:a).escaped_like('?', 'Foo_')).select_order_map(:a).must_equal []
|
1704
|
+
@ds.filter(Sequel.expr(:a).escaped_like('?', 'foo_')).select_order_map(:a).must_equal ['foo_']
|
1705
|
+
@ds.filter(Sequel.expr(:b).escaped_like('?', ['bar%'])).select_order_map(:b).must_equal ['bar%']
|
1706
|
+
@ds.filter(Sequel.expr(:a).escaped_like('??', ['fo', 'o\\_'])).select_order_map(:a).must_equal ['foo\\_']
|
1707
|
+
@ds.filter(Sequel.expr(:b).escaped_like('?', 'bar\\%')).select_order_map(:b).must_equal ['bar\\%']
|
1708
|
+
@ds.filter(Sequel.expr(:a).escaped_like('?', '[f#*?oo_]')).select_order_map(:a).must_equal ['[f#*?oo_]']
|
1709
|
+
@ds.filter(Sequel.expr(:b).escaped_like('?', '[bar%]')).select_order_map(:b).must_equal ['[bar%]']
|
1710
|
+
@ds.filter(Sequel.expr(:b).escaped_like('?_', 'bar%')).select_order_map(:b).must_equal ['bar%.']
|
1711
|
+
@ds.filter(Sequel.expr(:b).escaped_like('?%', 'bar%')).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
|
1712
|
+
|
1713
|
+
@ds.filter(Sequel.expr(:a).escaped_ilike('?', 'Foo_')).select_order_map(:a).must_equal ['foo_']
|
1714
|
+
@ds.filter(Sequel.expr(:a).escaped_ilike('?', 'Foo_')).select_order_map(:a).must_equal ['foo_']
|
1715
|
+
@ds.filter(Sequel.expr(:b).escaped_ilike('?', ['Bar%'])).select_order_map(:b).must_equal ['bar%']
|
1716
|
+
@ds.filter(Sequel.expr(:a).escaped_ilike('??', ['Fo', 'o\\_'])).select_order_map(:a).must_equal ['foo\\_']
|
1717
|
+
@ds.filter(Sequel.expr(:b).escaped_ilike('?', 'Bar\\%')).select_order_map(:b).must_equal ['bar\\%']
|
1718
|
+
@ds.filter(Sequel.expr(:a).escaped_ilike('?', '[F#*?oo_]')).select_order_map(:a).must_equal ['[f#*?oo_]']
|
1719
|
+
@ds.filter(Sequel.expr(:b).escaped_ilike('?', '[Bar%]')).select_order_map(:b).must_equal ['[bar%]']
|
1720
|
+
@ds.filter(Sequel.expr(:b).escaped_ilike('?_', 'Bar%')).select_order_map(:b).must_equal ['bar%.']
|
1721
|
+
@ds.filter(Sequel.expr(:b).escaped_ilike('?%', 'Bar%')).select_order_map(:b).must_equal ['bar%', 'bar%.', 'bar%..']
|
1701
1722
|
end
|
1702
1723
|
|
1703
1724
|
if DB.dataset.supports_regexp?
|
@@ -45,11 +45,11 @@ describe "Supported types" do
|
|
45
45
|
|
46
46
|
cspecify "should support generic numeric type", [:odbc, :mssql] do
|
47
47
|
ds = create_items_table_with_column(:number, Numeric, :size=>[15, 10])
|
48
|
-
ds.insert(:number => BigDecimal
|
49
|
-
ds.all.must_equal [{:number=>BigDecimal
|
48
|
+
ds.insert(:number => BigDecimal('2.123456789'))
|
49
|
+
ds.all.must_equal [{:number=>BigDecimal('2.123456789')}]
|
50
50
|
ds = create_items_table_with_column(:number, BigDecimal, :size=>[15, 10])
|
51
|
-
ds.insert(:number => BigDecimal
|
52
|
-
ds.all.must_equal [{:number=>BigDecimal
|
51
|
+
ds.insert(:number => BigDecimal('2.123456789'))
|
52
|
+
ds.all.must_equal [{:number=>BigDecimal('2.123456789')}]
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should support generic string type" do
|
data/spec/model/base_spec.rb
CHANGED
@@ -100,6 +100,15 @@ describe Sequel::Model, "dataset" do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
describe Sequel::Model, "has_dataset?" do
|
104
|
+
it "should return whether the model has a dataset" do
|
105
|
+
c = Class.new(Sequel::Model)
|
106
|
+
c.has_dataset?.must_equal false
|
107
|
+
c.dataset = c.db[:table]
|
108
|
+
c.has_dataset?.must_equal true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
103
112
|
describe Sequel::Model, "implicit table names" do
|
104
113
|
after do
|
105
114
|
Object.send(:remove_const, :BlahBlah)
|
@@ -2168,6 +2168,21 @@ describe Sequel::Model, "#eager_graph" do
|
|
2168
2168
|
a.al_genre.must_equal GraphGenre.load(:id=>12)
|
2169
2169
|
end
|
2170
2170
|
|
2171
|
+
it "should not include duplicate objects when eager graphing many_to_one=>one_to_many" do
|
2172
|
+
ds = GraphAlbum.eager_graph(:band=>:albums)
|
2173
|
+
ds.sql.must_equal "SELECT albums.id, albums.band_id, band.id AS band_id_0, band.vocalist_id, albums_0.id AS albums_0_id, albums_0.band_id AS albums_0_band_id FROM albums LEFT OUTER JOIN bands AS band ON (band.id = albums.band_id) LEFT OUTER JOIN albums AS albums_0 ON (albums_0.band_id = band.id)"
|
2174
|
+
a = ds.with_fetch([
|
2175
|
+
{:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>1, :albums_0_id=>1, :albums_0_band_id=>2},
|
2176
|
+
{:id=>2, :band_id=>2, :band_id_0=>2, :vocalist_id=>1, :albums_0_id=>1, :albums_0_band_id=>2},
|
2177
|
+
{:id=>1, :band_id=>2, :band_id_0=>2, :vocalist_id=>1, :albums_0_id=>2, :albums_0_band_id=>2},
|
2178
|
+
{:id=>2, :band_id=>2, :band_id_0=>2, :vocalist_id=>1, :albums_0_id=>2, :albums_0_band_id=>2}
|
2179
|
+
]).all
|
2180
|
+
albums = [GraphAlbum.load(:id => 1, :band_id => 2), GraphAlbum.load(:id => 2, :band_id => 2)]
|
2181
|
+
a.must_equal albums
|
2182
|
+
a.map(&:band).must_equal [GraphBand.load(:id=>2, :vocalist_id=>1), GraphBand.load(:id=>2, :vocalist_id=>1)]
|
2183
|
+
a.map(&:band).map(&:albums).must_equal [albums, albums]
|
2184
|
+
end
|
2185
|
+
|
2171
2186
|
it "should eagerly load a many_to_one association with a custom callback" do
|
2172
2187
|
ds = GraphAlbum.eager_graph(:band => proc {|ds1| ds1.select(:id).columns(:id)})
|
2173
2188
|
ds.sql.must_equal 'SELECT albums.id, albums.band_id, band.id AS band_id_0 FROM albums LEFT OUTER JOIN (SELECT id FROM bands) AS band ON (band.id = albums.band_id)'
|
@@ -2229,6 +2244,16 @@ describe Sequel::Model, "#eager_graph" do
|
|
2229
2244
|
a.album.band.must_equal GraphBand.load(:id => 2, :vocalist_id=>6)
|
2230
2245
|
a.album.tracks.must_equal [GraphTrack.load(:id => 3, :album_id => 1)]
|
2231
2246
|
end
|
2247
|
+
|
2248
|
+
it "should have frozen internal data structures" do
|
2249
|
+
ds = GraphAlbum.eager_graph(:band)
|
2250
|
+
ds.opts[:eager_graph].must_be :frozen?
|
2251
|
+
ds.opts[:eager_graph].each_value{|v| v.must_be :frozen? if v.is_a?(Hash)}
|
2252
|
+
|
2253
|
+
ds = ds.eager_graph(:tracks)
|
2254
|
+
ds.opts[:eager_graph].must_be :frozen?
|
2255
|
+
ds.opts[:eager_graph].each_value{|v| v.must_be :frozen? if v.is_a?(Hash)}
|
2256
|
+
end
|
2232
2257
|
end
|
2233
2258
|
|
2234
2259
|
describe "Sequel::Models with double underscores in table names" do
|
data/spec/model/record_spec.rb
CHANGED
@@ -1835,7 +1835,7 @@ describe Sequel::Model, "typecasting" do
|
|
1835
1835
|
it "should convert to BigDecimal for a decimal field" do
|
1836
1836
|
@c.db_schema = {:x=>{:type=>:decimal}}
|
1837
1837
|
m = @c.new
|
1838
|
-
bd = BigDecimal
|
1838
|
+
bd = BigDecimal('1.0')
|
1839
1839
|
m.x = '1.0'
|
1840
1840
|
m.x.must_equal bd
|
1841
1841
|
m.x = 1.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -192,6 +192,7 @@ extra_rdoc_files:
|
|
192
192
|
- doc/release_notes/5.4.0.txt
|
193
193
|
- doc/release_notes/5.8.0.txt
|
194
194
|
- doc/release_notes/5.7.0.txt
|
195
|
+
- doc/release_notes/5.9.0.txt
|
195
196
|
files:
|
196
197
|
- CHANGELOG
|
197
198
|
- MIT-LICENSE
|
@@ -278,6 +279,7 @@ files:
|
|
278
279
|
- doc/release_notes/5.6.0.txt
|
279
280
|
- doc/release_notes/5.7.0.txt
|
280
281
|
- doc/release_notes/5.8.0.txt
|
282
|
+
- doc/release_notes/5.9.0.txt
|
281
283
|
- doc/schema_modification.rdoc
|
282
284
|
- doc/security.rdoc
|
283
285
|
- doc/sharding.rdoc
|
@@ -385,6 +387,7 @@ files:
|
|
385
387
|
- lib/sequel/extensions/duplicate_columns_handler.rb
|
386
388
|
- lib/sequel/extensions/empty_array_consider_nulls.rb
|
387
389
|
- lib/sequel/extensions/error_sql.rb
|
390
|
+
- lib/sequel/extensions/escaped_like.rb
|
388
391
|
- lib/sequel/extensions/eval_inspect.rb
|
389
392
|
- lib/sequel/extensions/freeze_datasets.rb
|
390
393
|
- lib/sequel/extensions/from_block.rb
|
@@ -596,6 +599,7 @@ files:
|
|
596
599
|
- spec/extensions/empty_array_consider_nulls_spec.rb
|
597
600
|
- spec/extensions/error_splitter_spec.rb
|
598
601
|
- spec/extensions/error_sql_spec.rb
|
602
|
+
- spec/extensions/escaped_like_spec.rb
|
599
603
|
- spec/extensions/eval_inspect_spec.rb
|
600
604
|
- spec/extensions/finder_spec.rb
|
601
605
|
- spec/extensions/force_encoding_spec.rb
|