sequel 5.80.0 → 5.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/sequel +9 -4
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/ibmdb.rb +1 -0
- data/lib/sequel/adapters/jdbc/db2.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +3 -3
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -2
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +5 -5
- data/lib/sequel/adapters/jdbc/postgresql.rb +5 -5
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +6 -6
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -2
- data/lib/sequel/adapters/jdbc/sqlserver.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +8 -8
- data/lib/sequel/adapters/mysql2.rb +8 -1
- data/lib/sequel/adapters/shared/access.rb +1 -0
- data/lib/sequel/adapters/shared/db2.rb +1 -1
- data/lib/sequel/adapters/shared/mssql.rb +18 -5
- data/lib/sequel/adapters/shared/mysql.rb +8 -4
- data/lib/sequel/adapters/shared/oracle.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +106 -13
- data/lib/sequel/adapters/shared/sqlite.rb +4 -2
- data/lib/sequel/adapters/sqlite.rb +4 -0
- data/lib/sequel/adapters/trilogy.rb +1 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +26 -10
- data/lib/sequel/connection_pool/threaded.rb +26 -10
- data/lib/sequel/connection_pool.rb +2 -2
- data/lib/sequel/core.rb +15 -0
- data/lib/sequel/database/connecting.rb +20 -26
- data/lib/sequel/database/dataset_defaults.rb +3 -3
- data/lib/sequel/database/misc.rb +46 -10
- data/lib/sequel/database/query.rb +11 -11
- data/lib/sequel/database/schema_generator.rb +8 -0
- data/lib/sequel/database/schema_methods.rb +17 -1
- data/lib/sequel/dataset/actions.rb +9 -1
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +2 -1
- data/lib/sequel/dataset/query.rb +9 -5
- data/lib/sequel/dataset/sql.rb +25 -5
- data/lib/sequel/extensions/caller_logging.rb +2 -0
- data/lib/sequel/extensions/connection_validator.rb +15 -10
- data/lib/sequel/extensions/dataset_run.rb +41 -0
- data/lib/sequel/extensions/migration.rb +23 -3
- data/lib/sequel/extensions/null_dataset.rb +2 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -1
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +93 -10
- data/lib/sequel/extensions/pg_enum.rb +3 -3
- data/lib/sequel/extensions/pg_json_ops.rb +642 -9
- data/lib/sequel/extensions/pg_row.rb +3 -1
- data/lib/sequel/extensions/pg_schema_caching.rb +90 -0
- data/lib/sequel/extensions/provenance.rb +2 -0
- data/lib/sequel/extensions/query_blocker.rb +172 -0
- data/lib/sequel/extensions/schema_caching.rb +24 -9
- data/lib/sequel/extensions/schema_dumper.rb +16 -4
- data/lib/sequel/extensions/sqlite_json_ops.rb +1 -1
- data/lib/sequel/extensions/stdio_logger.rb +48 -0
- data/lib/sequel/extensions/string_agg.rb +17 -4
- data/lib/sequel/extensions/temporarily_release_connection.rb +178 -0
- data/lib/sequel/extensions/virtual_row_method_block.rb +1 -0
- data/lib/sequel/model/associations.rb +28 -3
- data/lib/sequel/model/base.rb +67 -18
- data/lib/sequel/plugins/association_pks.rb +1 -1
- data/lib/sequel/plugins/column_encryption.rb +1 -1
- data/lib/sequel/plugins/composition.rb +1 -1
- data/lib/sequel/plugins/defaults_setter.rb +16 -4
- data/lib/sequel/plugins/enum.rb +1 -1
- data/lib/sequel/plugins/forbid_lazy_load.rb +14 -1
- data/lib/sequel/plugins/input_transformer.rb +1 -1
- data/lib/sequel/plugins/inspect_pk.rb +44 -0
- data/lib/sequel/plugins/instance_filters.rb +4 -1
- data/lib/sequel/plugins/inverted_subsets.rb +1 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +10 -5
- data/lib/sequel/plugins/optimistic_locking.rb +2 -0
- data/lib/sequel/plugins/paged_operations.rb +5 -2
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +6 -1
- data/lib/sequel/plugins/pg_auto_validate_enums.rb +88 -0
- data/lib/sequel/plugins/pg_eager_any_typed_array.rb +95 -0
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +11 -5
- data/lib/sequel/plugins/sql_comments.rb +7 -2
- data/lib/sequel/plugins/static_cache_cache.rb +50 -13
- data/lib/sequel/plugins/subset_conditions.rb +85 -5
- data/lib/sequel/plugins/subset_static_cache.rb +263 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +6 -2
- data/lib/sequel/plugins/validate_associated.rb +1 -1
- data/lib/sequel/sql.rb +16 -6
- data/lib/sequel/version.rb +1 -1
- metadata +12 -234
- data/CHANGELOG +0 -1355
- data/README.rdoc +0 -936
- data/doc/advanced_associations.rdoc +0 -884
- data/doc/association_basics.rdoc +0 -1859
- data/doc/bin_sequel.rdoc +0 -146
- data/doc/cheat_sheet.rdoc +0 -255
- data/doc/code_order.rdoc +0 -102
- data/doc/core_extensions.rdoc +0 -405
- data/doc/dataset_basics.rdoc +0 -96
- data/doc/dataset_filtering.rdoc +0 -222
- data/doc/extensions.rdoc +0 -77
- data/doc/fork_safety.rdoc +0 -84
- data/doc/mass_assignment.rdoc +0 -98
- data/doc/migration.rdoc +0 -660
- data/doc/model_dataset_method_design.rdoc +0 -129
- data/doc/model_hooks.rdoc +0 -254
- data/doc/model_plugins.rdoc +0 -270
- data/doc/mssql_stored_procedures.rdoc +0 -43
- data/doc/object_model.rdoc +0 -563
- data/doc/opening_databases.rdoc +0 -436
- data/doc/postgresql.rdoc +0 -611
- data/doc/prepared_statements.rdoc +0 -144
- data/doc/querying.rdoc +0 -1070
- data/doc/reflection.rdoc +0 -120
- data/doc/release_notes/5.0.0.txt +0 -159
- data/doc/release_notes/5.1.0.txt +0 -31
- data/doc/release_notes/5.10.0.txt +0 -84
- data/doc/release_notes/5.11.0.txt +0 -83
- data/doc/release_notes/5.12.0.txt +0 -141
- data/doc/release_notes/5.13.0.txt +0 -27
- data/doc/release_notes/5.14.0.txt +0 -63
- data/doc/release_notes/5.15.0.txt +0 -39
- data/doc/release_notes/5.16.0.txt +0 -110
- data/doc/release_notes/5.17.0.txt +0 -31
- data/doc/release_notes/5.18.0.txt +0 -69
- data/doc/release_notes/5.19.0.txt +0 -28
- data/doc/release_notes/5.2.0.txt +0 -33
- data/doc/release_notes/5.20.0.txt +0 -89
- data/doc/release_notes/5.21.0.txt +0 -87
- data/doc/release_notes/5.22.0.txt +0 -48
- data/doc/release_notes/5.23.0.txt +0 -56
- data/doc/release_notes/5.24.0.txt +0 -56
- data/doc/release_notes/5.25.0.txt +0 -32
- data/doc/release_notes/5.26.0.txt +0 -35
- data/doc/release_notes/5.27.0.txt +0 -21
- data/doc/release_notes/5.28.0.txt +0 -16
- data/doc/release_notes/5.29.0.txt +0 -22
- data/doc/release_notes/5.3.0.txt +0 -121
- data/doc/release_notes/5.30.0.txt +0 -20
- data/doc/release_notes/5.31.0.txt +0 -148
- data/doc/release_notes/5.32.0.txt +0 -46
- data/doc/release_notes/5.33.0.txt +0 -24
- data/doc/release_notes/5.34.0.txt +0 -40
- data/doc/release_notes/5.35.0.txt +0 -56
- data/doc/release_notes/5.36.0.txt +0 -60
- data/doc/release_notes/5.37.0.txt +0 -30
- data/doc/release_notes/5.38.0.txt +0 -28
- data/doc/release_notes/5.39.0.txt +0 -19
- data/doc/release_notes/5.4.0.txt +0 -80
- data/doc/release_notes/5.40.0.txt +0 -40
- data/doc/release_notes/5.41.0.txt +0 -25
- data/doc/release_notes/5.42.0.txt +0 -136
- data/doc/release_notes/5.43.0.txt +0 -98
- data/doc/release_notes/5.44.0.txt +0 -32
- data/doc/release_notes/5.45.0.txt +0 -34
- data/doc/release_notes/5.46.0.txt +0 -87
- data/doc/release_notes/5.47.0.txt +0 -59
- data/doc/release_notes/5.48.0.txt +0 -14
- data/doc/release_notes/5.49.0.txt +0 -59
- data/doc/release_notes/5.5.0.txt +0 -61
- data/doc/release_notes/5.50.0.txt +0 -78
- data/doc/release_notes/5.51.0.txt +0 -47
- data/doc/release_notes/5.52.0.txt +0 -87
- data/doc/release_notes/5.53.0.txt +0 -23
- data/doc/release_notes/5.54.0.txt +0 -27
- data/doc/release_notes/5.55.0.txt +0 -21
- data/doc/release_notes/5.56.0.txt +0 -51
- data/doc/release_notes/5.57.0.txt +0 -23
- data/doc/release_notes/5.58.0.txt +0 -31
- data/doc/release_notes/5.59.0.txt +0 -73
- data/doc/release_notes/5.6.0.txt +0 -31
- data/doc/release_notes/5.60.0.txt +0 -22
- data/doc/release_notes/5.61.0.txt +0 -43
- data/doc/release_notes/5.62.0.txt +0 -132
- data/doc/release_notes/5.63.0.txt +0 -33
- data/doc/release_notes/5.64.0.txt +0 -50
- data/doc/release_notes/5.65.0.txt +0 -21
- data/doc/release_notes/5.66.0.txt +0 -24
- data/doc/release_notes/5.67.0.txt +0 -32
- data/doc/release_notes/5.68.0.txt +0 -61
- data/doc/release_notes/5.69.0.txt +0 -26
- data/doc/release_notes/5.7.0.txt +0 -108
- data/doc/release_notes/5.70.0.txt +0 -35
- data/doc/release_notes/5.71.0.txt +0 -21
- data/doc/release_notes/5.72.0.txt +0 -33
- data/doc/release_notes/5.73.0.txt +0 -66
- data/doc/release_notes/5.74.0.txt +0 -45
- data/doc/release_notes/5.75.0.txt +0 -35
- data/doc/release_notes/5.76.0.txt +0 -86
- data/doc/release_notes/5.77.0.txt +0 -63
- data/doc/release_notes/5.78.0.txt +0 -67
- data/doc/release_notes/5.79.0.txt +0 -28
- data/doc/release_notes/5.8.0.txt +0 -170
- data/doc/release_notes/5.80.0.txt +0 -40
- data/doc/release_notes/5.9.0.txt +0 -99
- data/doc/schema_modification.rdoc +0 -679
- data/doc/security.rdoc +0 -443
- data/doc/sharding.rdoc +0 -286
- data/doc/sql.rdoc +0 -648
- data/doc/testing.rdoc +0 -190
- data/doc/thread_safety.rdoc +0 -15
- data/doc/transactions.rdoc +0 -250
- data/doc/validations.rdoc +0 -558
- data/doc/virtual_rows.rdoc +0 -265
@@ -0,0 +1,263 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Sequel
|
4
|
+
module Plugins
|
5
|
+
# The subset_static_cache plugin is designed for model subsets that are not modified at all
|
6
|
+
# in production use cases, or at least where modifications to them would usually
|
7
|
+
# coincide with an application restart. When caching a model subset, it
|
8
|
+
# retrieves all rows in the database and statically caches a ruby array and hash
|
9
|
+
# keyed on primary key containing all of the model instances. All of these cached
|
10
|
+
# instances are frozen so they won't be modified unexpectedly.
|
11
|
+
#
|
12
|
+
# With the following code:
|
13
|
+
#
|
14
|
+
# class StatusType < Sequel::Model
|
15
|
+
# dataset_module do
|
16
|
+
# where :available, hidden: false
|
17
|
+
# end
|
18
|
+
# cache_subset :available
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# The following methods will use the cache and not issue a database query:
|
22
|
+
#
|
23
|
+
# * StatusType.available.with_pk
|
24
|
+
# * StatusType.available.all
|
25
|
+
# * StatusType.available.each
|
26
|
+
# * StatusType.available.first (without block, only supporting no arguments or single integer argument)
|
27
|
+
# * StatusType.available.count (without an argument or block)
|
28
|
+
# * StatusType.available.map
|
29
|
+
# * StatusType.available.as_hash
|
30
|
+
# * StatusType.available.to_hash
|
31
|
+
# * StatusType.available.to_hash_groups
|
32
|
+
#
|
33
|
+
# The cache is not used if you chain methods before or after calling the cached
|
34
|
+
# method, as doing so would not be safe:
|
35
|
+
#
|
36
|
+
# StatusType.where{number > 1}.available.all
|
37
|
+
# StatusType.available.where{number > 1}.all
|
38
|
+
#
|
39
|
+
# The cache is also not used if you change the class's dataset after caching
|
40
|
+
# the subset, or in subclasses of the model.
|
41
|
+
#
|
42
|
+
# You should not modify any row that is statically cached when using this plugin,
|
43
|
+
# as otherwise you will get different results for cached and uncached method
|
44
|
+
# calls.
|
45
|
+
module SubsetStaticCache
|
46
|
+
def self.configure(model)
|
47
|
+
model.class_exec do
|
48
|
+
@subset_static_caches ||= ({}.compare_by_identity)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module ClassMethods
|
53
|
+
# Cache the given subset statically, so that calling the subset method on
|
54
|
+
# the model will return a dataset that will return cached results instead
|
55
|
+
# of issuing database queries (assuming the cache has the necessary
|
56
|
+
# information).
|
57
|
+
#
|
58
|
+
# The model must already respond to the given method before cache_subset
|
59
|
+
# is called.
|
60
|
+
def cache_subset(meth)
|
61
|
+
ds = send(meth).with_extend(CachedDatasetMethods)
|
62
|
+
cache = ds.instance_variable_get(:@cache)
|
63
|
+
|
64
|
+
rows, hash = subset_static_cache_rows(ds, meth)
|
65
|
+
cache[:subset_static_cache_all] = rows
|
66
|
+
cache[:subset_static_cache_map] = hash
|
67
|
+
|
68
|
+
caches = @subset_static_caches
|
69
|
+
caches[meth] = ds
|
70
|
+
model = self
|
71
|
+
subset_static_cache_module.send(:define_method, meth) do
|
72
|
+
if (model == self) && (cached_dataset = caches[meth])
|
73
|
+
cached_dataset
|
74
|
+
else
|
75
|
+
super()
|
76
|
+
end
|
77
|
+
end
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
Plugins.after_set_dataset(self, :clear_subset_static_caches)
|
82
|
+
Plugins.inherited_instance_variables(self, :@subset_static_caches=>proc{{}.compare_by_identity})
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
# Clear the subset_static_caches. This is used if the model dataset
|
87
|
+
# changes, to prevent cached values from being used.
|
88
|
+
def clear_subset_static_caches
|
89
|
+
@subset_static_caches.clear
|
90
|
+
end
|
91
|
+
|
92
|
+
# A module for the subset static cache methods, so that you can define
|
93
|
+
# a singleton method in the class with the same name, and call super
|
94
|
+
# to get default behavior.
|
95
|
+
def subset_static_cache_module
|
96
|
+
return @subset_static_cache_module if @subset_static_cache_module
|
97
|
+
|
98
|
+
# Ensure dataset_methods module is defined and class is extended with
|
99
|
+
# it before calling creating this module.
|
100
|
+
dataset_methods_module
|
101
|
+
|
102
|
+
mod_name = "#{name}::@subset_static_cache_module"
|
103
|
+
Sequel.synchronize{@subset_static_cache_module ||= Sequel.set_temp_name(Module.new){mod_name}}
|
104
|
+
extend(@subset_static_cache_module)
|
105
|
+
@subset_static_cache_module
|
106
|
+
end
|
107
|
+
|
108
|
+
# Return the frozen array and hash used for caching the subset
|
109
|
+
# of the given dataset.
|
110
|
+
def subset_static_cache_rows(ds, meth)
|
111
|
+
all = load_subset_static_cache_rows(ds, meth)
|
112
|
+
h = {}
|
113
|
+
all.each do |o|
|
114
|
+
o.errors.freeze
|
115
|
+
h[o.pk.freeze] = o.freeze
|
116
|
+
end
|
117
|
+
[all, h.freeze]
|
118
|
+
end
|
119
|
+
|
120
|
+
# Return a frozen array for all rows in the dataset.
|
121
|
+
def load_subset_static_cache_rows(ds, meth)
|
122
|
+
ret = super if defined?(super)
|
123
|
+
ret || ds.all.freeze
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module CachedDatasetMethods
|
128
|
+
# An array of all of the dataset's instances, without issuing a database
|
129
|
+
# query. If a block is given, yields each instance to the block.
|
130
|
+
def all(&block)
|
131
|
+
return super unless all = @cache[:subset_static_cache_all]
|
132
|
+
|
133
|
+
array = all.dup
|
134
|
+
array.each(&block) if block
|
135
|
+
array
|
136
|
+
end
|
137
|
+
|
138
|
+
# Get the number of records in the cache, without issuing a database query,
|
139
|
+
# if no arguments or block are provided.
|
140
|
+
def count(*a, &block)
|
141
|
+
if a.empty? && !block && (all = @cache[:subset_static_cache_all])
|
142
|
+
all.size
|
143
|
+
else
|
144
|
+
super
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# If a block is given, multiple arguments are given, or a single
|
149
|
+
# non-Integer argument is given, performs the default behavior of
|
150
|
+
# issuing a database query. Otherwise, uses the cached values
|
151
|
+
# to return either the first cached instance (no arguments) or an
|
152
|
+
# array containing the number of instances specified (single integer
|
153
|
+
# argument).
|
154
|
+
def first(*args)
|
155
|
+
if !defined?(yield) && args.length <= 1 && (args.length == 0 || args[0].is_a?(Integer)) && (all = @cache[:subset_static_cache_all])
|
156
|
+
all.first(*args)
|
157
|
+
else
|
158
|
+
super
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return the frozen object with the given pk, or nil if no such object exists
|
163
|
+
# in the cache, without issuing a database query.
|
164
|
+
def with_pk(pk)
|
165
|
+
if cache = @cache[:subset_static_cache_map]
|
166
|
+
cache[pk]
|
167
|
+
else
|
168
|
+
super
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Yield each of the dataset's frozen instances to the block, without issuing a database
|
173
|
+
# query.
|
174
|
+
def each(&block)
|
175
|
+
return super unless all = @cache[:subset_static_cache_all]
|
176
|
+
all.each(&block)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Use the cache instead of a query to get the results.
|
180
|
+
def map(column=nil, &block)
|
181
|
+
return super unless all = @cache[:subset_static_cache_all]
|
182
|
+
if column
|
183
|
+
raise(Error, "Cannot provide both column and block to map") if block
|
184
|
+
if column.is_a?(Array)
|
185
|
+
all.map{|r| r.values.values_at(*column)}
|
186
|
+
else
|
187
|
+
all.map{|r| r[column]}
|
188
|
+
end
|
189
|
+
else
|
190
|
+
all.map(&block)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Use the cache instead of a query to get the results if possible
|
195
|
+
def as_hash(key_column = nil, value_column = nil, opts = OPTS)
|
196
|
+
return super unless all = @cache[:subset_static_cache_all]
|
197
|
+
|
198
|
+
if key_column.nil? && value_column.nil?
|
199
|
+
if opts[:hash]
|
200
|
+
key_column = model.primary_key
|
201
|
+
else
|
202
|
+
return Hash[@cache[:subset_static_cache_map]]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
h = opts[:hash] || {}
|
207
|
+
if value_column
|
208
|
+
if value_column.is_a?(Array)
|
209
|
+
if key_column.is_a?(Array)
|
210
|
+
all.each{|r| h[r.values.values_at(*key_column)] = r.values.values_at(*value_column)}
|
211
|
+
else
|
212
|
+
all.each{|r| h[r[key_column]] = r.values.values_at(*value_column)}
|
213
|
+
end
|
214
|
+
else
|
215
|
+
if key_column.is_a?(Array)
|
216
|
+
all.each{|r| h[r.values.values_at(*key_column)] = r[value_column]}
|
217
|
+
else
|
218
|
+
all.each{|r| h[r[key_column]] = r[value_column]}
|
219
|
+
end
|
220
|
+
end
|
221
|
+
elsif key_column.is_a?(Array)
|
222
|
+
all.each{|r| h[r.values.values_at(*key_column)] = r}
|
223
|
+
else
|
224
|
+
all.each{|r| h[r[key_column]] = r}
|
225
|
+
end
|
226
|
+
h
|
227
|
+
end
|
228
|
+
|
229
|
+
# Alias of as_hash for backwards compatibility.
|
230
|
+
def to_hash(*a)
|
231
|
+
as_hash(*a)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Use the cache instead of a query to get the results
|
235
|
+
def to_hash_groups(key_column, value_column = nil, opts = OPTS)
|
236
|
+
return super unless all = @cache[:subset_static_cache_all]
|
237
|
+
|
238
|
+
h = opts[:hash] || {}
|
239
|
+
if value_column
|
240
|
+
if value_column.is_a?(Array)
|
241
|
+
if key_column.is_a?(Array)
|
242
|
+
all.each{|r| (h[r.values.values_at(*key_column)] ||= []) << r.values.values_at(*value_column)}
|
243
|
+
else
|
244
|
+
all.each{|r| (h[r[key_column]] ||= []) << r.values.values_at(*value_column)}
|
245
|
+
end
|
246
|
+
else
|
247
|
+
if key_column.is_a?(Array)
|
248
|
+
all.each{|r| (h[r.values.values_at(*key_column)] ||= []) << r[value_column]}
|
249
|
+
else
|
250
|
+
all.each{|r| (h[r[key_column]] ||= []) << r[value_column]}
|
251
|
+
end
|
252
|
+
end
|
253
|
+
elsif key_column.is_a?(Array)
|
254
|
+
all.each{|r| (h[r.values.values_at(*key_column)] ||= []) << r}
|
255
|
+
else
|
256
|
+
all.each{|r| (h[r[key_column]] ||= []) << r}
|
257
|
+
end
|
258
|
+
h
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
@@ -158,15 +158,19 @@ module Sequel
|
|
158
158
|
end
|
159
159
|
|
160
160
|
# Filter the objects used when tactical eager loading.
|
161
|
-
# By default, this removes frozen objects and objects that alreayd have the association loaded
|
161
|
+
# By default, this removes frozen objects and objects that alreayd have the association loaded,
|
162
|
+
# as well as objects where the reflection for the association is not the same as the receiver's
|
163
|
+
# reflection for the association.
|
162
164
|
def _filter_tactical_eager_load_objects(opts)
|
163
165
|
objects = defined?(super) ? super : retrieved_with.dup
|
166
|
+
name = opts[:name]
|
164
167
|
if opts[:eager_reload]
|
165
168
|
objects.reject!(&:frozen?)
|
166
169
|
else
|
167
|
-
name = opts[:name]
|
168
170
|
objects.reject!{|x| x.frozen? || x.associations.include?(name)}
|
169
171
|
end
|
172
|
+
reflection = self.class.association_reflection(name)
|
173
|
+
objects.select!{|x| x.class.association_reflection(name).equal?(reflection)}
|
170
174
|
objects
|
171
175
|
end
|
172
176
|
end
|
@@ -53,7 +53,7 @@ module Sequel
|
|
53
53
|
def validate_associated_object(reflection, obj)
|
54
54
|
return if reflection[:validate] == false
|
55
55
|
association = reflection[:name]
|
56
|
-
if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(
|
56
|
+
if (reflection[:type] == :one_to_many || reflection[:type] == :one_to_one) && (key = reflection[:key]).is_a?(Symbol) && !(obj.values[key])
|
57
57
|
p_key = pk unless pk.is_a?(Array)
|
58
58
|
if p_key
|
59
59
|
obj.values[key] = p_key
|
data/lib/sequel/sql.rb
CHANGED
@@ -153,13 +153,16 @@ module Sequel
|
|
153
153
|
class ComplexExpression < Expression
|
154
154
|
# A hash of the opposite for each operator symbol, used for inverting
|
155
155
|
# objects.
|
156
|
-
|
156
|
+
OPERATOR_INVERSIONS = {:AND => :OR, :OR => :AND, :< => :>=, :> => :<=,
|
157
157
|
:<= => :>, :>= => :<, :'=' => :'!=' , :'!=' => :'=', :LIKE => :'NOT LIKE',
|
158
158
|
:'NOT LIKE' => :LIKE, :~ => :'!~', :'!~' => :~, :IN => :'NOT IN',
|
159
159
|
:'NOT IN' => :IN, :IS => :'IS NOT', :'IS NOT' => :IS, :'~*' => :'!~*',
|
160
160
|
:'!~*' => :'~*', :NOT => :NOOP, :NOOP => :NOT, :ILIKE => :'NOT ILIKE',
|
161
161
|
:'NOT ILIKE'=>:ILIKE}.freeze
|
162
162
|
|
163
|
+
# SEQUEL6: Remove
|
164
|
+
OPERTATOR_INVERSIONS = OPERATOR_INVERSIONS
|
165
|
+
|
163
166
|
# Standard mathematical operators used in +NumericMethods+
|
164
167
|
MATHEMATICAL_OPERATORS = [:+, :-, :/, :*, :**].freeze
|
165
168
|
|
@@ -1124,7 +1127,13 @@ module Sequel
|
|
1124
1127
|
when DelayedEvaluation
|
1125
1128
|
Sequel.delay{|ds| from_value_pair(l, r.call(ds))}
|
1126
1129
|
when Dataset::PlaceholderLiteralizer::Argument
|
1127
|
-
r.
|
1130
|
+
prev_transform = r.instance_variable_get(:@transformer)
|
1131
|
+
r.transform do |v|
|
1132
|
+
if prev_transform
|
1133
|
+
v = prev_transform.call(v)
|
1134
|
+
end
|
1135
|
+
from_value_pair(l, v)
|
1136
|
+
end
|
1128
1137
|
else
|
1129
1138
|
new(:'=', l, r)
|
1130
1139
|
end
|
@@ -1142,9 +1151,9 @@ module Sequel
|
|
1142
1151
|
when BooleanExpression
|
1143
1152
|
case op = ce.op
|
1144
1153
|
when :AND, :OR
|
1145
|
-
BooleanExpression.new(
|
1154
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.map{|a| BooleanExpression.invert(a)})
|
1146
1155
|
when :IN, :"NOT IN"
|
1147
|
-
BooleanExpression.new(
|
1156
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
1148
1157
|
else
|
1149
1158
|
if ce.args.length == 2
|
1150
1159
|
case ce.args[1]
|
@@ -1153,10 +1162,10 @@ module Sequel
|
|
1153
1162
|
# can result in incorrect behavior for ANY/SOME/ALL operators.
|
1154
1163
|
BooleanExpression.new(:NOT, ce)
|
1155
1164
|
else
|
1156
|
-
BooleanExpression.new(
|
1165
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
1157
1166
|
end
|
1158
1167
|
else
|
1159
|
-
BooleanExpression.new(
|
1168
|
+
BooleanExpression.new(OPERATOR_INVERSIONS[op], *ce.args.dup)
|
1160
1169
|
end
|
1161
1170
|
end
|
1162
1171
|
when StringExpression, NumericExpression
|
@@ -1912,6 +1921,7 @@ module Sequel
|
|
1912
1921
|
end
|
1913
1922
|
|
1914
1923
|
m = Module.new do
|
1924
|
+
Sequel.set_temp_name(Module.new){"Sequel::SQL::VirtualRow::_BaseMethodMissing"}
|
1915
1925
|
# Return an +Identifier+, +QualifiedIdentifier+, or +Function+, depending
|
1916
1926
|
# on arguments and whether a block is provided. Does not currently call the block.
|
1917
1927
|
# See the class level documentation.
|
data/lib/sequel/version.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
8
8
|
# release, generally around once a month.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 92
|
10
10
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
12
12
|
# releases that fix regressions from previous versions.
|