sequel 4.41.0 → 4.42.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|