sequel 3.28.0 → 3.29.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.
- data/CHANGELOG +119 -3
- data/Rakefile +5 -3
- data/bin/sequel +1 -5
- data/doc/model_hooks.rdoc +9 -1
- data/doc/opening_databases.rdoc +49 -40
- data/doc/prepared_statements.rdoc +27 -6
- data/doc/release_notes/3.28.0.txt +2 -2
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +18 -9
- data/doc/transactions.rdoc +41 -1
- data/lib/sequel/adapters/ado.rb +28 -17
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/amalgalite.rb +11 -7
- data/lib/sequel/adapters/db2.rb +122 -70
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do.rb +5 -36
- data/lib/sequel/adapters/do/mysql.rb +0 -5
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/firebird.rb +3 -6
- data/lib/sequel/adapters/ibmdb.rb +24 -16
- data/lib/sequel/adapters/informix.rb +2 -4
- data/lib/sequel/adapters/jdbc.rb +47 -11
- data/lib/sequel/adapters/jdbc/as400.rb +5 -24
- data/lib/sequel/adapters/jdbc/db2.rb +0 -5
- data/lib/sequel/adapters/jdbc/derby.rb +217 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
- data/lib/sequel/adapters/jdbc/h2.rb +10 -12
- data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
- data/lib/sequel/adapters/jdbc/informix.rb +0 -5
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
- data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
- data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
- data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
- data/lib/sequel/adapters/mock.rb +315 -0
- data/lib/sequel/adapters/mysql.rb +64 -51
- data/lib/sequel/adapters/mysql2.rb +15 -9
- data/lib/sequel/adapters/odbc.rb +13 -6
- data/lib/sequel/adapters/odbc/db2.rb +0 -4
- data/lib/sequel/adapters/odbc/mssql.rb +0 -5
- data/lib/sequel/adapters/openbase.rb +2 -4
- data/lib/sequel/adapters/oracle.rb +333 -51
- data/lib/sequel/adapters/postgres.rb +80 -27
- data/lib/sequel/adapters/shared/access.rb +0 -6
- data/lib/sequel/adapters/shared/db2.rb +13 -15
- data/lib/sequel/adapters/shared/firebird.rb +6 -6
- data/lib/sequel/adapters/shared/mssql.rb +23 -18
- data/lib/sequel/adapters/shared/mysql.rb +6 -6
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +185 -30
- data/lib/sequel/adapters/shared/postgres.rb +35 -18
- data/lib/sequel/adapters/shared/progress.rb +0 -6
- data/lib/sequel/adapters/shared/sqlite.rb +116 -37
- data/lib/sequel/adapters/sqlite.rb +16 -8
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/swift/mysql.rb +0 -5
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +6 -4
- data/lib/sequel/adapters/tinytds.rb +13 -10
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
- data/lib/sequel/core.rb +40 -0
- data/lib/sequel/database/connecting.rb +1 -2
- data/lib/sequel/database/dataset.rb +3 -3
- data/lib/sequel/database/dataset_defaults.rb +58 -0
- data/lib/sequel/database/misc.rb +62 -2
- data/lib/sequel/database/query.rb +113 -49
- data/lib/sequel/database/schema_methods.rb +7 -2
- data/lib/sequel/dataset/actions.rb +37 -19
- data/lib/sequel/dataset/features.rb +24 -0
- data/lib/sequel/dataset/graph.rb +7 -6
- data/lib/sequel/dataset/misc.rb +11 -3
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +6 -4
- data/lib/sequel/dataset/query.rb +46 -15
- data/lib/sequel/dataset/sql.rb +28 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/model.rb +2 -1
- data/lib/sequel/model/associations.rb +115 -33
- data/lib/sequel/model/base.rb +91 -31
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +6 -10
- data/lib/sequel/plugins/prepared_statements.rb +12 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +6 -1
- data/lib/sequel/plugins/sharding.rb +0 -5
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +1 -1
- data/lib/sequel/timezones.rb +42 -42
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mssql_spec.rb +29 -29
- data/spec/adapters/mysql_spec.rb +86 -104
- data/spec/adapters/oracle_spec.rb +48 -76
- data/spec/adapters/postgres_spec.rb +98 -33
- data/spec/adapters/spec_helper.rb +0 -5
- data/spec/adapters/sqlite_spec.rb +24 -21
- data/spec/core/connection_pool_spec.rb +9 -15
- data/spec/core/core_sql_spec.rb +20 -31
- data/spec/core/database_spec.rb +491 -227
- data/spec/core/dataset_spec.rb +638 -1051
- data/spec/core/expression_filters_spec.rb +0 -1
- data/spec/core/mock_adapter_spec.rb +378 -0
- data/spec/core/object_graph_spec.rb +48 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +51 -114
- data/spec/core/spec_helper.rb +3 -90
- data/spec/extensions/class_table_inheritance_spec.rb +1 -1
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/instance_hooks_spec.rb +71 -0
- data/spec/extensions/named_timezones_spec.rb +22 -2
- data/spec/extensions/nested_attributes_spec.rb +3 -0
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
- data/spec/extensions/serialization_spec.rb +5 -8
- data/spec/extensions/spec_helper.rb +4 -0
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/integration/associations_test.rb +123 -12
- data/spec/integration/dataset_test.rb +140 -47
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +179 -128
- data/spec/integration/prepared_statement_test.rb +92 -91
- data/spec/integration/schema_test.rb +42 -23
- data/spec/integration/spec_helper.rb +25 -31
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +161 -34
- data/spec/integration/type_test.rb +3 -3
- data/spec/model/association_reflection_spec.rb +83 -7
- data/spec/model/associations_spec.rb +393 -676
- data/spec/model/base_spec.rb +186 -116
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +343 -867
- data/spec/model/hooks_spec.rb +160 -79
- data/spec/model/model_spec.rb +118 -165
- data/spec/model/plugins_spec.rb +7 -13
- data/spec/model/record_spec.rb +138 -207
- data/spec/model/spec_helper.rb +10 -73
- metadata +14 -8
|
@@ -90,9 +90,9 @@ module Sequel
|
|
|
90
90
|
@cti_columns = {table_name=>columns}
|
|
91
91
|
@cti_table_map = opts[:table_map] || {}
|
|
92
92
|
dataset.row_proc = if key
|
|
93
|
-
lambda{|r| (m.call(r[key]) rescue model).
|
|
93
|
+
lambda{|r| (m.call(r[key]) rescue model).call(r)}
|
|
94
94
|
else
|
|
95
|
-
|
|
95
|
+
model
|
|
96
96
|
end
|
|
97
97
|
end
|
|
98
98
|
end
|
|
@@ -152,9 +152,9 @@ module Sequel
|
|
|
152
152
|
subclass.instance_eval do
|
|
153
153
|
m = method(:constantize)
|
|
154
154
|
dataset.row_proc = if cti_key
|
|
155
|
-
lambda{|r| (m.call(r[ck]) rescue subclass).
|
|
155
|
+
lambda{|r| (m.call(r[ck]) rescue subclass).call(r)}
|
|
156
156
|
else
|
|
157
|
-
|
|
157
|
+
subclass
|
|
158
158
|
end
|
|
159
159
|
(columns - [cbm.primary_key]).each{|a| define_lazy_attribute_getter(a)}
|
|
160
160
|
cti_tables.reverse.each do |table|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
module Sequel
|
|
2
|
+
module Plugins
|
|
3
|
+
# DatasetAssociations allows you to easily use your model associations
|
|
4
|
+
# via datasets. For each association you define, it creates a dataset
|
|
5
|
+
# method for that association that returns a dataset of all objects
|
|
6
|
+
# that are associated to objects in the current dataset. Here's a simple
|
|
7
|
+
# example:
|
|
8
|
+
#
|
|
9
|
+
# class Artist < Sequel::Model
|
|
10
|
+
# plugin :dataset_associations
|
|
11
|
+
# one_to_many :albums
|
|
12
|
+
# end
|
|
13
|
+
# Artist.filter(id=>1..100).albums
|
|
14
|
+
# # SELECT * FROM albums
|
|
15
|
+
# # WHERE (albums.artist_id IN (
|
|
16
|
+
# # SELECT id FROM artists
|
|
17
|
+
# # WHERE ((id >= 1) AND (id <= 100))))
|
|
18
|
+
#
|
|
19
|
+
# This works for all of the association types that ship with Sequel,
|
|
20
|
+
# including the many_through_many type. Most association options that
|
|
21
|
+
# are supported when eager loading are supported when using a
|
|
22
|
+
# dataset association. However, associations that use :limit or
|
|
23
|
+
# one_to_one associations that are really one_to_many relationships
|
|
24
|
+
# in the database will not work correctly, returning all associated
|
|
25
|
+
# objects.
|
|
26
|
+
#
|
|
27
|
+
# As the dataset methods return datasets, you can easily chain the
|
|
28
|
+
# methods to get associated datasets of associated datasets:
|
|
29
|
+
#
|
|
30
|
+
# Artist.filter(id=>1..100).albums.filter{name < 'M'}.tags
|
|
31
|
+
# # SELECT tags.* FROM tags
|
|
32
|
+
# # WHERE (tags.id IN (
|
|
33
|
+
# # SELECT albums_tags.tag_id FROM albums
|
|
34
|
+
# # INNER JOIN albums_tags
|
|
35
|
+
# # ON (albums_tags.album_id = albums.id)
|
|
36
|
+
# # WHERE
|
|
37
|
+
# # ((albums.artist_id IN (
|
|
38
|
+
# # SELECT id FROM artists
|
|
39
|
+
# # WHERE ((id >= 1) AND (id <= 100)))
|
|
40
|
+
# # AND
|
|
41
|
+
# # (name < 'M')))))
|
|
42
|
+
#
|
|
43
|
+
# Usage:
|
|
44
|
+
#
|
|
45
|
+
# # Make all model subclasses create association methods for datasets
|
|
46
|
+
# Sequel::Model.plugin :dataset_associations
|
|
47
|
+
#
|
|
48
|
+
# # Make the Album class create association methods for datasets
|
|
49
|
+
# Album.plugin :dataset_associations
|
|
50
|
+
module DatasetAssociations
|
|
51
|
+
module ClassMethods
|
|
52
|
+
# Set up a dataset method for each association to return an associated dataset
|
|
53
|
+
def associate(type, name, *)
|
|
54
|
+
ret = super
|
|
55
|
+
r = association_reflection(name)
|
|
56
|
+
meth = r.returns_array? ? name : pluralize(name).to_sym
|
|
57
|
+
def_dataset_method(meth){associated(name)}
|
|
58
|
+
ret
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
module DatasetMethods
|
|
63
|
+
# For the association given by +name+, return a dataset of associated objects
|
|
64
|
+
# such that it would return the union of calling the association method on
|
|
65
|
+
# all objects returned by the current dataset.
|
|
66
|
+
#
|
|
67
|
+
# This supports most options that are supported when eager loading. It doesn't
|
|
68
|
+
# support limits on the associations, or one_to_one associations that are really
|
|
69
|
+
# one_to_many and use an order to select the first matching object. In both of
|
|
70
|
+
# those cases, this will return an array of all matching objects.
|
|
71
|
+
def associated(name)
|
|
72
|
+
raise Error, "unrecognized association name: #{name.inspect}" unless r = model.association_reflection(name)
|
|
73
|
+
ds = r.associated_class.dataset
|
|
74
|
+
sds = opts[:limit] ? self : unordered
|
|
75
|
+
ds = case r[:type]
|
|
76
|
+
when :many_to_one
|
|
77
|
+
ds.filter(r.qualified_primary_key=>sds.select(*Array(r[:qualified_key])))
|
|
78
|
+
when :one_to_one, :one_to_many
|
|
79
|
+
ds.filter(r.qualified_key=>sds.select(*Array(r.qualified_primary_key)))
|
|
80
|
+
when :many_to_many
|
|
81
|
+
ds.filter(r.qualified_right_primary_key=>sds.select(*Array(r.qualified_right_key)).
|
|
82
|
+
join(r[:join_table], r[:left_keys].zip(r[:left_primary_keys]), :implicit_qualifier=>model.table_name))
|
|
83
|
+
when :many_through_many
|
|
84
|
+
fre = r.reverse_edges.first
|
|
85
|
+
fe, *edges = r.edges
|
|
86
|
+
sds = sds.select(*Array(r.qualify(fre[:table], fre[:left]))).
|
|
87
|
+
join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
|
|
88
|
+
edges.each{|e| sds = sds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
|
|
89
|
+
ds.filter(r.qualified_right_primary_key=>sds)
|
|
90
|
+
else
|
|
91
|
+
raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}"
|
|
92
|
+
end
|
|
93
|
+
ds = model.apply_association_dataset_opts(r, ds)
|
|
94
|
+
r[:extend].each{|m| ds.extend(m)}
|
|
95
|
+
ds
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -8,7 +8,7 @@ module Sequel
|
|
|
8
8
|
# attribute, the resulting value is forced to a given encoding if the
|
|
9
9
|
# value is a string. There are two ways to specify the encoding. You
|
|
10
10
|
# can either do so in the plugin call itself, or via the
|
|
11
|
-
# forced_encoding class accessor
|
|
11
|
+
# forced_encoding class accessor.
|
|
12
12
|
#
|
|
13
13
|
# Usage:
|
|
14
14
|
#
|
|
@@ -46,6 +46,11 @@ module Sequel
|
|
|
46
46
|
super(force_hash_encoding(row))
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Force the encoding of all string values when setting the instance's values.
|
|
50
|
+
def set_values(row)
|
|
51
|
+
super(force_hash_encoding(row))
|
|
52
|
+
end
|
|
53
|
+
|
|
49
54
|
private
|
|
50
55
|
|
|
51
56
|
# Force the encoding for all string values in the given row hash.
|
|
@@ -55,11 +60,6 @@ module Sequel
|
|
|
55
60
|
row
|
|
56
61
|
end
|
|
57
62
|
|
|
58
|
-
# Force the encoding of all string values when setting the instance's values.
|
|
59
|
-
def set_values(row)
|
|
60
|
-
super(force_hash_encoding(row))
|
|
61
|
-
end
|
|
62
|
-
|
|
63
63
|
# Force the encoding of all returned strings to the model's forced_encoding.
|
|
64
64
|
def typecast_value(column, value)
|
|
65
65
|
s = super
|
|
@@ -163,7 +163,7 @@ module Sequel
|
|
|
163
163
|
# certain fields in an initial query, make modifications to some of those
|
|
164
164
|
# fields and request other, potentially overlapping fields in a new query,
|
|
165
165
|
# and not have the second query override fields you modified.
|
|
166
|
-
def
|
|
166
|
+
def call(row)
|
|
167
167
|
return super unless idm = identity_map
|
|
168
168
|
if o = idm[identity_map_key(Array(primary_key).map{|x| row[x]})]
|
|
169
169
|
o.merge_db_update(row)
|
|
@@ -63,11 +63,8 @@ module Sequel
|
|
|
63
63
|
self[:eager_loading_predicate_key] ||= begin
|
|
64
64
|
calculate_edges
|
|
65
65
|
e = self[:edges].first
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
else
|
|
69
|
-
SQL::QualifiedIdentifier.new(e[:table], e[:right])
|
|
70
|
-
end
|
|
66
|
+
f = self[:final_reverse_edge]
|
|
67
|
+
qualify(f[:alias], e[:right])
|
|
71
68
|
end
|
|
72
69
|
end
|
|
73
70
|
|
|
@@ -200,9 +197,8 @@ module Sequel
|
|
|
200
197
|
ds = opts.associated_class
|
|
201
198
|
opts.reverse_edges.each{|t| ds = ds.join(t[:table], Array(t[:left]).zip(Array(t[:right])), :table_alias=>t[:alias])}
|
|
202
199
|
ft = opts[:final_reverse_edge]
|
|
203
|
-
|
|
204
|
-
ds =
|
|
205
|
-
ds = model.eager_loading_dataset(opts, ds, Array(opts.select), eo[:associations], eo)
|
|
200
|
+
ds = ds.join(ft[:table], Array(ft[:left]).zip(Array(ft[:right])) + [[opts.eager_loading_predicate_key, h.keys]], :table_alias=>ft[:alias])
|
|
201
|
+
ds = model.eager_loading_dataset(opts, ds, nil, eo[:associations], eo)
|
|
206
202
|
case opts.eager_limit_strategy
|
|
207
203
|
when :window_function
|
|
208
204
|
delete_rn = true
|
|
@@ -262,7 +258,7 @@ module Sequel
|
|
|
262
258
|
edges = ref.edges
|
|
263
259
|
first, rest = edges.first, edges[1..-1]
|
|
264
260
|
last = edges.last
|
|
265
|
-
ds = model.db[first[:table]].select(*Array(first[:
|
|
261
|
+
ds = model.db[first[:table]].select(*Array(ref.qualify(first[:table], first[:right])))
|
|
266
262
|
rest.each{|e| ds = ds.join(e[:table], e.fetch(:only_conditions, (Array(e[:right]).zip(Array(e[:left])) + e[:conditions])), :table_alias=>ds.unused_table_alias(e[:table]), &e[:block])}
|
|
267
263
|
last_alias = if rest.empty?
|
|
268
264
|
first[:table]
|
|
@@ -270,7 +266,7 @@ module Sequel
|
|
|
270
266
|
last_join = ds.opts[:join].last
|
|
271
267
|
last_join.table_alias || last_join.table
|
|
272
268
|
end
|
|
273
|
-
exp = association_filter_key_expression(Array(ref[:final_edge][:left])
|
|
269
|
+
exp = association_filter_key_expression(ref.qualify(last_alias, Array(ref[:final_edge][:left])), ref.right_primary_keys, obj)
|
|
274
270
|
if exp == SQL::Constants::FALSE
|
|
275
271
|
association_filter_handle_inversion(op, exp, Array(lpks))
|
|
276
272
|
else
|
|
@@ -85,7 +85,18 @@ module Sequel
|
|
|
85
85
|
# Return an array of two element arrays with the column symbol as the first entry and the
|
|
86
86
|
# placeholder symbol as the second entry.
|
|
87
87
|
def prepared_statement_key_array(keys)
|
|
88
|
-
|
|
88
|
+
if dataset.requires_placeholder_type_specifiers?
|
|
89
|
+
sch = db_schema
|
|
90
|
+
Array(keys).map do |k|
|
|
91
|
+
if (s = sch[k]) && (t = s[:type])
|
|
92
|
+
[k, :"$#{k}__#{t}"]
|
|
93
|
+
else
|
|
94
|
+
[k, :"$#{k}"]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
Array(keys).map{|k| [k, :"$#{k}"]}
|
|
99
|
+
end
|
|
89
100
|
end
|
|
90
101
|
|
|
91
102
|
# Return a hash mapping column symbols to placeholder symbols.
|
|
@@ -51,7 +51,7 @@ module Sequel
|
|
|
51
51
|
when :one_to_many
|
|
52
52
|
association_bound_variable_hash(opts.associated_class.table_name, opts[:keys], opts[:primary_keys])
|
|
53
53
|
when :many_to_many
|
|
54
|
-
association_bound_variable_hash(opts
|
|
54
|
+
association_bound_variable_hash(opts.join_table_alias, opts[:left_keys], opts[:left_primary_keys])
|
|
55
55
|
when :many_through_many
|
|
56
56
|
opts.reverse_edges
|
|
57
57
|
association_bound_variable_hash(opts[:final_reverse_edge][:alias], Array(opts[:left_key]), opts[:left_primary_keys])
|
|
@@ -109,7 +109,15 @@ module Sequel
|
|
|
109
109
|
ka = opts[:key_alias] ||= :x_root_x
|
|
110
110
|
t = opts[:cte_name] ||= :t
|
|
111
111
|
opts[:reciprocal] = nil
|
|
112
|
-
c_all =
|
|
112
|
+
c_all = if model.dataset.recursive_cte_requires_column_aliases?
|
|
113
|
+
# Work around Oracle/ruby-oci8 bug that returns integers as BigDecimals in recursive queries.
|
|
114
|
+
conv_bd = model.db.database_type == :oracle
|
|
115
|
+
col_aliases = model.dataset.columns
|
|
116
|
+
model_table = model.table_name
|
|
117
|
+
col_aliases.map{|c| SQL::QualifiedIdentifier.new(model_table, c)}
|
|
118
|
+
else
|
|
119
|
+
[SQL::ColumnAll.new(model.table_name)]
|
|
120
|
+
end
|
|
113
121
|
|
|
114
122
|
a = opts.merge(opts.fetch(:ancestors, {}))
|
|
115
123
|
ancestors = a.fetch(:name, :ancestors)
|
|
@@ -125,9 +133,9 @@ module Sequel
|
|
|
125
133
|
end
|
|
126
134
|
table_alias = model.dataset.schema_and_table(model.table_name)[1].to_sym
|
|
127
135
|
model.from(t => table_alias).
|
|
128
|
-
with_recursive(t, base_ds.select_all,
|
|
129
|
-
recursive_ds.
|
|
130
|
-
|
|
136
|
+
with_recursive(t, col_aliases ? base_ds.select(*col_aliases) : base_ds.select_all,
|
|
137
|
+
recursive_ds.select(*c_all),
|
|
138
|
+
:args=>col_aliases)
|
|
131
139
|
end
|
|
132
140
|
aal = Array(a[:after_load])
|
|
133
141
|
aal << proc do |m, ancs|
|
|
@@ -163,9 +171,9 @@ module Sequel
|
|
|
163
171
|
end
|
|
164
172
|
r = model.association_reflection(ancestors)
|
|
165
173
|
base_case = model.filter(prkey=>id_map.keys).
|
|
166
|
-
select(SQL::AliasedExpression.new(prkey, ka), c_all)
|
|
174
|
+
select(SQL::AliasedExpression.new(prkey, ka), *c_all)
|
|
167
175
|
recursive_case = model.join(t, key=>prkey).
|
|
168
|
-
select(SQL::QualifiedIdentifier.new(t, ka), c_all)
|
|
176
|
+
select(SQL::QualifiedIdentifier.new(t, ka), *c_all)
|
|
169
177
|
if c = r[:conditions]
|
|
170
178
|
(base_case, recursive_case) = [base_case, recursive_case].collect do |ds|
|
|
171
179
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.filter(*c) : ds.filter(c)
|
|
@@ -175,7 +183,8 @@ module Sequel
|
|
|
175
183
|
elds = model.eager_loading_dataset(r,
|
|
176
184
|
model.from(t => table_alias).
|
|
177
185
|
with_recursive(t, base_case,
|
|
178
|
-
recursive_case
|
|
186
|
+
recursive_case,
|
|
187
|
+
:args=>(([ka] + col_aliases) if col_aliases)),
|
|
179
188
|
r.select,
|
|
180
189
|
eo[:associations], eo)
|
|
181
190
|
elds = elds.select_append(ka) unless elds.opts[:select] == nil
|
|
@@ -192,7 +201,9 @@ module Sequel
|
|
|
192
201
|
(children_map[obj[key]] ||= []) << obj
|
|
193
202
|
end
|
|
194
203
|
|
|
195
|
-
|
|
204
|
+
kv = obj.values.delete(ka)
|
|
205
|
+
kv = kv.to_i if conv_bd && kv.is_a?(BigDecimal)
|
|
206
|
+
if roots = id_map[kv]
|
|
196
207
|
roots.each do |root|
|
|
197
208
|
root.associations[ancestors] << obj
|
|
198
209
|
end
|
|
@@ -222,9 +233,9 @@ module Sequel
|
|
|
222
233
|
end
|
|
223
234
|
table_alias = model.dataset.schema_and_table(model.table_name)[1].to_sym
|
|
224
235
|
model.from(t => table_alias).
|
|
225
|
-
with_recursive(t, base_ds.select_all,
|
|
226
|
-
recursive_ds.
|
|
227
|
-
|
|
236
|
+
with_recursive(t, col_aliases ? base_ds.select(*col_aliases) : base_ds.select_all,
|
|
237
|
+
recursive_ds.select(*c_all),
|
|
238
|
+
:args=>col_aliases)
|
|
228
239
|
end
|
|
229
240
|
dal = Array(d[:after_load])
|
|
230
241
|
dal << proc do |m, descs|
|
|
@@ -259,9 +270,9 @@ module Sequel
|
|
|
259
270
|
end
|
|
260
271
|
r = model.association_reflection(descendants)
|
|
261
272
|
base_case = model.filter(key=>id_map.keys).
|
|
262
|
-
select(SQL::AliasedExpression.new(key, ka), c_all)
|
|
273
|
+
select(SQL::AliasedExpression.new(key, ka), *c_all)
|
|
263
274
|
recursive_case = model.join(t, prkey=>key).
|
|
264
|
-
select(SQL::QualifiedIdentifier.new(t, ka), c_all)
|
|
275
|
+
select(SQL::QualifiedIdentifier.new(t, ka), *c_all)
|
|
265
276
|
if c = r[:conditions]
|
|
266
277
|
(base_case, recursive_case) = [base_case, recursive_case].collect do |ds|
|
|
267
278
|
(c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.filter(*c) : ds.filter(c)
|
|
@@ -276,7 +287,8 @@ module Sequel
|
|
|
276
287
|
end
|
|
277
288
|
table_alias = model.dataset.schema_and_table(model.table_name)[1].to_sym
|
|
278
289
|
elds = model.eager_loading_dataset(r,
|
|
279
|
-
model.from(t => table_alias).with_recursive(t, base_case, recursive_case
|
|
290
|
+
model.from(t => table_alias).with_recursive(t, base_case, recursive_case,
|
|
291
|
+
:args=>(([ka] + col_aliases + (level ? [la] : [])) if col_aliases)),
|
|
280
292
|
r.select,
|
|
281
293
|
associations, eo)
|
|
282
294
|
elds = elds.select_append(ka) unless elds.opts[:select] == nil
|
|
@@ -296,7 +308,9 @@ module Sequel
|
|
|
296
308
|
parent_map[opk] = obj
|
|
297
309
|
end
|
|
298
310
|
|
|
299
|
-
|
|
311
|
+
kv = obj.values.delete(ka)
|
|
312
|
+
kv = kv.to_i if conv_bd && kv.is_a?(BigDecimal)
|
|
313
|
+
if root = id_map[kv].first
|
|
300
314
|
root.associations[descendants] << obj
|
|
301
315
|
end
|
|
302
316
|
|
|
@@ -110,7 +110,7 @@ module Sequel
|
|
|
110
110
|
attr_reader :deserialized_values
|
|
111
111
|
|
|
112
112
|
# Set @deserialized_values to the empty hash
|
|
113
|
-
def
|
|
113
|
+
def initialize_set(values)
|
|
114
114
|
@deserialized_values = {}
|
|
115
115
|
super
|
|
116
116
|
end
|
|
@@ -127,6 +127,11 @@ module Sequel
|
|
|
127
127
|
super
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
def set_values(*)
|
|
131
|
+
@deserialized_values ||= {}
|
|
132
|
+
super
|
|
133
|
+
end
|
|
134
|
+
|
|
130
135
|
private
|
|
131
136
|
|
|
132
137
|
# Deserialize the column from either marshal or yaml format
|
|
@@ -90,11 +90,6 @@ module Sequel
|
|
|
90
90
|
use_server(super)
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
# Make sure to use the correct shard when using a transaction
|
|
94
|
-
def checked_transaction(opts={}, &block)
|
|
95
|
-
super(@server ? {:server=>@server}.merge(opts) : opts, &block)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
93
|
# If creating the object by doing <tt>add_association</tt> for a
|
|
99
94
|
# +many_to_many+ association, make sure the associated object is created on the
|
|
100
95
|
# current object's shard, unless the passed object already has an assigned shard.
|
|
@@ -124,7 +124,7 @@ module Sequel
|
|
|
124
124
|
# Return an instance of the class specified by sti_key,
|
|
125
125
|
# used by the row_proc.
|
|
126
126
|
def sti_load(r)
|
|
127
|
-
sti_class(sti_model_map[r[sti_key]]).
|
|
127
|
+
sti_class(sti_model_map[r[sti_key]]).call(r)
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
# Make sure that all subclasses of the parent class correctly include
|
|
@@ -5,7 +5,7 @@ module Sequel
|
|
|
5
5
|
# typecast correctly (with correct being defined as how the model object
|
|
6
6
|
# would typecast the same column values).
|
|
7
7
|
#
|
|
8
|
-
# This plugin modifies Model
|
|
8
|
+
# This plugin modifies Model#set_values to call the setter methods (which typecast
|
|
9
9
|
# by default) for all columns given. You can either specify the columns to
|
|
10
10
|
# typecast on load in the plugin call itself, or afterwards using
|
|
11
11
|
# add_typecast_on_load_columns:
|
|
@@ -41,16 +41,11 @@ module Sequel
|
|
|
41
41
|
super
|
|
42
42
|
subclass.instance_variable_set(:@typecast_on_load_columns, typecast_on_load_columns.dup)
|
|
43
43
|
end
|
|
44
|
-
|
|
45
|
-
# Call the setter method for each of the typecast on load columns,
|
|
46
|
-
# ensuring the model object will have the correct typecasting even
|
|
47
|
-
# if the database doesn't typecast the columns correctly.
|
|
48
|
-
def load(values)
|
|
49
|
-
super.load_typecast
|
|
50
|
-
end
|
|
51
44
|
end
|
|
52
45
|
|
|
53
46
|
module InstanceMethods
|
|
47
|
+
# Call the setter method for each of the model's typecast_on_load_columns
|
|
48
|
+
# with the current value, so it can be typecasted correctly.
|
|
54
49
|
def load_typecast
|
|
55
50
|
model.typecast_on_load_columns.each do |c|
|
|
56
51
|
if v = values[c]
|
|
@@ -61,10 +56,12 @@ module Sequel
|
|
|
61
56
|
self
|
|
62
57
|
end
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def
|
|
67
|
-
super
|
|
59
|
+
# Typecast values using #load_typecast when the values are retrieved from
|
|
60
|
+
# the database.
|
|
61
|
+
def set_values(values)
|
|
62
|
+
ret = super
|
|
63
|
+
load_typecast
|
|
64
|
+
ret
|
|
68
65
|
end
|
|
69
66
|
end
|
|
70
67
|
end
|