sequel 4.41.0 → 4.42.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/CHANGELOG +98 -0
- data/README.rdoc +23 -10
- data/doc/active_record.rdoc +4 -4
- data/doc/advanced_associations.rdoc +2 -2
- data/doc/association_basics.rdoc +5 -2
- data/doc/cheat_sheet.rdoc +3 -3
- data/doc/core_extensions.rdoc +2 -2
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +1 -1
- data/doc/migration.rdoc +19 -1
- data/doc/prepared_statements.rdoc +2 -2
- data/doc/release_notes/4.42.0.txt +221 -0
- data/doc/testing.rdoc +3 -1
- data/lib/sequel/adapters/ado/access.rb +0 -1
- data/lib/sequel/adapters/ado/mssql.rb +0 -1
- data/lib/sequel/adapters/do/mysql.rb +0 -1
- data/lib/sequel/adapters/do/postgres.rb +0 -1
- data/lib/sequel/adapters/do/sqlite3.rb +0 -1
- data/lib/sequel/adapters/ibmdb.rb +21 -25
- data/lib/sequel/adapters/jdbc.rb +8 -16
- data/lib/sequel/adapters/jdbc/as400.rb +0 -1
- data/lib/sequel/adapters/jdbc/cubrid.rb +0 -1
- data/lib/sequel/adapters/jdbc/db2.rb +0 -1
- data/lib/sequel/adapters/jdbc/derby.rb +0 -1
- data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -1
- data/lib/sequel/adapters/jdbc/h2.rb +0 -1
- data/lib/sequel/adapters/jdbc/hsqldb.rb +0 -1
- data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -1
- data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -1
- data/lib/sequel/adapters/jdbc/jtds.rb +0 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +0 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +0 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +0 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +0 -13
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +0 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +0 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -4
- data/lib/sequel/adapters/mock.rb +54 -12
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +11 -17
- data/lib/sequel/adapters/odbc/mssql.rb +0 -1
- data/lib/sequel/adapters/oracle.rb +8 -20
- data/lib/sequel/adapters/postgres.rb +11 -29
- data/lib/sequel/adapters/shared/access.rb +5 -12
- data/lib/sequel/adapters/shared/cubrid.rb +4 -13
- data/lib/sequel/adapters/shared/db2.rb +4 -2
- data/lib/sequel/adapters/shared/firebird.rb +2 -4
- data/lib/sequel/adapters/shared/informix.rb +4 -2
- data/lib/sequel/adapters/shared/mssql.rb +3 -5
- data/lib/sequel/adapters/shared/mysql.rb +4 -14
- data/lib/sequel/adapters/shared/oracle.rb +1 -3
- data/lib/sequel/adapters/shared/postgres.rb +16 -38
- data/lib/sequel/adapters/shared/progress.rb +0 -2
- data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -2
- data/lib/sequel/adapters/shared/sqlite.rb +20 -16
- data/lib/sequel/adapters/sqlite.rb +8 -20
- data/lib/sequel/adapters/swift/mysql.rb +0 -1
- data/lib/sequel/adapters/swift/postgres.rb +0 -1
- data/lib/sequel/adapters/swift/sqlite.rb +0 -1
- data/lib/sequel/adapters/tinytds.rb +4 -12
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +1 -1
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -2
- data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +11 -34
- data/lib/sequel/adapters/utils/stored_procedures.rb +9 -22
- data/lib/sequel/adapters/utils/unmodified_identifiers.rb +26 -0
- data/lib/sequel/ast_transformer.rb +2 -2
- data/lib/sequel/database/dataset.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +0 -66
- data/lib/sequel/database/features.rb +6 -0
- data/lib/sequel/database/misc.rb +31 -17
- data/lib/sequel/database/query.rb +7 -4
- data/lib/sequel/database/schema_methods.rb +1 -1
- data/lib/sequel/dataset.rb +8 -8
- data/lib/sequel/dataset/actions.rb +140 -46
- data/lib/sequel/dataset/features.rb +1 -5
- data/lib/sequel/dataset/graph.rb +7 -8
- data/lib/sequel/dataset/misc.rb +127 -56
- data/lib/sequel/dataset/mutation.rb +9 -20
- data/lib/sequel/dataset/placeholder_literalizer.rb +10 -1
- data/lib/sequel/dataset/prepared_statements.rb +102 -46
- data/lib/sequel/dataset/query.rb +155 -72
- data/lib/sequel/dataset/sql.rb +26 -9
- data/lib/sequel/extensions/columns_introspection.rb +3 -1
- data/lib/sequel/extensions/core_extensions.rb +5 -5
- data/lib/sequel/extensions/core_refinements.rb +5 -5
- data/lib/sequel/extensions/duplicate_columns_handler.rb +4 -2
- data/lib/sequel/extensions/freeze_datasets.rb +69 -0
- data/lib/sequel/extensions/identifier_mangling.rb +196 -0
- data/lib/sequel/extensions/looser_typecasting.rb +11 -7
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/null_dataset.rb +5 -2
- data/lib/sequel/extensions/pagination.rb +42 -23
- data/lib/sequel/extensions/pg_enum.rb +3 -3
- data/lib/sequel/extensions/query.rb +3 -3
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +15 -8
- data/lib/sequel/model/associations.rb +25 -8
- data/lib/sequel/model/base.rb +88 -29
- data/lib/sequel/model/dataset_module.rb +37 -0
- data/lib/sequel/plugins/association_pks.rb +4 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/constraint_validations.rb +1 -2
- data/lib/sequel/plugins/csv_serializer.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +8 -8
- data/lib/sequel/plugins/eager_each.rb +2 -2
- data/lib/sequel/plugins/instance_filters.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +2 -2
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/list.rb +4 -4
- data/lib/sequel/plugins/prepared_statements.rb +2 -4
- data/lib/sequel/plugins/prepared_statements_associations.rb +1 -3
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +13 -13
- data/lib/sequel/plugins/sharding.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +9 -4
- data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/plugins/xml_serializer.rb +2 -2
- data/lib/sequel/sql.rb +69 -36
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +10 -0
- data/spec/adapters/firebird_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +4 -5
- data/spec/adapters/mysql_spec.rb +9 -9
- data/spec/adapters/postgres_spec.rb +67 -68
- data/spec/adapters/spec_helper.rb +6 -1
- data/spec/adapters/sqlite_spec.rb +29 -15
- data/spec/core/connection_pool_spec.rb +14 -14
- data/spec/core/database_spec.rb +38 -180
- data/spec/core/dataset_mutation_spec.rb +253 -0
- data/spec/core/dataset_spec.rb +394 -537
- data/spec/core/expression_filters_spec.rb +34 -32
- data/spec/core/mock_adapter_spec.rb +27 -35
- data/spec/core/placeholder_literalizer_spec.rb +2 -4
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +1 -2
- data/spec/core_extensions_spec.rb +22 -29
- data/spec/extensions/active_model_spec.rb +6 -6
- data/spec/extensions/association_dependencies_spec.rb +2 -2
- data/spec/extensions/blacklist_security_spec.rb +3 -3
- data/spec/extensions/boolean_readers_spec.rb +12 -12
- data/spec/extensions/caching_spec.rb +13 -10
- data/spec/extensions/class_table_inheritance_spec.rb +38 -43
- data/spec/extensions/column_conflicts_spec.rb +1 -3
- data/spec/extensions/columns_introspection_spec.rb +2 -3
- data/spec/extensions/composition_spec.rb +5 -3
- data/spec/extensions/constraint_validations_plugin_spec.rb +5 -5
- data/spec/extensions/constraint_validations_spec.rb +14 -8
- data/spec/extensions/core_refinements_spec.rb +22 -29
- data/spec/extensions/csv_serializer_spec.rb +7 -6
- data/spec/extensions/date_arithmetic_spec.rb +15 -15
- data/spec/extensions/defaults_setter_spec.rb +2 -2
- data/spec/extensions/delay_add_association_spec.rb +1 -1
- data/spec/extensions/dirty_spec.rb +19 -10
- data/spec/extensions/duplicate_columns_handler_spec.rb +12 -18
- data/spec/extensions/eager_each_spec.rb +12 -16
- data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
- data/spec/extensions/eval_inspect_spec.rb +4 -3
- data/spec/extensions/force_encoding_spec.rb +12 -12
- data/spec/extensions/freeze_datasets_spec.rb +31 -0
- data/spec/extensions/graph_each_spec.rb +6 -18
- data/spec/extensions/hook_class_methods_spec.rb +7 -7
- data/spec/extensions/identifier_mangling_spec.rb +307 -0
- data/spec/extensions/instance_filters_spec.rb +5 -6
- data/spec/extensions/instance_hooks_spec.rb +12 -12
- data/spec/extensions/json_serializer_spec.rb +12 -15
- data/spec/extensions/lazy_attributes_spec.rb +4 -4
- data/spec/extensions/list_spec.rb +19 -21
- data/spec/extensions/many_through_many_spec.rb +108 -163
- data/spec/extensions/meta_def_spec.rb +7 -2
- data/spec/extensions/migration_spec.rb +10 -12
- data/spec/extensions/mssql_optimistic_locking_spec.rb +4 -3
- data/spec/extensions/named_timezones_spec.rb +4 -3
- data/spec/extensions/nested_attributes_spec.rb +2 -2
- data/spec/extensions/null_dataset_spec.rb +17 -12
- data/spec/extensions/optimistic_locking_spec.rb +4 -5
- data/spec/extensions/pagination_spec.rb +8 -10
- data/spec/extensions/pg_array_associations_spec.rb +28 -27
- data/spec/extensions/pg_array_ops_spec.rb +2 -1
- data/spec/extensions/pg_array_spec.rb +6 -2
- data/spec/extensions/pg_enum_spec.rb +5 -3
- data/spec/extensions/pg_hstore_ops_spec.rb +3 -1
- data/spec/extensions/pg_hstore_spec.rb +7 -6
- data/spec/extensions/pg_inet_ops_spec.rb +2 -1
- data/spec/extensions/pg_inet_spec.rb +2 -1
- data/spec/extensions/pg_interval_spec.rb +2 -1
- data/spec/extensions/pg_json_ops_spec.rb +2 -1
- data/spec/extensions/pg_json_spec.rb +6 -3
- data/spec/extensions/pg_loose_count_spec.rb +1 -0
- data/spec/extensions/pg_range_ops_spec.rb +3 -1
- data/spec/extensions/pg_range_spec.rb +9 -5
- data/spec/extensions/pg_row_ops_spec.rb +2 -1
- data/spec/extensions/pg_row_plugin_spec.rb +4 -6
- data/spec/extensions/pg_row_spec.rb +5 -3
- data/spec/extensions/pg_static_cache_updater_spec.rb +2 -1
- data/spec/extensions/pg_typecast_on_load_spec.rb +1 -1
- data/spec/extensions/prepared_statements_associations_spec.rb +1 -1
- data/spec/extensions/prepared_statements_spec.rb +12 -11
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +8 -5
- data/spec/extensions/rcte_tree_spec.rb +39 -39
- data/spec/extensions/round_timestamps_spec.rb +2 -2
- data/spec/extensions/schema_dumper_spec.rb +3 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/scissors_spec.rb +1 -2
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +30 -17
- data/spec/extensions/serialization_modification_detection_spec.rb +2 -2
- data/spec/extensions/serialization_spec.rb +15 -13
- data/spec/extensions/set_overrides_spec.rb +14 -8
- data/spec/extensions/sharding_spec.rb +9 -18
- data/spec/extensions/shared_caching_spec.rb +3 -4
- data/spec/extensions/single_table_inheritance_spec.rb +11 -11
- data/spec/extensions/skip_create_refresh_spec.rb +2 -1
- data/spec/extensions/spec_helper.rb +1 -1
- data/spec/extensions/split_values_spec.rb +2 -2
- data/spec/extensions/sql_comments_spec.rb +6 -0
- data/spec/extensions/static_cache_spec.rb +7 -9
- data/spec/extensions/string_agg_spec.rb +30 -29
- data/spec/extensions/tactical_eager_loading_spec.rb +4 -5
- data/spec/extensions/thread_local_timezones_spec.rb +2 -2
- data/spec/extensions/timestamps_spec.rb +28 -3
- data/spec/extensions/to_dot_spec.rb +1 -2
- data/spec/extensions/tree_spec.rb +33 -29
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/unlimited_update_spec.rb +1 -0
- data/spec/extensions/update_primary_key_spec.rb +11 -7
- data/spec/extensions/update_refresh_spec.rb +1 -1
- data/spec/extensions/uuid_spec.rb +0 -1
- data/spec/extensions/validate_associated_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +10 -10
- data/spec/extensions/validation_helpers_spec.rb +10 -10
- data/spec/extensions/xml_serializer_spec.rb +7 -3
- data/spec/integration/associations_test.rb +31 -31
- data/spec/integration/dataset_test.rb +17 -19
- data/spec/integration/eager_loader_test.rb +24 -24
- data/spec/integration/model_test.rb +6 -6
- data/spec/integration/plugin_test.rb +43 -43
- data/spec/integration/prepared_statement_test.rb +6 -6
- data/spec/integration/schema_test.rb +63 -52
- data/spec/integration/spec_helper.rb +6 -1
- data/spec/integration/transaction_test.rb +13 -13
- data/spec/model/association_reflection_spec.rb +17 -17
- data/spec/model/associations_spec.rb +101 -96
- data/spec/model/base_spec.rb +175 -49
- data/spec/model/class_dataset_methods_spec.rb +5 -9
- data/spec/model/dataset_methods_spec.rb +5 -5
- data/spec/model/eager_loading_spec.rb +209 -235
- data/spec/model/hooks_spec.rb +15 -15
- data/spec/model/model_spec.rb +28 -21
- data/spec/model/plugins_spec.rb +4 -5
- data/spec/model/record_spec.rb +59 -57
- data/spec/model/spec_helper.rb +1 -1
- data/spec/model/validations_spec.rb +6 -6
- data/spec/spec_config.rb +1 -1
- metadata +10 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
#
|
|
8
8
|
# It allows creation of enum types using create_enum:
|
|
9
9
|
#
|
|
10
|
-
# DB.create_enum(:
|
|
10
|
+
# DB.create_enum(:enum_type_name, %w'value1 value2 value3')
|
|
11
11
|
#
|
|
12
12
|
# You can also add values to existing enums via add_enum_value:
|
|
13
13
|
#
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
#
|
|
16
16
|
# If you want to drop an enum type, you can use drop_enum:
|
|
17
17
|
#
|
|
18
|
-
# DB.drop_enum(:
|
|
18
|
+
# DB.drop_enum(:enum_type_name)
|
|
19
19
|
#
|
|
20
20
|
# Just like any user-created type, after creating the type, you
|
|
21
21
|
# can create tables that have a column of that type:
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
#
|
|
45
45
|
# Sequel.migration do
|
|
46
46
|
# change do
|
|
47
|
-
# create_enum(:
|
|
47
|
+
# create_enum(:enum_type_name, %w'value1 value2 value3')
|
|
48
48
|
# end
|
|
49
49
|
# end
|
|
50
50
|
#
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# dataset = DB[:items].query do
|
|
8
8
|
# select :x, :y, :z
|
|
9
|
-
#
|
|
9
|
+
# where{(x > 1) & (y > 2)}
|
|
10
10
|
# reverse :z
|
|
11
11
|
# end
|
|
12
12
|
#
|
|
@@ -45,13 +45,13 @@ module Sequel
|
|
|
45
45
|
#
|
|
46
46
|
# dataset = DB[:items].query do
|
|
47
47
|
# select :x, :y, :z
|
|
48
|
-
#
|
|
48
|
+
# where{(x > 1) & (y > 2)}
|
|
49
49
|
# reverse :z
|
|
50
50
|
# end
|
|
51
51
|
#
|
|
52
52
|
# Which is the same as:
|
|
53
53
|
#
|
|
54
|
-
# dataset = DB[:items].select(:x, :y, :z).
|
|
54
|
+
# dataset = DB[:items].select(:x, :y, :z).where{(x > 1) & (y > 2)}.reverse(:z)
|
|
55
55
|
def query(&block)
|
|
56
56
|
query = Dataset::Query.new(self)
|
|
57
57
|
query.instance_eval(&block)
|
|
@@ -27,12 +27,19 @@
|
|
|
27
27
|
module Sequel
|
|
28
28
|
module Sequel3DatasetMethods
|
|
29
29
|
COMMA = Dataset::COMMA
|
|
30
|
-
#
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
# Change the database for this dataset.
|
|
31
|
+
def db=(v)
|
|
32
|
+
raise_if_frozen!
|
|
33
|
+
@db = v
|
|
34
|
+
@cache = {}
|
|
35
|
+
end
|
|
33
36
|
|
|
34
|
-
#
|
|
35
|
-
|
|
37
|
+
# Change the options for this dataset.
|
|
38
|
+
def opts=(v)
|
|
39
|
+
raise_if_frozen!
|
|
40
|
+
@opts = v
|
|
41
|
+
@cache = {}
|
|
42
|
+
end
|
|
36
43
|
|
|
37
44
|
# Update all records matching the conditions with the values specified.
|
|
38
45
|
# Returns the number of rows affected.
|
|
@@ -40,7 +47,7 @@ module Sequel
|
|
|
40
47
|
# DB[:table][:id=>1] = {:id=>2} # UPDATE table SET id = 2 WHERE id = 1
|
|
41
48
|
# # => 1 # number of rows affected
|
|
42
49
|
def []=(conditions, values)
|
|
43
|
-
|
|
50
|
+
where(conditions).update(values)
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
# Inserts multiple values. If a block is given it is invoked for each
|
|
@@ -71,7 +78,7 @@ module Sequel
|
|
|
71
78
|
# given table. If no columns are currently selected, select all
|
|
72
79
|
# columns of the given table.
|
|
73
80
|
#
|
|
74
|
-
# DB[:items].
|
|
81
|
+
# DB[:items].where(:id=>1).qualify_to(:i)
|
|
75
82
|
# # SELECT i.* FROM items WHERE (i.id = 1)
|
|
76
83
|
def qualify_to(table)
|
|
77
84
|
qualify(table)
|
|
@@ -83,7 +90,7 @@ module Sequel
|
|
|
83
90
|
# has columns with the same name as columns in the current dataset.
|
|
84
91
|
# See +qualify_to+.
|
|
85
92
|
#
|
|
86
|
-
# DB[:items].
|
|
93
|
+
# DB[:items].where(:id=>1).qualify_to_first_source
|
|
87
94
|
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
88
95
|
def qualify_to_first_source
|
|
89
96
|
qualify
|
|
@@ -68,9 +68,9 @@ module Sequel
|
|
|
68
68
|
|
|
69
69
|
# Apply all non-instance specific changes to the given dataset and return it.
|
|
70
70
|
def apply_dataset_changes(ds)
|
|
71
|
-
ds.
|
|
72
|
-
|
|
73
|
-
self[:extend].each{|m| ds.
|
|
71
|
+
ds = ds.with_extend(AssociationDatasetMethods).
|
|
72
|
+
clone(:association_reflection => self)
|
|
73
|
+
self[:extend].each{|m| ds = ds.with_extend(m)}
|
|
74
74
|
ds = ds.select(*select) if select
|
|
75
75
|
if c = self[:conditions]
|
|
76
76
|
ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
|
|
@@ -263,6 +263,7 @@ module Sequel
|
|
|
263
263
|
|
|
264
264
|
eager_limit =
|
|
265
265
|
if el = ds.opts[:eager_limit]
|
|
266
|
+
raise Error, "The :eager_limit dataset option is not supported for associations returning a single record" unless returns_array?
|
|
266
267
|
strategy ||= true_eager_graph_limit_strategy
|
|
267
268
|
if el.is_a?(Array)
|
|
268
269
|
el
|
|
@@ -276,6 +277,7 @@ module Sequel
|
|
|
276
277
|
strategy = true_eager_graph_limit_strategy if strategy == :union
|
|
277
278
|
# Correlated subqueries are not supported for regular eager loading
|
|
278
279
|
strategy = :ruby if strategy == :correlated_subquery
|
|
280
|
+
strategy = nil if strategy == :ruby && assign_singular?
|
|
279
281
|
objects = apply_eager_limit_strategy(ds, strategy, eager_limit).all
|
|
280
282
|
elsif strategy == :union
|
|
281
283
|
objects = []
|
|
@@ -1358,11 +1360,17 @@ module Sequel
|
|
|
1358
1360
|
|
|
1359
1361
|
# This module contains methods added to all association datasets
|
|
1360
1362
|
module AssociationDatasetMethods
|
|
1363
|
+
Dataset.def_deprecated_opts_setter(self, :model, :association_reflection)
|
|
1364
|
+
|
|
1361
1365
|
# The model object that created the association dataset
|
|
1362
|
-
|
|
1366
|
+
def model_object
|
|
1367
|
+
@opts[:model_object]
|
|
1368
|
+
end
|
|
1363
1369
|
|
|
1364
1370
|
# The association reflection related to the association dataset
|
|
1365
|
-
|
|
1371
|
+
def association_reflection
|
|
1372
|
+
@opts[:association_reflection]
|
|
1373
|
+
end
|
|
1366
1374
|
end
|
|
1367
1375
|
|
|
1368
1376
|
# Each kind of association adds a number of instance methods to the model class which
|
|
@@ -1501,6 +1509,10 @@ module Sequel
|
|
|
1501
1509
|
# the given association. Can be used to DRY up a bunch of similar associations that
|
|
1502
1510
|
# all share the same options such as :class and :key, while changing the order and block used.
|
|
1503
1511
|
# :conditions :: The conditions to use to filter the association, can be any argument passed to where.
|
|
1512
|
+
# This option is not respected when using eager_graph or association_join, unless it
|
|
1513
|
+
# is hash or array of two element arrays. Consider also specifying the :graph_block
|
|
1514
|
+
# option if the value for this option is not a hash or array of two element arrays
|
|
1515
|
+
# and you plan to use this association in eager_graph or association_join.
|
|
1504
1516
|
# :dataset :: A proc that is instance_execed to get the base dataset to use (before the other
|
|
1505
1517
|
# options are applied). If the proc accepts an argument, it is passed the related
|
|
1506
1518
|
# association reflection.
|
|
@@ -2118,7 +2130,7 @@ module Sequel
|
|
|
2118
2130
|
unless ds.kind_of?(AssociationDatasetMethods)
|
|
2119
2131
|
ds = opts.apply_dataset_changes(ds)
|
|
2120
2132
|
end
|
|
2121
|
-
ds.model_object
|
|
2133
|
+
ds = ds.clone(:model_object => self)
|
|
2122
2134
|
ds = ds.eager_graph(opts[:eager_graph]) if opts[:eager_graph] && opts.eager_graph_lazy_dataset?
|
|
2123
2135
|
ds = instance_exec(ds, &opts[:block]) if opts[:block]
|
|
2124
2136
|
ds
|
|
@@ -2697,7 +2709,7 @@ END
|
|
|
2697
2709
|
def ungraphed
|
|
2698
2710
|
ds = super.clone(:eager_graph=>nil)
|
|
2699
2711
|
if (eg = @opts[:eager_graph]) && (rp = eg[:row_proc])
|
|
2700
|
-
ds
|
|
2712
|
+
ds = ds.with_row_proc(rp)
|
|
2701
2713
|
end
|
|
2702
2714
|
ds
|
|
2703
2715
|
end
|
|
@@ -2737,9 +2749,14 @@ END
|
|
|
2737
2749
|
end
|
|
2738
2750
|
local_opts = ds.opts[:eager_graph][:local]
|
|
2739
2751
|
limit_strategy = r.eager_graph_limit_strategy(local_opts[:limit_strategy])
|
|
2752
|
+
|
|
2753
|
+
if r[:conditions] && !Sequel.condition_specifier?(r[:conditions]) && !r[:orig_opts].has_key?(:graph_conditions) && !r[:orig_opts].has_key?(:graph_only_conditions) && !r.has_key?(:graph_block)
|
|
2754
|
+
Sequel::Deprecation.deprecate("Ignoring :conditions for #{r[:model]} #{r[:name]} association during eager_graph/association_join, consider specifying :graph_block") unless r[:ignore_conditions_warning]
|
|
2755
|
+
end
|
|
2756
|
+
|
|
2740
2757
|
ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
|
|
2741
2758
|
if r[:order_eager_graph] && (order = r.fetch(:graph_order, r[:order]))
|
|
2742
|
-
ds = ds.
|
|
2759
|
+
ds = ds.order_append(*qualified_expression(order, assoc_table_alias))
|
|
2743
2760
|
end
|
|
2744
2761
|
eager_graph = ds.opts[:eager_graph]
|
|
2745
2762
|
eager_graph[:requirements][assoc_table_alias] = requirements.dup
|
data/lib/sequel/model/base.rb
CHANGED
|
@@ -286,25 +286,42 @@ module Sequel
|
|
|
286
286
|
# Returns the module given or the anonymous module created.
|
|
287
287
|
#
|
|
288
288
|
# # Usage with existing module
|
|
289
|
-
#
|
|
289
|
+
# Album.dataset_module Sequel::ColumnsIntrospection
|
|
290
290
|
#
|
|
291
291
|
# # Usage with anonymous module
|
|
292
|
-
#
|
|
292
|
+
# Album.dataset_module do
|
|
293
293
|
# def foo
|
|
294
294
|
# :bar
|
|
295
295
|
# end
|
|
296
296
|
# end
|
|
297
|
-
#
|
|
297
|
+
# Album.dataset.foo
|
|
298
298
|
# # => :bar
|
|
299
|
-
#
|
|
299
|
+
# Album.foo
|
|
300
300
|
# # => :bar
|
|
301
301
|
#
|
|
302
302
|
# Any anonymous modules created are actually instances of Sequel::Model::DatasetModule
|
|
303
|
-
# (a Module subclass), which allows you to call the subset method on them
|
|
304
|
-
#
|
|
305
|
-
#
|
|
306
|
-
#
|
|
303
|
+
# (a Module subclass), which allows you to call the subset method on them, which
|
|
304
|
+
# defines a dataset method that adds a filter. There are also a number of other
|
|
305
|
+
# methods with the same names as the dataset methods, which can use to define
|
|
306
|
+
# named dataset methods:
|
|
307
|
+
#
|
|
308
|
+
# Album.dataset_module do
|
|
309
|
+
# subset :released, Sequel.identifier(release_date) <= Sequel::CURRENT_DATE
|
|
310
|
+
# order :by_release_date, :release_date
|
|
311
|
+
# select :for_select_options, :id, :name, :release_date
|
|
307
312
|
# end
|
|
313
|
+
# Album.released.sql
|
|
314
|
+
# # => "SELECT * FROM artists WHERE (release_date <= CURRENT_DATE)"
|
|
315
|
+
# Album.by_release_date.sql
|
|
316
|
+
# # => "SELECT * FROM artists ORDER BY release_date"
|
|
317
|
+
# Album.for_select_options.sql
|
|
318
|
+
# # => "SELECT id, name, release_date FROM artists"
|
|
319
|
+
# Album.released.by_release_date.for_select_options.sql
|
|
320
|
+
# # => "SELECT id, name, release_date FROM artists WHERE (release_date <= CURRENT_DATE) ORDER BY release_date"
|
|
321
|
+
#
|
|
322
|
+
# The following methods are supported: distinct, exclude, exclude_having, grep, group, group_and_count,
|
|
323
|
+
# group_append, having, limit, offset, order, order_append, order_prepend, select, select_all,
|
|
324
|
+
# select_append, select_group, where, and server.
|
|
308
325
|
#
|
|
309
326
|
# Any public methods in the dataset module will have class methods created that
|
|
310
327
|
# call the method on the dataset, assuming that the class method is not already
|
|
@@ -388,14 +405,15 @@ module Sequel
|
|
|
388
405
|
# If a block is not given, just define a class method on the model for each argument
|
|
389
406
|
# that calls the dataset method of the same argument name.
|
|
390
407
|
#
|
|
391
|
-
#
|
|
392
|
-
#
|
|
393
|
-
#
|
|
408
|
+
# Using dataset_module is recommended over using this method. In addition to allowing
|
|
409
|
+
# more natural ruby syntax for defining methods manually, it also offers numerous
|
|
410
|
+
# helper methods that make defining common dataset methods more easily, as well as
|
|
411
|
+
# supporting dataset caching (assuming the arguments allow it).
|
|
394
412
|
#
|
|
395
413
|
# # Add new dataset method and class method that calls it
|
|
396
414
|
# Artist.def_dataset_method(:by_name){order(:name)}
|
|
397
|
-
# Artist.
|
|
398
|
-
# Artist.by_name.
|
|
415
|
+
# Artist.where(:name.like('A%')).by_name
|
|
416
|
+
# Artist.by_name.where(:name.like('A%'))
|
|
399
417
|
#
|
|
400
418
|
# # Just add a class method that calls an existing dataset method
|
|
401
419
|
# Artist.def_dataset_method(:server!)
|
|
@@ -424,7 +442,7 @@ module Sequel
|
|
|
424
442
|
# Use optimized finder
|
|
425
443
|
first_where(args.first)
|
|
426
444
|
else
|
|
427
|
-
|
|
445
|
+
where(*args, &block).first
|
|
428
446
|
end
|
|
429
447
|
end
|
|
430
448
|
|
|
@@ -707,7 +725,7 @@ module Sequel
|
|
|
707
725
|
# plan to join other tables to this table and you want the column references
|
|
708
726
|
# to be qualified.
|
|
709
727
|
#
|
|
710
|
-
# Artist.
|
|
728
|
+
# Artist.where(Artist.qualified_primary_key_hash(1))
|
|
711
729
|
# # SELECT * FROM artists WHERE (artists.id = 1)
|
|
712
730
|
def qualified_primary_key_hash(value, qualifier=table_name)
|
|
713
731
|
case key = @primary_key
|
|
@@ -802,11 +820,10 @@ module Sequel
|
|
|
802
820
|
@columns = superclass.instance_variable_get(:@columns)
|
|
803
821
|
@db_schema = superclass.instance_variable_get(:@db_schema)
|
|
804
822
|
else
|
|
805
|
-
@
|
|
823
|
+
@dataset = @dataset.with_extend(*@dataset_method_modules.reverse) if @dataset_method_modules
|
|
806
824
|
@db_schema = get_db_schema
|
|
807
825
|
end
|
|
808
826
|
|
|
809
|
-
@dataset.model = self if @dataset.respond_to?(:model=)
|
|
810
827
|
reset_instance_dataset
|
|
811
828
|
self
|
|
812
829
|
end
|
|
@@ -868,7 +885,14 @@ module Sequel
|
|
|
868
885
|
# dataset methods that accept arguments, you should use define a
|
|
869
886
|
# method directly inside a #dataset_module block.
|
|
870
887
|
def subset(name, *args, &block)
|
|
871
|
-
|
|
888
|
+
if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
|
|
889
|
+
def_dataset_method(name){filter(*args, &block)}
|
|
890
|
+
else
|
|
891
|
+
key = :"_subset_#{name}_ds"
|
|
892
|
+
def_dataset_method(name) do
|
|
893
|
+
cached_dataset(key){filter(*args)}
|
|
894
|
+
end
|
|
895
|
+
end
|
|
872
896
|
end
|
|
873
897
|
|
|
874
898
|
# Returns name of primary table for the dataset. If the table for the dataset
|
|
@@ -933,15 +957,15 @@ module Sequel
|
|
|
933
957
|
else
|
|
934
958
|
raise(Error, "Model.set_dataset takes one of the following classes as an argument: Symbol, LiteralString, SQL::Identifier, SQL::QualifiedIdentifier, SQL::AliasedExpression, Dataset")
|
|
935
959
|
end
|
|
936
|
-
|
|
937
|
-
ds
|
|
960
|
+
|
|
961
|
+
set_dataset_row_proc(ds.clone(:model=>self))
|
|
938
962
|
end
|
|
939
963
|
|
|
940
964
|
# Add the module to the class's dataset_method_modules. Extend the dataset with the
|
|
941
965
|
# module if the model has a dataset. Add dataset methods to the class for all
|
|
942
966
|
# public dataset methods.
|
|
943
967
|
def dataset_extend(mod, opts=OPTS)
|
|
944
|
-
@dataset.
|
|
968
|
+
@dataset = @dataset.with_extend(mod) if @dataset
|
|
945
969
|
reset_instance_dataset
|
|
946
970
|
dataset_method_modules << mod
|
|
947
971
|
unless opts[:create_class_methods] == false
|
|
@@ -1204,7 +1228,7 @@ module Sequel
|
|
|
1204
1228
|
|
|
1205
1229
|
# Set the dataset's row_proc to the current model.
|
|
1206
1230
|
def set_dataset_row_proc(ds)
|
|
1207
|
-
ds.
|
|
1231
|
+
ds.with_row_proc(self)
|
|
1208
1232
|
end
|
|
1209
1233
|
|
|
1210
1234
|
# Reset the fast primary key lookup SQL when the simple_pk value changes.
|
|
@@ -1791,7 +1815,7 @@ module Sequel
|
|
|
1791
1815
|
# Set the shard that this object is tied to. Returns self.
|
|
1792
1816
|
def set_server(s)
|
|
1793
1817
|
@server = s
|
|
1794
|
-
@this
|
|
1818
|
+
@this = @this.server(s) if @this
|
|
1795
1819
|
self
|
|
1796
1820
|
end
|
|
1797
1821
|
|
|
@@ -2368,10 +2392,14 @@ module Sequel
|
|
|
2368
2392
|
# Dataset methods are methods that the model class extends its dataset with in
|
|
2369
2393
|
# the call to set_dataset.
|
|
2370
2394
|
module DatasetMethods
|
|
2395
|
+
Dataset.def_deprecated_opts_setter(self, :model)
|
|
2396
|
+
|
|
2371
2397
|
# The model class associated with this dataset
|
|
2372
2398
|
#
|
|
2373
2399
|
# Artist.dataset.model # => Artist
|
|
2374
|
-
|
|
2400
|
+
def model
|
|
2401
|
+
@opts[:model]
|
|
2402
|
+
end
|
|
2375
2403
|
|
|
2376
2404
|
# Assume if a single integer is given that it is a lookup by primary
|
|
2377
2405
|
# key, and call with_pk with the argument.
|
|
@@ -2449,8 +2477,8 @@ module Sequel
|
|
|
2449
2477
|
# Album.last
|
|
2450
2478
|
# # SELECT * FROM albums ORDER BY id DESC LIMIT 1
|
|
2451
2479
|
def last(*a, &block)
|
|
2452
|
-
if
|
|
2453
|
-
|
|
2480
|
+
if ds = _primary_key_order
|
|
2481
|
+
ds.last(*a, &block)
|
|
2454
2482
|
else
|
|
2455
2483
|
super
|
|
2456
2484
|
end
|
|
@@ -2465,8 +2493,8 @@ module Sequel
|
|
|
2465
2493
|
# # SELECT * FROM albums ORDER BY id LIMIT 1000 OFFSET 2000
|
|
2466
2494
|
# # ...
|
|
2467
2495
|
def paged_each(*a, &block)
|
|
2468
|
-
if
|
|
2469
|
-
|
|
2496
|
+
if ds = _primary_key_order
|
|
2497
|
+
ds.paged_each(*a, &block)
|
|
2470
2498
|
else
|
|
2471
2499
|
super
|
|
2472
2500
|
end
|
|
@@ -2500,7 +2528,11 @@ module Sequel
|
|
|
2500
2528
|
# Artist.dataset.with_pk([1, 2])
|
|
2501
2529
|
# # SELECT * FROM artists WHERE ((artists.id1 = 1) AND (artists.id2 = 2)) LIMIT 1
|
|
2502
2530
|
def with_pk(pk)
|
|
2503
|
-
|
|
2531
|
+
if loader = _with_pk_loader
|
|
2532
|
+
loader.first(*pk)
|
|
2533
|
+
else
|
|
2534
|
+
first(model.qualified_primary_key_hash(pk))
|
|
2535
|
+
end
|
|
2504
2536
|
end
|
|
2505
2537
|
|
|
2506
2538
|
# Same as with_pk, but raises NoMatchingRow instead of returning nil if no
|
|
@@ -2508,6 +2540,33 @@ module Sequel
|
|
|
2508
2540
|
def with_pk!(pk)
|
|
2509
2541
|
with_pk(pk) || raise(NoMatchingRow.new(self))
|
|
2510
2542
|
end
|
|
2543
|
+
|
|
2544
|
+
private
|
|
2545
|
+
|
|
2546
|
+
# If the dataset is not already ordered, and the model has a primary key,
|
|
2547
|
+
# return a clone ordered by the primary key.
|
|
2548
|
+
def _primary_key_order
|
|
2549
|
+
if @opts[:order].nil? && model && (pk = model.primary_key)
|
|
2550
|
+
cached_dataset(:_pk_order_ds){order(*pk)}
|
|
2551
|
+
end
|
|
2552
|
+
end
|
|
2553
|
+
|
|
2554
|
+
# A cached placeholder literalizer, if one exists for the current dataset.
|
|
2555
|
+
def _with_pk_loader
|
|
2556
|
+
cached_placeholder_literalizer(:_with_pk_loader) do |pl|
|
|
2557
|
+
table = model.table_name
|
|
2558
|
+
cond = case primary_key = model.primary_key
|
|
2559
|
+
when Array
|
|
2560
|
+
primary_key.map{|key| [SQL::QualifiedIdentifier.new(table, key), pl.arg]}
|
|
2561
|
+
when Symbol
|
|
2562
|
+
{SQL::QualifiedIdentifier.new(table, primary_key)=>pl.arg}
|
|
2563
|
+
else
|
|
2564
|
+
raise(Error, "#{model} does not have a primary key")
|
|
2565
|
+
end
|
|
2566
|
+
|
|
2567
|
+
where(cond).limit(1)
|
|
2568
|
+
end
|
|
2569
|
+
end
|
|
2511
2570
|
end
|
|
2512
2571
|
|
|
2513
2572
|
extend ClassMethods
|
|
@@ -20,6 +20,43 @@ module Sequel
|
|
|
20
20
|
@model.subset(name, *args, &block)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# Alias for subset
|
|
24
|
+
def where(name, *args, &block)
|
|
25
|
+
subset(name, *args, &block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
%w'exclude exclude_having having'.map(&:to_sym).each do |meth|
|
|
29
|
+
define_method(meth) do |name, *args, &block|
|
|
30
|
+
if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
|
|
31
|
+
@model.def_dataset_method(name){send(meth, *args, &block)}
|
|
32
|
+
else
|
|
33
|
+
key = :"_#{meth}_#{name}_ds"
|
|
34
|
+
@model.def_dataset_method(name) do
|
|
35
|
+
cached_dataset(key){send(meth, *args)}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
meths = (<<-METHS).split.map(&:to_sym)
|
|
42
|
+
distinct grep group group_and_count group_append
|
|
43
|
+
limit offset order order_append order_prepend
|
|
44
|
+
select select_all select_append select_group server
|
|
45
|
+
METHS
|
|
46
|
+
|
|
47
|
+
meths.each do |meth|
|
|
48
|
+
define_method(meth) do |name, *args, &block|
|
|
49
|
+
if block
|
|
50
|
+
@model.def_dataset_method(name){send(meth, *args, &block)}
|
|
51
|
+
else
|
|
52
|
+
key = :"_#{meth}_#{name}_ds"
|
|
53
|
+
@model.def_dataset_method(name) do
|
|
54
|
+
cached_dataset(key){send(meth, *args)}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
23
60
|
private
|
|
24
61
|
|
|
25
62
|
# Add a class method to the related model that
|