sequel 4.47.0 → 4.48.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +134 -0
- data/Rakefile +1 -1
- data/doc/release_notes/4.48.0.txt +293 -0
- data/lib/sequel/adapters/ado/access.rb +2 -1
- data/lib/sequel/adapters/do/postgres.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +24 -7
- data/lib/sequel/adapters/jdbc.rb +36 -22
- data/lib/sequel/adapters/jdbc/db2.rb +12 -3
- data/lib/sequel/adapters/jdbc/derby.rb +4 -5
- data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
- data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
- data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
- data/lib/sequel/adapters/mock.rb +24 -19
- data/lib/sequel/adapters/mysql.rb +17 -16
- data/lib/sequel/adapters/mysql2.rb +4 -5
- data/lib/sequel/adapters/oracle.rb +5 -9
- data/lib/sequel/adapters/postgres.rb +89 -102
- data/lib/sequel/adapters/shared/db2.rb +22 -6
- data/lib/sequel/adapters/shared/mssql.rb +5 -4
- data/lib/sequel/adapters/shared/mysql.rb +75 -24
- data/lib/sequel/adapters/shared/postgres.rb +196 -94
- data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
- data/lib/sequel/adapters/shared/sqlite.rb +72 -82
- data/lib/sequel/adapters/sqlanywhere.rb +4 -1
- data/lib/sequel/adapters/sqlite.rb +5 -3
- data/lib/sequel/adapters/swift/postgres.rb +5 -2
- data/lib/sequel/adapters/tinytds.rb +0 -5
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/adapters/utils/pg_types.rb +2 -76
- data/lib/sequel/core.rb +2 -2
- data/lib/sequel/database/connecting.rb +5 -5
- data/lib/sequel/database/dataset.rb +6 -3
- data/lib/sequel/database/misc.rb +1 -1
- data/lib/sequel/database/query.rb +3 -0
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset/actions.rb +18 -10
- data/lib/sequel/dataset/graph.rb +1 -1
- data/lib/sequel/dataset/misc.rb +1 -0
- data/lib/sequel/dataset/prepared_statements.rb +3 -3
- data/lib/sequel/dataset/query.rb +19 -8
- data/lib/sequel/extensions/core_extensions.rb +4 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
- data/lib/sequel/extensions/filter_having.rb +2 -0
- data/lib/sequel/extensions/freeze_datasets.rb +2 -0
- data/lib/sequel/extensions/from_block.rb +1 -1
- data/lib/sequel/extensions/graph_each.rb +2 -2
- data/lib/sequel/extensions/hash_aliases.rb +2 -0
- data/lib/sequel/extensions/identifier_mangling.rb +0 -7
- data/lib/sequel/extensions/meta_def.rb +2 -0
- data/lib/sequel/extensions/migration.rb +6 -6
- data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +207 -130
- data/lib/sequel/extensions/pg_hstore.rb +38 -20
- data/lib/sequel/extensions/pg_inet.rb +18 -6
- data/lib/sequel/extensions/pg_interval.rb +19 -12
- data/lib/sequel/extensions/pg_json.rb +25 -14
- data/lib/sequel/extensions/pg_json_ops.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +133 -100
- data/lib/sequel/extensions/pg_range_ops.rb +4 -3
- data/lib/sequel/extensions/pg_row.rb +68 -39
- data/lib/sequel/extensions/pg_row_ops.rb +11 -5
- data/lib/sequel/extensions/query_literals.rb +2 -0
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
- data/lib/sequel/extensions/s.rb +1 -1
- data/lib/sequel/extensions/schema_dumper.rb +24 -24
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
- data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
- data/lib/sequel/extensions/set_overrides.rb +2 -2
- data/lib/sequel/extensions/string_agg.rb +0 -1
- data/lib/sequel/extensions/symbol_aref.rb +0 -4
- data/lib/sequel/model.rb +25 -57
- data/lib/sequel/model/associations.rb +14 -5
- data/lib/sequel/model/base.rb +96 -32
- data/lib/sequel/plugins/association_pks.rb +73 -46
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/auto_validations.rb +6 -2
- data/lib/sequel/plugins/boolean_readers.rb +1 -1
- data/lib/sequel/plugins/caching.rb +19 -13
- data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
- data/lib/sequel/plugins/column_conflicts.rb +7 -2
- data/lib/sequel/plugins/column_select.rb +1 -1
- data/lib/sequel/plugins/csv_serializer.rb +8 -8
- data/lib/sequel/plugins/defaults_setter.rb +10 -0
- data/lib/sequel/plugins/eager_each.rb +1 -1
- data/lib/sequel/plugins/force_encoding.rb +2 -2
- data/lib/sequel/plugins/hook_class_methods.rb +9 -12
- data/lib/sequel/plugins/identifier_columns.rb +2 -0
- data/lib/sequel/plugins/instance_filters.rb +3 -1
- data/lib/sequel/plugins/instance_hooks.rb +17 -9
- data/lib/sequel/plugins/json_serializer.rb +17 -10
- data/lib/sequel/plugins/lazy_attributes.rb +8 -7
- data/lib/sequel/plugins/modification_detection.rb +3 -0
- data/lib/sequel/plugins/nested_attributes.rb +5 -1
- data/lib/sequel/plugins/pg_array_associations.rb +5 -0
- data/lib/sequel/plugins/prepared_statements.rb +1 -0
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/serialization.rb +3 -10
- data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/split_values.rb +6 -5
- data/lib/sequel/plugins/static_cache.rb +31 -25
- data/lib/sequel/plugins/subset_conditions.rb +3 -1
- data/lib/sequel/plugins/table_select.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -6
- data/lib/sequel/plugins/validation_helpers.rb +2 -4
- data/lib/sequel/plugins/xml_serializer.rb +4 -4
- data/lib/sequel/sql.rb +2 -2
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +115 -14
- data/spec/adapters/mysql_spec.rb +78 -28
- data/spec/adapters/oracle_spec.rb +24 -24
- data/spec/adapters/postgres_spec.rb +38 -24
- data/spec/adapters/sqlanywhere_spec.rb +88 -86
- data/spec/adapters/sqlite_spec.rb +29 -24
- data/spec/core/connection_pool_spec.rb +17 -0
- data/spec/core/database_spec.rb +6 -0
- data/spec/core/dataset_spec.rb +46 -36
- data/spec/core/schema_spec.rb +16 -0
- data/spec/core/spec_helper.rb +1 -0
- data/spec/core_extensions_spec.rb +6 -2
- data/spec/extensions/active_model_spec.rb +1 -1
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +34 -2
- data/spec/extensions/auto_literal_strings_spec.rb +5 -1
- data/spec/extensions/auto_validations_spec.rb +2 -0
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/boolean_subsets_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +48 -2
- data/spec/extensions/column_conflicts_spec.rb +11 -0
- data/spec/extensions/connection_validator_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +8 -8
- data/spec/extensions/defaults_setter_spec.rb +1 -1
- data/spec/extensions/filter_having_spec.rb +5 -3
- data/spec/extensions/hash_aliases_spec.rb +3 -1
- data/spec/extensions/identifier_columns_spec.rb +3 -1
- data/spec/extensions/implicit_subquery_spec.rb +4 -2
- data/spec/extensions/json_serializer_spec.rb +18 -0
- data/spec/extensions/lazy_attributes_spec.rb +3 -3
- data/spec/extensions/meta_def_spec.rb +9 -0
- data/spec/extensions/migration_spec.rb +3 -3
- data/spec/extensions/nested_attributes_spec.rb +14 -3
- data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
- data/spec/extensions/pg_array_associations_spec.rb +29 -18
- data/spec/extensions/pg_array_spec.rb +44 -25
- data/spec/extensions/pg_hstore_spec.rb +10 -0
- data/spec/extensions/pg_inet_spec.rb +26 -0
- data/spec/extensions/pg_interval_spec.rb +20 -0
- data/spec/extensions/pg_json_spec.rb +24 -0
- data/spec/extensions/pg_range_spec.rb +98 -14
- data/spec/extensions/pg_row_spec.rb +14 -4
- data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +3 -1
- data/spec/extensions/schema_dumper_spec.rb +96 -98
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
- data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -1
- data/spec/extensions/static_cache_spec.rb +75 -24
- data/spec/extensions/string_agg_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +9 -0
- data/spec/extensions/validation_helpers_spec.rb +9 -3
- data/spec/extensions/whitelist_security_spec.rb +26 -0
- data/spec/integration/dataset_test.rb +45 -44
- data/spec/integration/plugin_test.rb +20 -0
- data/spec/integration/prepared_statement_test.rb +3 -0
- data/spec/integration/schema_test.rb +21 -1
- data/spec/integration/transaction_test.rb +40 -40
- data/spec/model/class_dataset_methods_spec.rb +14 -4
- data/spec/model/dataset_methods_spec.rb +12 -3
- data/spec/model/model_spec.rb +8 -0
- metadata +6 -4
- data/spec/adapters/firebird_spec.rb +0 -405
- data/spec/adapters/informix_spec.rb +0 -100
@@ -41,6 +41,17 @@ module Sequel
|
|
41
41
|
# If set to :remove, the setter will treat the nil as an empty array, removing
|
42
42
|
# the association all currently associated values.
|
43
43
|
#
|
44
|
+
# For many_to_many associations, association_pks assumes the related pks can be
|
45
|
+
# accessed directly from the join table. This works in most cases, but in cases
|
46
|
+
# where the :right_primary_key association option is used to specify a different
|
47
|
+
# primary key in the associated table, association_pks will return the value of
|
48
|
+
# the association primary keys (foreign key values to associated table in the join
|
49
|
+
# table), not the associated model primary keys. If you would like to use the
|
50
|
+
# associated model primary keys, you need to use the
|
51
|
+
# :association_pks_use_associated_table association option. If the
|
52
|
+
# :association_pks_use_associated_table association option is used, no setter
|
53
|
+
# method will be added.
|
54
|
+
#
|
44
55
|
# Usage:
|
45
56
|
#
|
46
57
|
# # Make all model subclass *_to_many associations have association_pks
|
@@ -57,7 +68,7 @@ module Sequel
|
|
57
68
|
# Define a association_pks method using the block for the association reflection
|
58
69
|
def def_association_pks_methods(opts)
|
59
70
|
association_module_def(:"#{singularize(opts[:name])}_pks", opts){_association_pks_getter(opts)}
|
60
|
-
association_module_def(:"#{singularize(opts[:name])}_pks=", opts){|pks| _association_pks_setter(opts, pks)}
|
71
|
+
association_module_def(:"#{singularize(opts[:name])}_pks=", opts){|pks| _association_pks_setter(opts, pks)} if opts[:pks_setter]
|
61
72
|
end
|
62
73
|
|
63
74
|
# Add a getter that checks the join table for matching records and
|
@@ -73,11 +84,23 @@ module Sequel
|
|
73
84
|
clpk = lpk.is_a?(Array)
|
74
85
|
crk = rk.is_a?(Array)
|
75
86
|
|
76
|
-
opts[:pks_getter] = if
|
87
|
+
opts[:pks_getter] = if join_associated_table = opts[:association_pks_use_associated_table]
|
88
|
+
tname = opts[:join_table]
|
89
|
+
lambda do
|
90
|
+
cond = if clpk
|
91
|
+
lk.zip(lpk).map{|k, pk| [Sequel.qualify(tname, k), get_column_value(pk)]}
|
92
|
+
else
|
93
|
+
{Sequel.qualify(tname, lk) => get_column_value(lpk)}
|
94
|
+
end
|
95
|
+
rpk = opts.associated_class.primary_key
|
96
|
+
opts.associated_dataset.
|
97
|
+
naked.where(cond).
|
98
|
+
select_map(Sequel.send(rpk.is_a?(Array) ? :deep_qualify : :qualify, opts.associated_class.table_name, rpk))
|
99
|
+
end
|
100
|
+
elsif clpk
|
77
101
|
lambda do
|
78
|
-
|
79
|
-
|
80
|
-
_join_table_dataset(opts).where(h).select_map(rk)
|
102
|
+
cond = lk.zip(lpk).map{|k, pk| [k, get_column_value(pk)]}
|
103
|
+
_join_table_dataset(opts).where(cond).select_map(rk)
|
81
104
|
end
|
82
105
|
else
|
83
106
|
lambda do
|
@@ -85,25 +108,27 @@ module Sequel
|
|
85
108
|
end
|
86
109
|
end
|
87
110
|
|
88
|
-
opts[:
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
111
|
+
if !opts[:read_only] && !join_associated_table
|
112
|
+
opts[:pks_setter] = lambda do |pks|
|
113
|
+
if pks.empty?
|
114
|
+
send(opts.remove_all_method)
|
115
|
+
else
|
116
|
+
checked_transaction do
|
117
|
+
if clpk
|
118
|
+
lpkv = lpk.map{|k| get_column_value(k)}
|
119
|
+
cond = lk.zip(lpkv)
|
120
|
+
else
|
121
|
+
lpkv = get_column_value(lpk)
|
122
|
+
cond = {lk=>lpkv}
|
123
|
+
end
|
124
|
+
ds = _join_table_dataset(opts).where(cond)
|
125
|
+
ds.exclude(rk=>pks).delete
|
126
|
+
pks -= ds.select_map(rk)
|
127
|
+
lpkv = Array(lpkv)
|
128
|
+
key_array = crk ? pks.map{|pk| lpkv + pk} : pks.map{|pk| lpkv + [pk]}
|
129
|
+
key_columns = Array(lk) + Array(rk)
|
130
|
+
ds.import(key_columns, key_array)
|
99
131
|
end
|
100
|
-
ds = _join_table_dataset(opts).where(cond)
|
101
|
-
ds.exclude(rk=>pks).delete
|
102
|
-
pks -= ds.select_map(rk)
|
103
|
-
lpkv = Array(lpkv)
|
104
|
-
key_array = crk ? pks.map{|pk| lpkv + pk} : pks.map{|pk| lpkv + [pk]}
|
105
|
-
key_columns = Array(lk) + Array(rk)
|
106
|
-
ds.import(key_columns, key_array)
|
107
132
|
end
|
108
133
|
end
|
109
134
|
end
|
@@ -124,29 +149,31 @@ module Sequel
|
|
124
149
|
send(opts.dataset_method).select_map(opts.associated_class.primary_key)
|
125
150
|
end
|
126
151
|
|
127
|
-
opts[:
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
primary_key = opts.associated_class.primary_key
|
132
|
-
pkh = {primary_key=>pks}
|
133
|
-
|
134
|
-
if key.is_a?(Array)
|
135
|
-
h = {}
|
136
|
-
nh = {}
|
137
|
-
key.zip(pk).each do|k, v|
|
138
|
-
h[k] = v
|
139
|
-
nh[k] = nil
|
140
|
-
end
|
152
|
+
unless opts[:read_only]
|
153
|
+
opts[:pks_setter] = lambda do |pks|
|
154
|
+
if pks.empty?
|
155
|
+
send(opts.remove_all_method)
|
141
156
|
else
|
142
|
-
|
143
|
-
|
144
|
-
end
|
157
|
+
primary_key = opts.associated_class.primary_key
|
158
|
+
pkh = {primary_key=>pks}
|
145
159
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
160
|
+
if key.is_a?(Array)
|
161
|
+
h = {}
|
162
|
+
nh = {}
|
163
|
+
key.zip(pk).each do|k, v|
|
164
|
+
h[k] = v
|
165
|
+
nh[k] = nil
|
166
|
+
end
|
167
|
+
else
|
168
|
+
h = {key=>pk}
|
169
|
+
nh = {key=>nil}
|
170
|
+
end
|
171
|
+
|
172
|
+
checked_transaction do
|
173
|
+
ds = send(opts.dataset_method)
|
174
|
+
ds.unfiltered.where(pkh).update(h)
|
175
|
+
ds.exclude(pkh).update(nh)
|
176
|
+
end
|
150
177
|
end
|
151
178
|
end
|
152
179
|
end
|
@@ -208,7 +235,7 @@ module Sequel
|
|
208
235
|
pks = convert_pk_array(opts, pks)
|
209
236
|
|
210
237
|
delay = opts.fetch(:delay_pks) do
|
211
|
-
Sequel::Deprecation.deprecate("association_pks will default to assuming the :delay_pks=>:always association option starting in Sequel 5. Explicitly set :delay_pks=>false option for the association if you want changes to take effect immediately instead of being delayed until the object is saved (association: #{opts.inspect})
|
238
|
+
Sequel::Deprecation.deprecate("association_pks will default to assuming the :delay_pks=>:always association option starting in Sequel 5. Explicitly set :delay_pks=>false option for the association if you want changes to take effect immediately instead of being delayed until the object is saved (association: #{opts.inspect})")
|
212
239
|
false
|
213
240
|
end
|
214
241
|
if (new? && delay) || (delay == :always)
|
@@ -216,7 +243,7 @@ module Sequel
|
|
216
243
|
(@_association_pks ||= {})[opts[:name]] = pks
|
217
244
|
else
|
218
245
|
if !new? && delay && delay != :always
|
219
|
-
Sequel::Deprecation.deprecate("association_pks with the :delay_pks=>true association option will also delay setting of associated values for existing objects in Sequel 5 (currently it just delays setting of associated values for new objects). Please change to using :delay_pks=>:always to avoid this message. Sequel 5 will not support the existing :delay_pks=>true behavior for only delaying for new objects and not for existing objects
|
246
|
+
Sequel::Deprecation.deprecate("association_pks with the :delay_pks=>true association option will also delay setting of associated values for existing objects in Sequel 5 (currently it just delays setting of associated values for new objects). Please change to using :delay_pks=>:always to avoid this message. Sequel 5 will not support the existing :delay_pks=>true behavior for only delaying for new objects and not for existing objects")
|
220
247
|
end
|
221
248
|
instance_exec(pks, &opts[:pks_setter])
|
222
249
|
end
|
@@ -101,7 +101,7 @@ module Sequel
|
|
101
101
|
def def_association_method(opts)
|
102
102
|
if opts.returns_array?
|
103
103
|
association_module_def(opts.association_method, opts) do |*dynamic_opts, &block|
|
104
|
-
Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored
|
104
|
+
Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored") if dynamic_opts.length > 1
|
105
105
|
AssociationProxy.new(self, opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
|
106
106
|
end
|
107
107
|
else
|
@@ -140,9 +140,13 @@ module Sequel
|
|
140
140
|
# Skip automatic validations for the given validation type (:not_null, :types, :unique).
|
141
141
|
# If :all is given as the type, skip all auto validations.
|
142
142
|
def skip_auto_validations(type)
|
143
|
-
|
143
|
+
case type
|
144
|
+
when :all
|
144
145
|
[:not_null, :types, :unique, :max_length].each{|v| skip_auto_validations(v)}
|
145
|
-
|
146
|
+
when :not_null
|
147
|
+
auto_validate_not_null_columns.clear
|
148
|
+
auto_validate_explicit_not_null_columns.clear
|
149
|
+
when :types
|
146
150
|
@auto_validate_types = false
|
147
151
|
else
|
148
152
|
send("auto_validate_#{type}_columns").clear
|
@@ -48,7 +48,7 @@ module Sequel
|
|
48
48
|
|
49
49
|
# Add attribute? methods for all of the boolean attributes for this model.
|
50
50
|
def create_boolean_readers
|
51
|
-
im = instance_methods.
|
51
|
+
im = instance_methods.map(&:to_s)
|
52
52
|
if cs = check_non_connection_error(false){columns}
|
53
53
|
cs.each{|c| create_boolean_reader(c) if boolean_attribute?(c) && !im.include?("#{c}?")}
|
54
54
|
end
|
@@ -19,8 +19,13 @@ module Sequel
|
|
19
19
|
# raise an exception for a missing record, so if you use memcached, you will
|
20
20
|
# want to use this option.
|
21
21
|
#
|
22
|
-
# Note that only
|
23
|
-
#
|
22
|
+
# Note that only lookups by primary key are cached using this plugin. The following
|
23
|
+
# methods use a lookup by primary key:
|
24
|
+
#
|
25
|
+
# * Model.with_pk
|
26
|
+
# * Model.with_pk!
|
27
|
+
# * Model.[] # when argument is not hash or nil
|
28
|
+
# * many_to_one association method # without dynamic callback, when primary key matches
|
24
29
|
#
|
25
30
|
# Usage:
|
26
31
|
#
|
@@ -68,7 +73,7 @@ module Sequel
|
|
68
73
|
|
69
74
|
# Returns the prefix used to namespace this class in the cache.
|
70
75
|
def cache_key_prefix
|
71
|
-
|
76
|
+
to_s
|
72
77
|
end
|
73
78
|
|
74
79
|
# Return a key string for the given primary key.
|
@@ -86,26 +91,27 @@ module Sequel
|
|
86
91
|
|
87
92
|
private
|
88
93
|
|
89
|
-
#
|
90
|
-
def
|
94
|
+
# Access the cache using the given method and key, rescuing exceptions if necessary.
|
95
|
+
def cache_op(meth, ck)
|
91
96
|
if @cache_ignore_exceptions
|
92
|
-
@cache_store.
|
97
|
+
@cache_store.send(meth, ck) rescue nil
|
93
98
|
else
|
94
|
-
@cache_store.
|
99
|
+
@cache_store.send(meth, ck)
|
95
100
|
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Delete the entry with the matching key from the cache
|
104
|
+
def cache_delete(ck)
|
105
|
+
cache_op(:delete, ck)
|
96
106
|
nil
|
97
107
|
end
|
98
108
|
|
99
109
|
# Returned the cached object, or nil if the object was not
|
100
110
|
# in the cached
|
101
111
|
def cache_get(ck)
|
102
|
-
|
103
|
-
@cache_store.get(ck) rescue nil
|
104
|
-
else
|
105
|
-
@cache_store.get(ck)
|
106
|
-
end
|
112
|
+
cache_op(:get, ck)
|
107
113
|
end
|
108
|
-
|
114
|
+
|
109
115
|
# Set the object in the cache_store with the given key for cache_ttl seconds.
|
110
116
|
def cache_set(ck, obj)
|
111
117
|
@cache_store.set(ck, obj, @cache_ttl)
|
@@ -203,7 +203,7 @@ module Sequel
|
|
203
203
|
@cti_instance_dataset = @instance_dataset
|
204
204
|
@cti_table_columns = columns
|
205
205
|
@cti_table_map = opts[:table_map] || {}
|
206
|
-
@cti_alias = opts[:alias]
|
206
|
+
@cti_alias = opts[:alias] # || table_name # SEQUEL5
|
207
207
|
end
|
208
208
|
end
|
209
209
|
|
@@ -216,6 +216,7 @@ module Sequel
|
|
216
216
|
# This is the only model in the hierarchy that loads the
|
217
217
|
# class_table_inheritance plugin. For backwards compatibility.
|
218
218
|
def cti_base_model
|
219
|
+
Sequel::Deprecation.deprecate("#{self}.cti_base_model", "Use #{self}.cti_models.first instead")
|
219
220
|
@cti_models.first
|
220
221
|
end
|
221
222
|
|
@@ -228,12 +229,12 @@ module Sequel
|
|
228
229
|
attr_reader :cti_instance_dataset
|
229
230
|
|
230
231
|
# An array of table symbols that back this model. The first is
|
231
|
-
#
|
232
|
+
# table symbol for the base model, and the last is the current model
|
232
233
|
# table symbol.
|
233
234
|
attr_reader :cti_tables
|
234
235
|
|
235
236
|
# A hash with class name symbol keys and table name symbol values.
|
236
|
-
# Specified with the :table_map option to the plugin, and used if
|
237
|
+
# Specified with the :table_map option to the plugin, and should be used if
|
237
238
|
# the implicit naming is incorrect.
|
238
239
|
attr_reader :cti_table_map
|
239
240
|
|
@@ -247,10 +248,16 @@ module Sequel
|
|
247
248
|
end
|
248
249
|
|
249
250
|
# Alias to sti_key, for backwards compatibility.
|
250
|
-
def cti_key
|
251
|
+
def cti_key
|
252
|
+
Sequel::Deprecation.deprecate("#{self}.cti_key", "Use #{self}.sti_key instead")
|
253
|
+
sti_key
|
254
|
+
end
|
251
255
|
|
252
256
|
# Alias to sti_model_map, for backwards compatibility.
|
253
|
-
def cti_model_map
|
257
|
+
def cti_model_map
|
258
|
+
Sequel::Deprecation.deprecate("#{self}.cti_model_map", "Use #{self}.sti_model_map instead")
|
259
|
+
sti_model_map
|
260
|
+
end
|
254
261
|
|
255
262
|
# Freeze CTI information when freezing model class.
|
256
263
|
def freeze
|
@@ -297,19 +304,20 @@ module Sequel
|
|
297
304
|
cols = columns - [pk]
|
298
305
|
dup_cols = cols & ds.columns
|
299
306
|
unless dup_cols.empty?
|
307
|
+
# raise Error, "class_table_inheritance with duplicate column names (other than the primary key column) is not supported, make sure tables have unique column names"
|
300
308
|
Sequel::Deprecation.deprecate("Using class_table_inheritance with duplicate column names (#{n} => #{dup_cols}) in subclass tables (other than the primary key column)', 'Make sure all tables used have unique column names, or implement support for handling duplicate column names in the class_table_inheritance plugin")
|
301
309
|
end
|
302
310
|
sel_app = cols.map{|cc| Sequel.qualify(table, Sequel.identifier(cc))}
|
303
311
|
@sti_dataset = ds = ds.join(table, pk=>pk).select_append(*sel_app)
|
304
312
|
|
305
|
-
if @cti_alias
|
313
|
+
if @cti_alias # SEQUEL5: remove if
|
306
314
|
ds = ds.from_self(:alias=>@cti_alias)
|
307
315
|
end
|
308
316
|
|
309
317
|
set_dataset(ds)
|
310
318
|
set_columns(self.columns)
|
311
319
|
@dataset = @dataset.with_row_proc(lambda{|r| subclass.sti_load(r)})
|
312
|
-
cols.each{|a| define_lazy_attribute_getter(a, :dataset=>dataset, :table=>@cti_alias||table)}
|
320
|
+
cols.each{|a| define_lazy_attribute_getter(a, :dataset=>dataset, :table=>@cti_alias||table)} # SEQUEL5: remove ||table
|
313
321
|
|
314
322
|
@cti_models += [self]
|
315
323
|
@cti_tables += [table]
|
@@ -325,7 +333,7 @@ module Sequel
|
|
325
333
|
# The table name for the current model class's main table.
|
326
334
|
def table_name
|
327
335
|
if cti_tables
|
328
|
-
if @cti_alias
|
336
|
+
if @cti_alias # SEQUEL5: remove if
|
329
337
|
@cti_alias
|
330
338
|
else
|
331
339
|
cti_tables.last
|
@@ -340,6 +348,7 @@ module Sequel
|
|
340
348
|
cti_tables ? cti_tables.last : dataset.first_source_alias
|
341
349
|
end
|
342
350
|
|
351
|
+
# The model class for the given key value.
|
343
352
|
def sti_class_from_key(key)
|
344
353
|
sti_class(sti_model_map[key])
|
345
354
|
end
|
@@ -350,7 +359,7 @@ module Sequel
|
|
350
359
|
# when setting subclass dataset.
|
351
360
|
def sti_subclass_dataset(key)
|
352
361
|
ds = super
|
353
|
-
if @cti_alias
|
362
|
+
if @cti_alias && cti_models[0] != self # SEQUEL5: remove @cti_alias
|
354
363
|
ds = ds.from_self(:alias=>@cti_alias)
|
355
364
|
end
|
356
365
|
ds
|
@@ -395,7 +404,7 @@ module Sequel
|
|
395
404
|
# Insert rows into all backing tables, using the columns
|
396
405
|
# in each table.
|
397
406
|
def _insert
|
398
|
-
return super if model.
|
407
|
+
return super if model.cti_models[0] == model
|
399
408
|
model.cti_models.each do |m|
|
400
409
|
v = {}
|
401
410
|
m.cti_table_columns.each{|c| v[c] = @values[c] if @values.include?(c)}
|
@@ -29,11 +29,16 @@ module Sequel
|
|
29
29
|
# # Make the Album class handle column conflicts automatically
|
30
30
|
# Album.plugin :column_conflicts
|
31
31
|
module ColumnConflicts
|
32
|
-
|
33
|
-
def self.configure(model)
|
32
|
+
def self.apply(model)
|
34
33
|
model.instance_eval do
|
35
34
|
@get_column_conflicts = {}
|
36
35
|
@set_column_conflicts = {}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Check for column conflicts on the current model if the model has a dataset.
|
40
|
+
def self.configure(model)
|
41
|
+
model.instance_eval do
|
37
42
|
check_column_conflicts if @dataset
|
38
43
|
end
|
39
44
|
end
|
@@ -41,7 +41,7 @@ module Sequel
|
|
41
41
|
# qualifying them with table's name.
|
42
42
|
def convert_input_dataset(ds)
|
43
43
|
ds = super
|
44
|
-
if !ds.opts[:select] && (from = ds.opts[:from]) && from.length == 1 && !ds.opts[:join]
|
44
|
+
if !ds.opts[:select] && (from = ds.opts[:from]) && from.length == 1 && !ds.opts[:join] # SEQUE5: just !ds.opts[:select]
|
45
45
|
if db.supports_schema_parsing?
|
46
46
|
cols = check_non_connection_error(false){db.schema(ds)}
|
47
47
|
if cols
|
@@ -76,9 +76,9 @@ module Sequel
|
|
76
76
|
|
77
77
|
# Set up the column readers to do deserialization and the column writers
|
78
78
|
# to save the value in deserialized_values
|
79
|
-
def self.configure(model, opts =
|
79
|
+
def self.configure(model, opts = OPTS)
|
80
80
|
model.instance_eval do
|
81
|
-
@csv_serializer_opts = (@csv_serializer_opts ||
|
81
|
+
@csv_serializer_opts = (@csv_serializer_opts || OPTS).merge(opts)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
@@ -87,7 +87,7 @@ module Sequel
|
|
87
87
|
attr_reader :csv_serializer_opts
|
88
88
|
|
89
89
|
# Attempt to parse an array of instances from the given CSV string
|
90
|
-
def array_from_csv(csv, opts =
|
90
|
+
def array_from_csv(csv, opts = OPTS)
|
91
91
|
CSV.parse(csv, process_csv_serializer_opts(opts)).map do |row|
|
92
92
|
row = row.to_hash
|
93
93
|
row.delete(nil)
|
@@ -105,13 +105,13 @@ module Sequel
|
|
105
105
|
end
|
106
106
|
|
107
107
|
# Attempt to parse a single instance from the given CSV string
|
108
|
-
def from_csv(csv, opts =
|
108
|
+
def from_csv(csv, opts = OPTS)
|
109
109
|
new.from_csv(csv, opts)
|
110
110
|
end
|
111
111
|
|
112
112
|
# Convert the options hash to one that can be passed to CSV.
|
113
113
|
def process_csv_serializer_opts(opts)
|
114
|
-
opts = (csv_serializer_opts ||
|
114
|
+
opts = (csv_serializer_opts || OPTS).merge(opts)
|
115
115
|
opts_cols = opts.delete(:columns)
|
116
116
|
opts_include = opts.delete(:include)
|
117
117
|
opts_except = opts.delete(:except)
|
@@ -136,7 +136,7 @@ module Sequel
|
|
136
136
|
#
|
137
137
|
# :headers :: The headers to use for the CSV line. Use nil for a header
|
138
138
|
# to specify the column should be ignored.
|
139
|
-
def from_csv(csv, opts =
|
139
|
+
def from_csv(csv, opts = OPTS)
|
140
140
|
row = CSV.parse_line(csv, model.process_csv_serializer_opts(opts)).to_hash
|
141
141
|
row.delete(nil)
|
142
142
|
set(row)
|
@@ -151,7 +151,7 @@ module Sequel
|
|
151
151
|
# output, ignoring all other columns
|
152
152
|
# :include :: Symbol or Array of Symbols specifying non-column
|
153
153
|
# attributes to include in the CSV output.
|
154
|
-
def to_csv(opts =
|
154
|
+
def to_csv(opts = OPTS)
|
155
155
|
opts = model.process_csv_serializer_opts(opts)
|
156
156
|
|
157
157
|
CSV.generate(opts) do |csv|
|
@@ -168,7 +168,7 @@ module Sequel
|
|
168
168
|
#
|
169
169
|
# :array :: An array of instances. If this is not provided, calls #all
|
170
170
|
# on the receiver to get the array.
|
171
|
-
def to_csv(opts =
|
171
|
+
def to_csv(opts = OPTS)
|
172
172
|
opts = model.process_csv_serializer_opts({:columns=>columns}.merge!(opts))
|
173
173
|
items = opts.delete(:array) || self
|
174
174
|
|