sequel 5.4.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +26 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/doc/release_notes/5.5.0.txt +61 -0
- data/lib/sequel/adapters/postgres.rb +8 -2
- data/lib/sequel/database/query.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +11 -0
- data/lib/sequel/extensions/pg_hstore.rb +10 -0
- data/lib/sequel/extensions/pg_inet.rb +10 -0
- data/lib/sequel/extensions/pg_interval.rb +10 -0
- data/lib/sequel/extensions/pg_json.rb +24 -0
- data/lib/sequel/extensions/pg_range.rb +14 -0
- data/lib/sequel/model/base.rb +29 -18
- data/lib/sequel/plugins/defaults_setter.rb +45 -8
- data/lib/sequel/plugins/dirty.rb +2 -2
- data/lib/sequel/plugins/modification_detection.rb +12 -5
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +2 -1
- data/lib/sequel/plugins/serialization.rb +3 -2
- data/lib/sequel/plugins/typecast_on_load.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +2 -1
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/postgres_spec.rb +79 -8
- data/spec/core/schema_spec.rb +10 -0
- data/spec/extensions/defaults_setter_spec.rb +18 -0
- data/spec/extensions/modification_detection_spec.rb +13 -0
- data/spec/extensions/pg_array_spec.rb +11 -0
- data/spec/extensions/pg_hstore_spec.rb +11 -0
- data/spec/extensions/pg_inet_spec.rb +6 -0
- data/spec/extensions/pg_interval_spec.rb +6 -0
- data/spec/extensions/pg_json_spec.rb +29 -0
- data/spec/extensions/pg_range_spec.rb +6 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34e1f1ee3e3e1b863d4efbc3710cae912ae394a655b6e9fed41325f02d54f23e
|
4
|
+
data.tar.gz: af6f231e63231de19bb7956ea16cff29ec2faebe379a0ba86e12df933af0b91b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2f482f59fe3bb9eb19d2fa88a6fccfdf5e259cb23a52e2d21c3bb692f4f3a04339c2011922a03ceb4593b4a2708fbafdd45dbde2a882f7f77d20a3e2048e000
|
7
|
+
data.tar.gz: 19e9f635bcdb299673ab5d042159f7e76dbdee1807fd02b8e897c434e6ad11214113ac252064106507620ae3e9a19d3facb49d181ab28cc08e47c5a5b2ebfa65
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
=== 5.5.0 (2018-01-31)
|
2
|
+
|
3
|
+
* Make Database#copy_table in the postgres adapter handle errors that occur while processing rows (jeremyevans) (#1470)
|
4
|
+
|
5
|
+
* Cache results of changed_columns method in local variables in many places for better performance (jeremyevans)
|
6
|
+
|
7
|
+
* Make modification_detection plugin not break column change detection for new objects (jeremyevans) (#1468)
|
8
|
+
|
9
|
+
* Make pg_range extension set :ruby_default schema value for recognized range defaults (jeremyevans)
|
10
|
+
|
11
|
+
* Make pg_interval extension set :ruby_default schema value for recognized interval defaults (jeremyevans)
|
12
|
+
|
13
|
+
* Make pg_json extension set :callable_default schema value for empty json/jsonb array/hash defaults (jeremyevans)
|
14
|
+
|
15
|
+
* Make pg_inet extension set :ruby_default schema value for recognized inet/cidr defaults (jeremyevans)
|
16
|
+
|
17
|
+
* Make pg_hstore extension set :callable_default schema value for empty hstore defaults (jeremyevans)
|
18
|
+
|
19
|
+
* Make pg_array extension set :callable_default schema value for recognized empty array defaults (jeremyevans) (#1466)
|
20
|
+
|
21
|
+
* Make defaults_setter plugin prefer :callable_default db_schema values over :ruby_default db_schema values (jeremyevans)
|
22
|
+
|
23
|
+
* Add defaults_setter plugin :cache option for caching default values returned (jeremyevans)
|
24
|
+
|
25
|
+
* Freeze string values in hashes returned by Database#schema (jeremyevans)
|
26
|
+
|
1
27
|
=== 5.4.0 (2018-01-04)
|
2
28
|
|
3
29
|
* Enable fractional seconds in timestamps on DB2 (jeremyevans) (#1463)
|
data/MIT-LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
Copyright (c) 2007-2008 Sharon Rosner
|
2
|
-
Copyright (c) 2008-
|
2
|
+
Copyright (c) 2008-2018 Jeremy Evans
|
3
3
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
5
|
of this software and associated documentation files (the "Software"), to
|
data/README.rdoc
CHANGED
@@ -124,7 +124,7 @@ You can also specify optional parameters, such as the connection pool size, or l
|
|
124
124
|
It is also possible to use a hash instead of a connection URL, but make sure to include the :adapter option in this case:
|
125
125
|
|
126
126
|
DB = Sequel.connect(adapter: :postgres, user: 'user', password: 'password', host: 'host', port: port,
|
127
|
-
database: 'database_name
|
127
|
+
database: 'database_name', max_connections: 10, logger: Logger.new('log/db.log'))
|
128
128
|
|
129
129
|
You can specify a block to connect, which will disconnect from the database after it completes:
|
130
130
|
|
@@ -0,0 +1,61 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The defaults_setter plugin now supports a :cache option, which
|
4
|
+
will cache default values in the model object's values hash:
|
5
|
+
|
6
|
+
Model.plugin :defaults_setter
|
7
|
+
o = Model.new
|
8
|
+
o.column # => 1 # default value
|
9
|
+
o.values # => {}
|
10
|
+
|
11
|
+
Model.plugin :defaults_setter, cache: true
|
12
|
+
o = Model.new
|
13
|
+
o.column # => 1 # default value
|
14
|
+
o.values # => {:column => 1}
|
15
|
+
|
16
|
+
* The pg_array extension now sets a :callable_default schema entry
|
17
|
+
for recognized empty array defaults.
|
18
|
+
|
19
|
+
* The pg_hstore extension now sets a :callable_default schema entry
|
20
|
+
for recognized empty hstore defaults.
|
21
|
+
|
22
|
+
* The pg_json extension now sets a :callable_default schema entry for
|
23
|
+
recognized empty json/jsonb array/hash defaults.
|
24
|
+
|
25
|
+
* The pg_inet extension now sets a :ruby_default schema entry for
|
26
|
+
recognized inet/cidr defaults.
|
27
|
+
|
28
|
+
* The pg_range extension now sets a :ruby_default schema entry for
|
29
|
+
recognized range defaults.
|
30
|
+
|
31
|
+
* The defaults_setter plugin will now give preference to a
|
32
|
+
:callable_default schema entry over a :ruby_default schema entry.
|
33
|
+
Combined with the other changes listed above, this makes default
|
34
|
+
values recognized by the pg_array, pg_hstore, and pg_json extensions
|
35
|
+
work well if the defaults_setter :cache option is also used.
|
36
|
+
|
37
|
+
= Other Improvements
|
38
|
+
|
39
|
+
* The modification_detection plugin no longer breaks column change
|
40
|
+
detection for new objects.
|
41
|
+
|
42
|
+
* Database#copy_table in the postgres adapter now handles errors that
|
43
|
+
occur when processing rows. Previously, an exception could be
|
44
|
+
raised on the next query in that case.
|
45
|
+
|
46
|
+
* The results of the changed_columns method are now cached in many
|
47
|
+
places internally where they are called in a loop. This results
|
48
|
+
in better performance, especially if the modification_detection or
|
49
|
+
serialization_modification_detection plugins are used.
|
50
|
+
|
51
|
+
= Backwards Compatibility
|
52
|
+
|
53
|
+
* The pg_interval extension now sets a :ruby_default schema entry for
|
54
|
+
recognized interval defaults to the same value Sequel would return
|
55
|
+
if the default value was returned. Previously, Sequel would use a
|
56
|
+
string in the :ruby_schema schema value.
|
57
|
+
|
58
|
+
* String values in hashes returned by Database#schema are now frozen
|
59
|
+
to prevent possible thread-safety issues and issues with
|
60
|
+
unintentional modification of a shared string. The hashes
|
61
|
+
themselves are not frozen and can still be modified.
|
@@ -309,12 +309,18 @@ module Sequel
|
|
309
309
|
while buf = conn.get_copy_data
|
310
310
|
yield buf
|
311
311
|
end
|
312
|
-
nil
|
312
|
+
b = nil
|
313
313
|
else
|
314
314
|
b = String.new
|
315
315
|
b << buf while buf = conn.get_copy_data
|
316
|
-
b
|
317
316
|
end
|
317
|
+
|
318
|
+
res = conn.get_last_result
|
319
|
+
if !res || res.result_status != 1
|
320
|
+
raise PG::NotAllCopyDataRetrieved, "Not all COPY data retrieved"
|
321
|
+
end
|
322
|
+
|
323
|
+
b
|
318
324
|
rescue => e
|
319
325
|
raise_error(e, :disconnect=>true)
|
320
326
|
ensure
|
@@ -175,6 +175,10 @@ module Sequel
|
|
175
175
|
if !c[:max_length] && c[:type] == :string && (max_length = column_schema_max_length(c[:db_type]))
|
176
176
|
c[:max_length] = max_length
|
177
177
|
end
|
178
|
+
|
179
|
+
c.each_value do |v|
|
180
|
+
v.freeze if v.is_a?(String)
|
181
|
+
end
|
178
182
|
end
|
179
183
|
Sequel.synchronize{@schemas[quoted_name] = cols} if cache_schema
|
180
184
|
cols
|
@@ -253,6 +253,17 @@ module Sequel
|
|
253
253
|
end
|
254
254
|
end
|
255
255
|
|
256
|
+
# Set the :callable_default value if the default value is recognized as an empty array.
|
257
|
+
def schema_parse_table(*)
|
258
|
+
super.each do |a|
|
259
|
+
h = a[1]
|
260
|
+
if h[:default] =~ /\A(?:'\{\}'|ARRAY\[\])::([\w ]+)\[\]\z/
|
261
|
+
type = $1.freeze
|
262
|
+
h[:callable_default] = lambda{Sequel.pg_array([], type)}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
256
267
|
# Convert ruby arrays to PostgreSQL arrays when used as default values.
|
257
268
|
def column_definition_default_sql(sql, column)
|
258
269
|
if (d = column[:default]) && d.is_a?(Array) && !Sequel.condition_specifier?(d)
|
@@ -154,6 +154,16 @@ module Sequel
|
|
154
154
|
db_type == 'hstore' ? :hstore : super
|
155
155
|
end
|
156
156
|
|
157
|
+
# Set the :callable_default value if the default value is recognized as an empty hstore.
|
158
|
+
def schema_parse_table(*)
|
159
|
+
super.each do |a|
|
160
|
+
h = a[1]
|
161
|
+
if h[:type] == :hstore && h[:default] =~ /\A''::hstore\z/
|
162
|
+
h[:callable_default] = lambda{HStore.new({})}
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
157
167
|
# Typecast value correctly to HStore. If already an
|
158
168
|
# HStore instance, return as is. If a hash, return
|
159
169
|
# an HStore version of it. If a string, assume it is
|
@@ -85,6 +85,16 @@ module Sequel
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
# Set the :ruby_default value if the default value is recognized as an ip address.
|
89
|
+
def schema_parse_table(*)
|
90
|
+
super.each do |a|
|
91
|
+
h = a[1]
|
92
|
+
if h[:type] == :ipaddr && h[:default] =~ /\A'([:a-fA-F0-9\.\/]+)'::(?:inet|cidr)\z/
|
93
|
+
h[:ruby_default] = IPAddr.new($1)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
88
98
|
# Typecast the given value to an IPAddr object.
|
89
99
|
def typecast_value_ipaddr(value)
|
90
100
|
case value
|
@@ -146,6 +146,16 @@ module Sequel
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
+
# Set the :ruby_default value if the default value is recognized as an interval.
|
150
|
+
def schema_parse_table(*)
|
151
|
+
super.each do |a|
|
152
|
+
h = a[1]
|
153
|
+
if h[:type] == :interval && h[:default] =~ /\A'([\w ]+)'::interval\z/
|
154
|
+
h[:ruby_default] = PARSER.call($1)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
149
159
|
# Typecast value correctly to an ActiveSupport::Duration instance.
|
150
160
|
# If already an ActiveSupport::Duration, return it.
|
151
161
|
# If a numeric argument is given, assume it represents a number
|
@@ -214,6 +214,30 @@ module Sequel
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
+
# Set the :callable_default value if the default value is recognized as an empty json/jsonb array/hash.
|
218
|
+
def schema_parse_table(*)
|
219
|
+
super.each do |a|
|
220
|
+
h = a[1]
|
221
|
+
if (h[:type] == :json || h[:type] == :jsonb) && h[:default] =~ /\A'(\{\}|\[\])'::jsonb?\z/
|
222
|
+
is_array = $1 == '[]'
|
223
|
+
|
224
|
+
klass = if h[:type] == :json
|
225
|
+
if is_array
|
226
|
+
JSONArray
|
227
|
+
else
|
228
|
+
JSONHash
|
229
|
+
end
|
230
|
+
elsif is_array
|
231
|
+
JSONBArray
|
232
|
+
else
|
233
|
+
JSONBHash
|
234
|
+
end
|
235
|
+
|
236
|
+
h[:callable_default] = lambda{klass.new(is_array ? [] : {})}
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
217
241
|
# Convert the value given to a JSONArray or JSONHash
|
218
242
|
def typecast_value_json(value)
|
219
243
|
case value
|
@@ -262,6 +262,20 @@ module Sequel
|
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
265
|
+
# Set the :ruby_default value if the default value is recognized as a range.
|
266
|
+
def schema_parse_table(*)
|
267
|
+
super.each do |a|
|
268
|
+
h = a[1]
|
269
|
+
db_type = h[:db_type]
|
270
|
+
if @pg_range_schema_types[db_type] && h[:default] =~ /\A'([^']+)'::#{db_type}\z/
|
271
|
+
default = $1
|
272
|
+
if convertor = conversion_procs[h[:oid]]
|
273
|
+
h[:ruby_default] = convertor.call($1)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
265
279
|
# Typecast value correctly to a PGRange. If already an
|
266
280
|
# PGRange instance with the same db_type, return as is.
|
267
281
|
# If a PGRange with a different subtype, return a new
|
data/lib/sequel/model/base.rb
CHANGED
@@ -1060,7 +1060,7 @@ module Sequel
|
|
1060
1060
|
@new = true
|
1061
1061
|
@modified = true
|
1062
1062
|
initialize_set(values)
|
1063
|
-
|
1063
|
+
_changed_columns.clear
|
1064
1064
|
yield self if block_given?
|
1065
1065
|
end
|
1066
1066
|
|
@@ -1137,9 +1137,9 @@ module Sequel
|
|
1137
1137
|
# a.name = 'Bob'
|
1138
1138
|
# a.changed_columns # => [:name]
|
1139
1139
|
def changed_columns
|
1140
|
-
|
1140
|
+
_changed_columns
|
1141
1141
|
end
|
1142
|
-
|
1142
|
+
|
1143
1143
|
# Deletes and returns +self+. Does not run destroy hooks.
|
1144
1144
|
# Look into using +destroy+ instead.
|
1145
1145
|
#
|
@@ -1212,7 +1212,7 @@ module Sequel
|
|
1212
1212
|
# errors, or dataset.
|
1213
1213
|
def freeze
|
1214
1214
|
values.freeze
|
1215
|
-
|
1215
|
+
_changed_columns.freeze
|
1216
1216
|
unless errors.frozen?
|
1217
1217
|
validate
|
1218
1218
|
errors.freeze
|
@@ -1316,9 +1316,7 @@ module Sequel
|
|
1316
1316
|
# a.modified!(:name)
|
1317
1317
|
# a.name.gsub!(/[aeou]/, 'i')
|
1318
1318
|
def modified!(column=nil)
|
1319
|
-
|
1320
|
-
changed_columns << column
|
1321
|
-
end
|
1319
|
+
_add_changed_column(column) if column
|
1322
1320
|
@modified = true
|
1323
1321
|
end
|
1324
1322
|
|
@@ -1583,6 +1581,17 @@ module Sequel
|
|
1583
1581
|
|
1584
1582
|
private
|
1585
1583
|
|
1584
|
+
# Add a column as a changed column.
|
1585
|
+
def _add_changed_column(column)
|
1586
|
+
cc = _changed_columns
|
1587
|
+
cc << column unless cc.include?(column)
|
1588
|
+
end
|
1589
|
+
|
1590
|
+
# Internal changed_columns method that just returns stored array.
|
1591
|
+
def _changed_columns
|
1592
|
+
@changed_columns ||= []
|
1593
|
+
end
|
1594
|
+
|
1586
1595
|
# Do the deletion of the object's dataset, and check that the row
|
1587
1596
|
# was actually deleted.
|
1588
1597
|
def _delete
|
@@ -1672,7 +1681,7 @@ module Sequel
|
|
1672
1681
|
# is used for reading newly inserted values from the database
|
1673
1682
|
def _refresh(dataset)
|
1674
1683
|
_refresh_set_values(_refresh_get(dataset) || raise(NoExistingObject, "Record not found"))
|
1675
|
-
|
1684
|
+
_changed_columns.clear
|
1676
1685
|
end
|
1677
1686
|
|
1678
1687
|
# Get the row of column data from the database.
|
@@ -1710,7 +1719,7 @@ module Sequel
|
|
1710
1719
|
@this = nil
|
1711
1720
|
@new = false
|
1712
1721
|
@modified = false
|
1713
|
-
pk ? _save_refresh :
|
1722
|
+
pk ? _save_refresh : _changed_columns.clear
|
1714
1723
|
after_create
|
1715
1724
|
true
|
1716
1725
|
end
|
@@ -1721,16 +1730,18 @@ module Sequel
|
|
1721
1730
|
before_update
|
1722
1731
|
columns = opts[:columns]
|
1723
1732
|
if columns.nil?
|
1724
|
-
|
1725
|
-
|
1733
|
+
if opts[:changed]
|
1734
|
+
cc = changed_columns
|
1735
|
+
columns_updated = @values.reject{|k,v| !cc.include?(k)}
|
1736
|
+
cc.clear
|
1726
1737
|
else
|
1727
|
-
_save_update_all_columns_hash
|
1738
|
+
columns_updated = _save_update_all_columns_hash
|
1739
|
+
_changed_columns.clear
|
1728
1740
|
end
|
1729
|
-
changed_columns.clear
|
1730
1741
|
else # update only the specified columns
|
1731
1742
|
columns = Array(columns)
|
1732
1743
|
columns_updated = @values.reject{|k, v| !columns.include?(k)}
|
1733
|
-
|
1744
|
+
_changed_columns.reject!{|c| columns.include?(c)}
|
1734
1745
|
end
|
1735
1746
|
_update_columns(columns_updated)
|
1736
1747
|
@this = nil
|
@@ -1752,7 +1763,7 @@ module Sequel
|
|
1752
1763
|
# can be overridden to avoid the refresh.
|
1753
1764
|
def _save_refresh
|
1754
1765
|
_save_set_values(_refresh_get(this.server?(:default)) || raise(NoExistingObject, "Record not found"))
|
1755
|
-
|
1766
|
+
_changed_columns.clear
|
1756
1767
|
end
|
1757
1768
|
|
1758
1769
|
# Set values to the provided hash. Called after a create,
|
@@ -1769,7 +1780,8 @@ module Sequel
|
|
1769
1780
|
# to their existing values.
|
1770
1781
|
def _save_update_all_columns_hash
|
1771
1782
|
v = Hash[@values]
|
1772
|
-
|
1783
|
+
cc = changed_columns
|
1784
|
+
Array(primary_key).each{|x| v.delete(x) unless cc.include?(x)}
|
1773
1785
|
v
|
1774
1786
|
end
|
1775
1787
|
|
@@ -1847,8 +1859,7 @@ module Sequel
|
|
1847
1859
|
|
1848
1860
|
# Change the value of the column to given value, recording the change.
|
1849
1861
|
def change_column_value(column, value)
|
1850
|
-
|
1851
|
-
cc << column unless cc.include?(column)
|
1862
|
+
_add_changed_column(column)
|
1852
1863
|
@values[column] = value
|
1853
1864
|
end
|
1854
1865
|
|
@@ -23,6 +23,24 @@ module Sequel
|
|
23
23
|
#
|
24
24
|
# Album.default_values[:a] = lambda{Date.today}
|
25
25
|
# Album.new.a # => Date.today
|
26
|
+
#
|
27
|
+
# By default, default values returned are not cached:
|
28
|
+
#
|
29
|
+
# Album.new.a.equal?(Album.new.a) # => false
|
30
|
+
#
|
31
|
+
# However, you can turn on caching of default values:
|
32
|
+
#
|
33
|
+
# Album.plugin :defaults_setter, cache: true
|
34
|
+
# Album.new.a.equal?(Album.new.a) # => false
|
35
|
+
#
|
36
|
+
# Note that if the cache is turned on, the cached values are stored in
|
37
|
+
# the values hash:
|
38
|
+
#
|
39
|
+
# Album.plugin :defaults_setter, cache: true
|
40
|
+
# album = Album.new
|
41
|
+
# album.values # => {}
|
42
|
+
# album.a
|
43
|
+
# album.values # => {:a => Date.today}
|
26
44
|
#
|
27
45
|
# Usage:
|
28
46
|
#
|
@@ -32,22 +50,31 @@ module Sequel
|
|
32
50
|
# # Make the Album class set defaults
|
33
51
|
# Album.plugin :defaults_setter
|
34
52
|
module DefaultsSetter
|
35
|
-
# Set the default values based on the model schema
|
36
|
-
|
37
|
-
|
53
|
+
# Set the default values based on the model schema. Options:
|
54
|
+
# :cache :: Cache default values returned in the model's values hash.
|
55
|
+
def self.configure(model, opts=OPTS)
|
56
|
+
model.instance_exec do
|
57
|
+
set_default_values
|
58
|
+
@cache_default_values = opts[:cache] if opts.has_key?(:cache)
|
59
|
+
end
|
38
60
|
end
|
39
61
|
|
40
62
|
module ClassMethods
|
41
|
-
# The default values to
|
63
|
+
# The default values to use for this model. A hash with column symbol
|
42
64
|
# keys and default values. If the default values respond to +call+, it will be called
|
43
65
|
# to get the value, otherwise the value will be used directly. You can manually modify
|
44
66
|
# this hash to set specific default values, by default the ones will be parsed from the database.
|
45
67
|
attr_reader :default_values
|
46
|
-
|
68
|
+
|
47
69
|
Plugins.after_set_dataset(self, :set_default_values)
|
48
70
|
|
49
|
-
Plugins.inherited_instance_variables(self, :@default_values=>:dup)
|
71
|
+
Plugins.inherited_instance_variables(self, :@default_values=>:dup, :@cache_default_values=>nil)
|
50
72
|
|
73
|
+
# Whether default values should be cached in the values hash after being retrieved.
|
74
|
+
def cache_default_values?
|
75
|
+
@cache_default_values
|
76
|
+
end
|
77
|
+
|
51
78
|
# Freeze default values when freezing model class
|
52
79
|
def freeze
|
53
80
|
@default_values.freeze
|
@@ -59,7 +86,15 @@ module Sequel
|
|
59
86
|
# Parse the cached database schema for this model and set the default values appropriately.
|
60
87
|
def set_default_values
|
61
88
|
h = {}
|
62
|
-
|
89
|
+
if @db_schema
|
90
|
+
@db_schema.each do |k, v|
|
91
|
+
if v[:callable_default]
|
92
|
+
h[k] = v[:callable_default]
|
93
|
+
elsif !v[:ruby_default].nil?
|
94
|
+
h[k] = convert_default_value(v[:ruby_default])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
63
98
|
@default_values = h.merge!(@default_values || {})
|
64
99
|
end
|
65
100
|
|
@@ -82,7 +117,9 @@ module Sequel
|
|
82
117
|
def [](k)
|
83
118
|
if new? && !values.has_key?(k)
|
84
119
|
v = model.default_values[k]
|
85
|
-
v
|
120
|
+
v = v.call if v.respond_to?(:call)
|
121
|
+
values[k] = v if model.cache_default_values?
|
122
|
+
v
|
86
123
|
else
|
87
124
|
super
|
88
125
|
end
|
data/lib/sequel/plugins/dirty.rb
CHANGED
@@ -137,7 +137,7 @@ module Sequel
|
|
137
137
|
# name.gsub(/i/i, 'o')
|
138
138
|
# column_change(:name) # => ['Initial', 'onotoal']
|
139
139
|
def will_change_column(column)
|
140
|
-
|
140
|
+
_add_changed_column(column)
|
141
141
|
check_missing_initial_value(column)
|
142
142
|
|
143
143
|
value = if initial_values.has_key?(column)
|
@@ -186,7 +186,7 @@ module Sequel
|
|
186
186
|
initial = iv[column]
|
187
187
|
super
|
188
188
|
if value == initial
|
189
|
-
|
189
|
+
_changed_columns.delete(column) unless missing_initial_values.include?(column)
|
190
190
|
iv.delete(column)
|
191
191
|
end
|
192
192
|
else
|
@@ -58,13 +58,20 @@ module Sequel
|
|
58
58
|
# Detect which columns have been modified by comparing the cached hash
|
59
59
|
# value to the hash of the current value.
|
60
60
|
def changed_columns
|
61
|
-
|
62
|
-
changed = []
|
63
|
-
v = @values
|
61
|
+
changed = super
|
64
62
|
if vh = @values_hashes
|
65
|
-
|
63
|
+
values = @values
|
64
|
+
changed = changed.dup if frozen?
|
65
|
+
vh.each do |c, v|
|
66
|
+
match = values.has_key?(c) && v == values[c].hash
|
67
|
+
if changed.include?(c)
|
68
|
+
changed.delete(c) if match
|
69
|
+
else
|
70
|
+
changed << c unless match
|
71
|
+
end
|
72
|
+
end
|
66
73
|
end
|
67
|
-
|
74
|
+
changed
|
68
75
|
end
|
69
76
|
|
70
77
|
private
|
@@ -75,7 +75,8 @@ module Sequel
|
|
75
75
|
# it to be assigned.
|
76
76
|
def _save_update_all_columns_hash
|
77
77
|
v = @values.dup
|
78
|
-
|
78
|
+
cc = changed_columns
|
79
|
+
Array(primary_key).each{|x| v.delete(x) unless cc.include?(x)}
|
79
80
|
v.delete(model.lock_column)
|
80
81
|
v
|
81
82
|
end
|
@@ -155,8 +155,9 @@ module Sequel
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
define_method("#{column}=") do |v|
|
158
|
-
|
159
|
-
|
158
|
+
cc = changed_columns
|
159
|
+
if !cc.include?(column) && (new? || get_column_value(column) != v)
|
160
|
+
cc << column
|
160
161
|
|
161
162
|
will_change_column(column) if respond_to?(:will_change_column)
|
162
163
|
end
|
@@ -252,7 +252,8 @@ module Sequel
|
|
252
252
|
atts.each do |a|
|
253
253
|
arr = Array(a)
|
254
254
|
next if arr.any?{|x| errors.on(x)}
|
255
|
-
|
255
|
+
cc = changed_columns
|
256
|
+
next if opts.fetch(:only_if_modified, true) && !new? && !arr.any?{|x| cc.include?(x)}
|
256
257
|
ds = opts[:dataset] || model.dataset
|
257
258
|
ds = if where
|
258
259
|
where.call(ds, self, arr)
|
data/lib/sequel/version.rb
CHANGED
@@ -5,7 +5,7 @@ module Sequel
|
|
5
5
|
MAJOR = 5
|
6
6
|
# The minor version of Sequel. Bumped for every non-patch level
|
7
7
|
# release, generally around once a month.
|
8
|
-
MINOR =
|
8
|
+
MINOR = 5
|
9
9
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
10
10
|
# releases that fix regressions from previous versions.
|
11
11
|
TINY = 0
|
@@ -523,11 +523,6 @@ describe "A PostgreSQL dataset" do
|
|
523
523
|
@db[:atest].get(Sequel.extract(:year, :t)).must_equal 2010
|
524
524
|
end
|
525
525
|
|
526
|
-
it "should be able to parse the default value for an interval type" do
|
527
|
-
@db.create_table!(:atest){interval :t, :default=>'1 week'}
|
528
|
-
@db.schema(:atest).first.last[:ruby_default].must_equal '7 days'
|
529
|
-
end
|
530
|
-
|
531
526
|
it "should have #transaction support various types of synchronous options" do
|
532
527
|
@db.transaction(:synchronous=>:on){}
|
533
528
|
@db.transaction(:synchronous=>true){}
|
@@ -1877,6 +1872,11 @@ if uses_pg_or_jdbc && DB.server_version >= 90000
|
|
1877
1872
|
e.wrapped_exception.must_be_kind_of ArgumentError
|
1878
1873
|
e.message.must_include "foo"
|
1879
1874
|
end
|
1875
|
+
|
1876
|
+
it "should handle errors raised during row processing" do
|
1877
|
+
proc{@db.copy_table(@db[:test_copy].select(Sequel[1]/(Sequel[:x] - 3)))}.must_raise Sequel::DatabaseError
|
1878
|
+
@db.get(1).must_equal 1
|
1879
|
+
end
|
1880
1880
|
end
|
1881
1881
|
end
|
1882
1882
|
|
@@ -2362,6 +2362,19 @@ describe 'PostgreSQL array handling' do
|
|
2362
2362
|
c.where(:i=>o2.i, :f=>o2.f, :d=>o2.d, :t=>o2.t).all.must_equal [o]
|
2363
2363
|
end
|
2364
2364
|
|
2365
|
+
it 'with empty array default values and defaults_setter plugin' do
|
2366
|
+
@db.create_table!(:items) do
|
2367
|
+
column :n, 'integer[]', :default=>[]
|
2368
|
+
end
|
2369
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
2370
|
+
c.plugin :defaults_setter, :cache=>true
|
2371
|
+
o = c.new
|
2372
|
+
o.n.class.must_equal(Sequel::Postgres::PGArray)
|
2373
|
+
o.n.to_a.must_be_same_as(o.n.to_a)
|
2374
|
+
o.n << 1
|
2375
|
+
o.save.n.must_equal [1]
|
2376
|
+
end
|
2377
|
+
|
2365
2378
|
it 'operations/functions with pg_array_ops' do
|
2366
2379
|
Sequel.extension :pg_array_ops
|
2367
2380
|
@db.create_table!(:items){column :i, 'integer[]'; column :i2, 'integer[]'; column :i3, 'integer[]'; column :i4, 'integer[]'; column :i5, 'integer[]'}
|
@@ -2599,6 +2612,19 @@ describe 'PostgreSQL hstore handling' do
|
|
2599
2612
|
c.filter(:mtm_items=>c.filter(:id=>o.id)).all.must_equal [o]
|
2600
2613
|
end
|
2601
2614
|
|
2615
|
+
it 'with empty hstore default values and defaults_setter plugin' do
|
2616
|
+
@db.create_table!(:items) do
|
2617
|
+
hstore :h, :default=>Sequel.hstore({})
|
2618
|
+
end
|
2619
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
2620
|
+
c.plugin :defaults_setter, :cache=>true
|
2621
|
+
o = c.new
|
2622
|
+
o.h.class.must_equal(Sequel::Postgres::HStore)
|
2623
|
+
o.h.to_hash.must_be_same_as(o.h.to_hash)
|
2624
|
+
o.h['a'] = 'b'
|
2625
|
+
o.save.h.must_equal('a'=>'b')
|
2626
|
+
end
|
2627
|
+
|
2602
2628
|
it 'operations/functions with pg_hstore_ops' do
|
2603
2629
|
Sequel.extension :pg_hstore_ops, :pg_array_ops
|
2604
2630
|
@db.create_table!(:items){hstore :h1; hstore :h2; hstore :h3; String :t}
|
@@ -2695,11 +2721,10 @@ describe 'PostgreSQL json type' do
|
|
2695
2721
|
json_types.each do |json_type|
|
2696
2722
|
json_array_type = "#{json_type}[]"
|
2697
2723
|
pg_json = lambda{|v| Sequel.send(:"pg_#{json_type}", v)}
|
2724
|
+
hash_class = json_type == :jsonb ? Sequel::Postgres::JSONBHash : Sequel::Postgres::JSONHash
|
2725
|
+
array_class = json_type == :jsonb ? Sequel::Postgres::JSONBArray : Sequel::Postgres::JSONArray
|
2698
2726
|
|
2699
2727
|
it 'insert and retrieve json values' do
|
2700
|
-
hash_class = json_type == :jsonb ? Sequel::Postgres::JSONBHash : Sequel::Postgres::JSONHash
|
2701
|
-
array_class = json_type == :jsonb ? Sequel::Postgres::JSONBArray : Sequel::Postgres::JSONArray
|
2702
|
-
|
2703
2728
|
@db.create_table!(:items){column :j, json_type}
|
2704
2729
|
@ds.insert(pg_json.call(@h))
|
2705
2730
|
@ds.count.must_equal 1
|
@@ -2753,6 +2778,25 @@ describe 'PostgreSQL json type' do
|
|
2753
2778
|
c.create(:h=>pg_json.call(@a)).h.must_equal @a
|
2754
2779
|
end
|
2755
2780
|
|
2781
|
+
it 'with empty json default values and defaults_setter plugin' do
|
2782
|
+
@db.create_table!(:items) do
|
2783
|
+
column :h, json_type, :default=>hash_class.new({})
|
2784
|
+
column :a, json_type, :default=>array_class.new([])
|
2785
|
+
end
|
2786
|
+
c = Class.new(Sequel::Model(@db[:items]))
|
2787
|
+
c.plugin :defaults_setter, :cache=>true
|
2788
|
+
o = c.new
|
2789
|
+
o.h.class.must_equal(hash_class)
|
2790
|
+
o.a.class.must_equal(array_class)
|
2791
|
+
o.h.to_hash.must_be_same_as(o.h.to_hash)
|
2792
|
+
o.a.to_a.must_be_same_as(o.a.to_a)
|
2793
|
+
o.h['a'] = 'b'
|
2794
|
+
o.a << 1
|
2795
|
+
o.save
|
2796
|
+
o.h.must_equal('a'=>'b')
|
2797
|
+
o.a.must_equal([1])
|
2798
|
+
end
|
2799
|
+
|
2756
2800
|
it 'use json in bound variables' do
|
2757
2801
|
@db.create_table!(:items){column :i, json_type}
|
2758
2802
|
@ds.call(:insert, {:i=>pg_json.call(@h)}, {:i=>:$i})
|
@@ -2956,6 +3000,15 @@ describe 'PostgreSQL inet/cidr types' do
|
|
2956
3000
|
@ds.filter(:i=>:$i, :c=>:$c, :m=>:$m).call(:delete, :i=>[@ipv4], :c=>[@ipv4nm], :m=>['12:34:56:78:90:ab']).must_equal 1
|
2957
3001
|
end if uses_pg_or_jdbc
|
2958
3002
|
|
3003
|
+
it 'parse default values for schema' do
|
3004
|
+
@db.create_table!(:items) do
|
3005
|
+
inet :i, :default=>IPAddr.new('127.0.0.1')
|
3006
|
+
cidr :c, :default=>IPAddr.new('127.0.0.1')
|
3007
|
+
end
|
3008
|
+
@db.schema(:items)[0][1][:ruby_default].must_equal IPAddr.new('127.0.0.1')
|
3009
|
+
@db.schema(:items)[1][1][:ruby_default].must_equal IPAddr.new('127.0.0.1')
|
3010
|
+
end
|
3011
|
+
|
2959
3012
|
it 'with models' do
|
2960
3013
|
@db.create_table!(:items) do
|
2961
3014
|
primary_key :id
|
@@ -3113,6 +3166,15 @@ describe 'PostgreSQL range types' do
|
|
3113
3166
|
@ds.filter(h).call(:delete, @ra).must_equal 1
|
3114
3167
|
end if uses_pg_or_jdbc
|
3115
3168
|
|
3169
|
+
it 'parse default values for schema' do
|
3170
|
+
@db.create_table!(:items) do
|
3171
|
+
Integer :j
|
3172
|
+
int4range :i, :default=>1..4
|
3173
|
+
end
|
3174
|
+
@db.schema(:items)[0][1][:ruby_default].must_be_nil
|
3175
|
+
@db.schema(:items)[1][1][:ruby_default].must_equal Sequel::Postgres::PGRange.new(1, 5, :exclude_end=>true, :db_type=>'int4range')
|
3176
|
+
end
|
3177
|
+
|
3116
3178
|
it 'with models' do
|
3117
3179
|
@db.create_table!(:items){primary_key :id; int4range :i4; int8range :i8; numrange :n; daterange :d; tsrange :t; tstzrange :tz}
|
3118
3180
|
c = Class.new(Sequel::Model(@db[:items]))
|
@@ -3282,6 +3344,15 @@ describe 'PostgreSQL interval types' do
|
|
3282
3344
|
@ds.filter(:i=>:$i).call(:delete, :i=>[d]).must_equal 1
|
3283
3345
|
end if uses_pg_or_jdbc
|
3284
3346
|
|
3347
|
+
it 'parse default values for schema' do
|
3348
|
+
@db.create_table!(:items) do
|
3349
|
+
Integer :j
|
3350
|
+
interval :i, :default=>ActiveSupport::Duration.new(3*86400, :days=>3)
|
3351
|
+
end
|
3352
|
+
@db.schema(:items)[0][1][:ruby_default].must_be_nil
|
3353
|
+
@db.schema(:items)[1][1][:ruby_default].must_equal ActiveSupport::Duration.new(3*86400, :days=>3)
|
3354
|
+
end
|
3355
|
+
|
3285
3356
|
it 'with models' do
|
3286
3357
|
@db.create_table!(:items) do
|
3287
3358
|
primary_key :id
|
data/spec/core/schema_spec.rb
CHANGED
@@ -1619,6 +1619,16 @@ describe "Schema Parser" do
|
|
1619
1619
|
@db.schema(:x).wont_be_same_as(@db.schema(:x))
|
1620
1620
|
end
|
1621
1621
|
|
1622
|
+
it "should freeze string values in resulting hash" do
|
1623
|
+
@db.define_singleton_method(:schema_parse_table) do |t, opts|
|
1624
|
+
[[:a, {:oid=>1, :db_type=>'integer'.dup, :default=>"'a'".dup, :ruby_default=>'a'.dup}]]
|
1625
|
+
end
|
1626
|
+
c = @db.schema(:x)[0][1]
|
1627
|
+
c[:db_type].frozen?.must_equal true
|
1628
|
+
c[:default].frozen?.must_equal true
|
1629
|
+
c[:ruby_default].frozen?.must_equal true
|
1630
|
+
end
|
1631
|
+
|
1622
1632
|
it "should provide options if given a table name" do
|
1623
1633
|
c = nil
|
1624
1634
|
@db.define_singleton_method(:schema_parse_table) do |t, opts|
|
@@ -41,6 +41,15 @@ describe "Sequel::Plugins::DefaultsSetter" do
|
|
41
41
|
(t - Time.now).must_be :<, 1
|
42
42
|
end
|
43
43
|
|
44
|
+
it "should handle :callable_default values in schema in preference to :ruby_default" do
|
45
|
+
@db.define_singleton_method(:schema) do |*|
|
46
|
+
[[:id, {:primary_key=>true}],
|
47
|
+
[:a, {:ruby_default => Time.now, :callable_default=>lambda{Date.today}, :primary_key=>false}]]
|
48
|
+
end
|
49
|
+
@c.dataset = @c.dataset
|
50
|
+
@c.new.a.must_equal Date.today
|
51
|
+
end
|
52
|
+
|
44
53
|
it "should handle Sequel::CURRENT_TIMESTAMP default by using the current DateTime if Sequel.datetime_class is DateTime" do
|
45
54
|
Sequel.datetime_class = DateTime
|
46
55
|
t = @pr.call(Sequel::CURRENT_TIMESTAMP).new.a
|
@@ -60,6 +69,15 @@ describe "Sequel::Plugins::DefaultsSetter" do
|
|
60
69
|
@db.sqls.must_equal ["INSERT INTO foo (a) VALUES (CURRENT_TIMESTAMP)", "SELECT * FROM foo WHERE id = 1"]
|
61
70
|
end
|
62
71
|
|
72
|
+
it "should cache default values if :cache plugin option is used" do
|
73
|
+
@c.plugin :defaults_setter, :cache => true
|
74
|
+
@c.default_values[:a] = 'a'
|
75
|
+
o = @c.new
|
76
|
+
o.a.must_equal 'a'
|
77
|
+
o.values[:a].must_equal 'a'
|
78
|
+
o.a.must_be_same_as(o.a)
|
79
|
+
end
|
80
|
+
|
63
81
|
it "should not override a given value" do
|
64
82
|
@pr.call(2)
|
65
83
|
@c.new('a'=>3).a.must_equal 3
|
@@ -11,6 +11,13 @@ describe "serialization_modification_detection plugin" do
|
|
11
11
|
@ds.db.sqls
|
12
12
|
end
|
13
13
|
|
14
|
+
it "should detect setting new column values on new objects" do
|
15
|
+
@o = @c.new
|
16
|
+
@o.changed_columns.must_equal []
|
17
|
+
@o.a = 'c'
|
18
|
+
@o.changed_columns.must_equal [:a]
|
19
|
+
end
|
20
|
+
|
14
21
|
it "should only detect columns that have been changed" do
|
15
22
|
@o.changed_columns.must_equal []
|
16
23
|
@o.a << 'b'
|
@@ -32,6 +39,12 @@ describe "serialization_modification_detection plugin" do
|
|
32
39
|
@o.changed_columns.must_equal []
|
33
40
|
end
|
34
41
|
|
42
|
+
it "should detect columns that have been changed on frozen objects" do
|
43
|
+
@o.freeze
|
44
|
+
@o.a << 'b'
|
45
|
+
@o.changed_columns.must_equal [:a]
|
46
|
+
end
|
47
|
+
|
35
48
|
it "should not list a column twice" do
|
36
49
|
@o.a = 'b'.dup
|
37
50
|
@o.a << 'a'
|
@@ -209,6 +209,17 @@ describe "pg_array extension" do
|
|
209
209
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :integer_array, :real_array, :decimal_array, :string_array]
|
210
210
|
end
|
211
211
|
|
212
|
+
it "should set :callable_default schema entries if default value is recognized" do
|
213
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'t', :db_type=>'text[]', :default=>"'{}'::text[]"}]
|
214
|
+
s = @db.schema(:items)
|
215
|
+
s[0][1][:callable_default].must_be_nil
|
216
|
+
v = s[1][1][:callable_default].call
|
217
|
+
Sequel::Postgres::PGArray.===(v).must_equal true
|
218
|
+
@db.literal(v).must_equal "'{}'::text[]"
|
219
|
+
v << 'a'
|
220
|
+
@db.literal(v).must_equal "ARRAY['a']::text[]"
|
221
|
+
end
|
222
|
+
|
212
223
|
it "should support typecasting of the various array types" do
|
213
224
|
{
|
214
225
|
:integer=>{:class=>Integer, :convert=>['1', 1, '1']},
|
@@ -186,6 +186,17 @@ describe "pg_hstore extension" do
|
|
186
186
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :hstore]
|
187
187
|
end
|
188
188
|
|
189
|
+
it "should set :callable_default schema entries if default value is recognized" do
|
190
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'t', :db_type=>'hstore', :default=>"''::hstore"}]
|
191
|
+
s = @db.schema(:items)
|
192
|
+
s[0][1][:callable_default].must_be_nil
|
193
|
+
v = s[1][1][:callable_default].call
|
194
|
+
Sequel::Postgres::HStore.===(v).must_equal true
|
195
|
+
@db.literal(v).must_equal "''::hstore"
|
196
|
+
v['a'] = 'b'
|
197
|
+
@db.literal(v).must_equal "'\"a\"=>\"b\"'::hstore"
|
198
|
+
end
|
199
|
+
|
189
200
|
it "should support typecasting for the hstore type" do
|
190
201
|
h = Sequel.hstore(1=>2)
|
191
202
|
@db.typecast_value(:hstore, h).object_id.must_equal(h.object_id)
|
@@ -51,6 +51,12 @@ describe "pg_inet extension" do
|
|
51
51
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :ipaddr, :ipaddr]
|
52
52
|
end
|
53
53
|
|
54
|
+
it "should set :ruby_default schema entries if default value is recognized" do
|
55
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'t', :db_type=>'inet', :default=>"'127.0.0.1'::inet"}]
|
56
|
+
s = @db.schema(:items)
|
57
|
+
s[1][1][:ruby_default].must_equal IPAddr.new('127.0.0.1')
|
58
|
+
end
|
59
|
+
|
54
60
|
it "should support typecasting for the ipaddr type" do
|
55
61
|
ip = IPAddr.new('127.0.0.1')
|
56
62
|
@db.typecast_value(:ipaddr, ip).must_be_same_as(ip)
|
@@ -66,6 +66,12 @@ describe "pg_interval extension" do
|
|
66
66
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :interval]
|
67
67
|
end
|
68
68
|
|
69
|
+
it "should set :ruby_default schema entries if default value is recognized" do
|
70
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'t', :db_type=>'interval', :default=>"'3 days'::interval"}]
|
71
|
+
s = @db.schema(:items)
|
72
|
+
s[1][1][:ruby_default].must_equal ActiveSupport::Duration.new(3*86400, :days=>3)
|
73
|
+
end
|
74
|
+
|
69
75
|
it "should support typecasting for the interval type" do
|
70
76
|
d = ActiveSupport::Duration.new(31557600 + 2*86400*30 + 3*86400*7 + 4*86400 + 5*3600 + 6*60 + 7, [[:years, 1], [:months, 2], [:days, 25], [:seconds, 18367]])
|
71
77
|
@db.typecast_value(:interval, d).object_id.must_equal d.object_id
|
@@ -183,6 +183,35 @@ describe "pg_json extension" do
|
|
183
183
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :jsonb]
|
184
184
|
end
|
185
185
|
|
186
|
+
it "should set :callable_default schema entries if default value is recognized" do
|
187
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:name=>'jh', :db_type=>'json', :default=>"'{}'::json"}, {:name=>'ja', :db_type=>'json', :default=>"'[]'::json"}, {:name=>'jbh', :db_type=>'jsonb', :default=>"'{}'::jsonb"}, {:name=>'jba', :db_type=>'jsonb', :default=>"'[]'::jsonb"}]
|
188
|
+
s = @db.schema(:items)
|
189
|
+
s[0][1][:callable_default].must_be_nil
|
190
|
+
v = s[1][1][:callable_default].call
|
191
|
+
Sequel::Postgres::JSONHash.===(v).must_equal true
|
192
|
+
@db.literal(v).must_equal "'{}'::json"
|
193
|
+
v['a'] = 'b'
|
194
|
+
@db.literal(v).must_equal "'{\"a\":\"b\"}'::json"
|
195
|
+
|
196
|
+
v = s[2][1][:callable_default].call
|
197
|
+
Sequel::Postgres::JSONArray.===(v).must_equal true
|
198
|
+
@db.literal(v).must_equal "'[]'::json"
|
199
|
+
v << 1
|
200
|
+
@db.literal(v).must_equal "'[1]'::json"
|
201
|
+
|
202
|
+
v = s[3][1][:callable_default].call
|
203
|
+
Sequel::Postgres::JSONBHash.===(v).must_equal true
|
204
|
+
@db.literal(v).must_equal "'{}'::jsonb"
|
205
|
+
v['a'] = 'b'
|
206
|
+
@db.literal(v).must_equal "'{\"a\":\"b\"}'::jsonb"
|
207
|
+
|
208
|
+
v = s[4][1][:callable_default].call
|
209
|
+
Sequel::Postgres::JSONBArray.===(v).must_equal true
|
210
|
+
@db.literal(v).must_equal "'[]'::jsonb"
|
211
|
+
v << 1
|
212
|
+
@db.literal(v).must_equal "'[1]'::jsonb"
|
213
|
+
end
|
214
|
+
|
186
215
|
it "should support typecasting for the json type" do
|
187
216
|
h = Sequel.pg_json(1=>2)
|
188
217
|
a = Sequel.pg_json([1])
|
@@ -93,6 +93,12 @@ describe "pg_range extension" do
|
|
93
93
|
@db.schema(:items).map{|e| e[1][:type]}.must_equal [:integer, :int4range_array, :int8range_array, :numrange_array, :daterange_array, :tsrange_array, :tstzrange_array]
|
94
94
|
end
|
95
95
|
|
96
|
+
it "should set :ruby_default schema entries if default value is recognized" do
|
97
|
+
@db.fetch = [{:name=>'id', :db_type=>'integer', :default=>'1'}, {:oid=>3904, :name=>'t', :db_type=>'int4range', :default=>"'[1,5)'::int4range"}]
|
98
|
+
s = @db.schema(:items)
|
99
|
+
s[1][1][:ruby_default].must_equal Sequel::Postgres::PGRange.new(1, 5, :exclude_end=>true, :db_type=>'int4range')
|
100
|
+
end
|
101
|
+
|
96
102
|
describe "database typecasting" do
|
97
103
|
before do
|
98
104
|
@o = @R.new(1, 2, :db_type=>'int4range')
|
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.5.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-01-
|
11
|
+
date: 2018-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -255,6 +255,7 @@ extra_rdoc_files:
|
|
255
255
|
- doc/release_notes/5.2.0.txt
|
256
256
|
- doc/release_notes/5.3.0.txt
|
257
257
|
- doc/release_notes/5.4.0.txt
|
258
|
+
- doc/release_notes/5.5.0.txt
|
258
259
|
files:
|
259
260
|
- CHANGELOG
|
260
261
|
- MIT-LICENSE
|
@@ -404,6 +405,7 @@ files:
|
|
404
405
|
- doc/release_notes/5.2.0.txt
|
405
406
|
- doc/release_notes/5.3.0.txt
|
406
407
|
- doc/release_notes/5.4.0.txt
|
408
|
+
- doc/release_notes/5.5.0.txt
|
407
409
|
- doc/schema_modification.rdoc
|
408
410
|
- doc/security.rdoc
|
409
411
|
- doc/sharding.rdoc
|