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
|
@@ -28,7 +28,9 @@ module Sequel
|
|
|
28
28
|
# Symbols, SQL::Identifiers, SQL::QualifiedIdentifiers, and
|
|
29
29
|
# SQL::AliasedExpressions.
|
|
30
30
|
def columns
|
|
31
|
-
|
|
31
|
+
if cols = _columns
|
|
32
|
+
return cols
|
|
33
|
+
end
|
|
32
34
|
if (pcs = probable_columns) && pcs.all?
|
|
33
35
|
self.columns = pcs
|
|
34
36
|
else
|
|
@@ -42,9 +42,9 @@ class Array
|
|
|
42
42
|
# this array as a value in a filter, but may be necessary if you are using it as a
|
|
43
43
|
# value with placeholder SQL:
|
|
44
44
|
#
|
|
45
|
-
# DB[:a].
|
|
46
|
-
# DB[:a].
|
|
47
|
-
# DB[:a].
|
|
45
|
+
# DB[:a].where([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
|
|
46
|
+
# DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
|
|
47
|
+
# DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
|
|
48
48
|
def sql_value_list
|
|
49
49
|
::Sequel::SQL::ValueList.new(self)
|
|
50
50
|
end
|
|
@@ -174,10 +174,10 @@ class String
|
|
|
174
174
|
# Converts a string into a <tt>Sequel::LiteralString</tt>, in order to override string
|
|
175
175
|
# literalization, e.g.:
|
|
176
176
|
#
|
|
177
|
-
# DB[:items].
|
|
177
|
+
# DB[:items].where(:abc => 'def').sql #=>
|
|
178
178
|
# "SELECT * FROM items WHERE (abc = 'def')"
|
|
179
179
|
#
|
|
180
|
-
# DB[:items].
|
|
180
|
+
# DB[:items].where(:abc => 'def'.lit).sql #=>
|
|
181
181
|
# "SELECT * FROM items WHERE (abc = def)"
|
|
182
182
|
#
|
|
183
183
|
# You can also provide arguments, to create a <tt>Sequel::SQL::PlaceholderLiteralString</tt>:
|
|
@@ -38,9 +38,9 @@ module Sequel::CoreRefinements
|
|
|
38
38
|
# this array as a value in a filter, but may be necessary if you are using it as a
|
|
39
39
|
# value with placeholder SQL:
|
|
40
40
|
#
|
|
41
|
-
# DB[:a].
|
|
42
|
-
# DB[:a].
|
|
43
|
-
# DB[:a].
|
|
41
|
+
# DB[:a].where([:a, :b]=>[[1, 2], [3, 4]]) # SQL: (a, b) IN ((1, 2), (3, 4))
|
|
42
|
+
# DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]]) # SQL: (a, b) IN ((1 = 2) AND (3 = 4))
|
|
43
|
+
# DB[:a].where('(a, b) IN ?', [[1, 2], [3, 4]].sql_value_list) # SQL: (a, b) IN ((1, 2), (3, 4))
|
|
44
44
|
def sql_value_list
|
|
45
45
|
::Sequel::SQL::ValueList.new(self)
|
|
46
46
|
end
|
|
@@ -167,10 +167,10 @@ module Sequel::CoreRefinements
|
|
|
167
167
|
# Converts a string into a <tt>Sequel::LiteralString</tt>, in order to override string
|
|
168
168
|
# literalization, e.g.:
|
|
169
169
|
#
|
|
170
|
-
# DB[:items].
|
|
170
|
+
# DB[:items].where(:abc => 'def').sql #=>
|
|
171
171
|
# "SELECT * FROM items WHERE (abc = 'def')"
|
|
172
172
|
#
|
|
173
|
-
# DB[:items].
|
|
173
|
+
# DB[:items].where(:abc => 'def'.lit).sql #=>
|
|
174
174
|
# "SELECT * FROM items WHERE (abc = def)"
|
|
175
175
|
#
|
|
176
176
|
# You can also provide arguments, to create a <tt>Sequel::SQL::PlaceholderLiteralString</tt>:
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
|
|
36
36
|
module Sequel
|
|
37
37
|
module DuplicateColumnsHandler
|
|
38
|
+
CALLER_ARGS = RUBY_VERSION >= '2.0' ? [0,1] : [0]
|
|
39
|
+
|
|
38
40
|
# Customize handling of duplicate columns for this dataset.
|
|
39
41
|
def on_duplicate_columns(handler = (raise Error, "Must provide either an argument or a block to on_duplicate_columns" unless block_given?; nil), &block)
|
|
40
42
|
raise Error, "Cannot provide both an argument and a block to on_duplicate_columns" if handler && block
|
|
@@ -47,14 +49,14 @@ module Sequel
|
|
|
47
49
|
if cols && cols.uniq.size != cols.size
|
|
48
50
|
handle_duplicate_columns(cols)
|
|
49
51
|
end
|
|
50
|
-
|
|
52
|
+
super
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
private
|
|
54
56
|
|
|
55
57
|
# Invoke the appropriate behavior when duplicate columns are present.
|
|
56
58
|
def handle_duplicate_columns(cols)
|
|
57
|
-
message = "One or more duplicate columns present in #{cols.inspect}"
|
|
59
|
+
message = "#{caller(*CALLER_ARGS).first}: One or more duplicate columns present in #{cols.inspect}"
|
|
58
60
|
|
|
59
61
|
case duplicate_columns_handler_type(cols)
|
|
60
62
|
when :raise
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The freeze_datasets extension freezes a databases's datasets by
|
|
4
|
+
# default, and makes it so the databases's datasets are always
|
|
5
|
+
# frozen. This makes sure you can never accidentally modify a
|
|
6
|
+
# dataset that may be used elsewhere (such as a model class's
|
|
7
|
+
# dataset or the same dataset being used in another thread).
|
|
8
|
+
# Frozen datasets can also perform caching for many
|
|
9
|
+
# different methods that can significantly improve performance.
|
|
10
|
+
#
|
|
11
|
+
# In addition to the caching provided by frozen datasets, this
|
|
12
|
+
# also adds caching of Database#from calls if the method is
|
|
13
|
+
# called with a single Symbol argument and not a block. In
|
|
14
|
+
# addition to speeding up Dataset#from itself, because it
|
|
15
|
+
# returns a cached dataset, all caching done by that dataset
|
|
16
|
+
# can also improve performance.
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
#
|
|
20
|
+
# DB.extension(:freeze_datasets)
|
|
21
|
+
#
|
|
22
|
+
# Related module: Sequel::FreezeDatasets
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
module Sequel
|
|
26
|
+
class Database
|
|
27
|
+
module FreezeDatasets
|
|
28
|
+
module DatasetMethods
|
|
29
|
+
# Make dup be an alias to clone, so that it
|
|
30
|
+
# returns a frozen dataset.
|
|
31
|
+
def dup
|
|
32
|
+
clone
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Reset the default dataset for this database after
|
|
37
|
+
# loading the extension.
|
|
38
|
+
def self.extended(db)
|
|
39
|
+
db.extend_datasets(DatasetMethods)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Cache returned dataset if given a single argument and no block.
|
|
43
|
+
def from(*args, &block)
|
|
44
|
+
if !block && args.length == 1 && (table = args[0]).is_a?(Symbol)
|
|
45
|
+
@default_dataset.send(:cached_dataset, :"_from_#{table}_ds"){super}
|
|
46
|
+
else
|
|
47
|
+
super
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Freeze datasets created from this dataset.
|
|
52
|
+
def dataset
|
|
53
|
+
super.freeze
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# Clear the cache of the default dataset when removing a cached
|
|
59
|
+
# schema, in order to clear the from table cache.
|
|
60
|
+
def remove_cached_schema(table)
|
|
61
|
+
cache = @default_dataset.send(:cache)
|
|
62
|
+
Sequel.synchronize{cache.clear}
|
|
63
|
+
super
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
register_extension(:freeze_datasets, FreezeDatasets)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The identifier_mangling extension adds support for to change
|
|
4
|
+
# the default identifier mangling for datasets, as well as all
|
|
5
|
+
# datasets for a given database.
|
|
6
|
+
#
|
|
7
|
+
# # Use uppercase identifiers in database, and lowercase in ruby.
|
|
8
|
+
# # Default behavior of Sequel, as the SQL standard behavior
|
|
9
|
+
# # folds unquoted identifiers to uppercase.
|
|
10
|
+
# DB.identifier_input_method = :upcase
|
|
11
|
+
# DB.identifier_output_method = :downcase
|
|
12
|
+
#
|
|
13
|
+
# # Don't modify identifiers.
|
|
14
|
+
# # Default behavior of Sequel on PostgreSQL, MySQL, SQLite,
|
|
15
|
+
# # as they fold unquoted identifiers to lowercase.
|
|
16
|
+
# DB.identifier_input_method = nil
|
|
17
|
+
# DB.identifier_output_method = nil
|
|
18
|
+
#
|
|
19
|
+
# You can also choose to turn on or off identifier quoting:
|
|
20
|
+
#
|
|
21
|
+
# # Quote identifiers. Sequel's default behavior.
|
|
22
|
+
# DB.quote_identifiers = true
|
|
23
|
+
#
|
|
24
|
+
# # Don't quote identifiers. Sequel's default behavior on DB2.
|
|
25
|
+
# DB.quote_identifiers = false
|
|
26
|
+
#
|
|
27
|
+
# To modify the identifiers on a per-dataset basis:
|
|
28
|
+
#
|
|
29
|
+
# ds = DB[:a].with_input_indentifier(:upcase).
|
|
30
|
+
# with_output_identifier(:downcase).
|
|
31
|
+
# with_quote_identifiers(true)
|
|
32
|
+
#
|
|
33
|
+
# To load the extension into the database:
|
|
34
|
+
#
|
|
35
|
+
# DB.extension :identifier_mangling
|
|
36
|
+
#
|
|
37
|
+
# Historically, Sequel supported these methods by default on
|
|
38
|
+
# Databases and Datasets. Sequel 4 will continue to support
|
|
39
|
+
# the methods for backwards compatibility, by loading this
|
|
40
|
+
# extension automatically for databases unless the
|
|
41
|
+
# <tt>:identifier_mangling=>false</tt> Database option is
|
|
42
|
+
# used.
|
|
43
|
+
#
|
|
44
|
+
# Related modules: Sequel::IdentifierMangling::DatabaseMethods,
|
|
45
|
+
# Sequel::IdentifierMangling::DatasetMethods
|
|
46
|
+
|
|
47
|
+
#
|
|
48
|
+
module Sequel
|
|
49
|
+
module IdentifierMangling
|
|
50
|
+
module DatabaseMethods
|
|
51
|
+
def self.extended(db)
|
|
52
|
+
db.instance_exec do
|
|
53
|
+
@identifier_input_method = nil
|
|
54
|
+
@identifier_output_method = nil
|
|
55
|
+
@quote_identifiers = nil
|
|
56
|
+
reset_identifier_mangling
|
|
57
|
+
extend_datasets(DatasetMethods)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# The identifier input method to use by default for this database (default: adapter default)
|
|
62
|
+
attr_reader :identifier_input_method
|
|
63
|
+
|
|
64
|
+
# The identifier output method to use by default for this database (default: adapter default)
|
|
65
|
+
attr_reader :identifier_output_method
|
|
66
|
+
|
|
67
|
+
# Set the method to call on identifiers going into the database:
|
|
68
|
+
#
|
|
69
|
+
# DB[:items] # SELECT * FROM items
|
|
70
|
+
# DB.identifier_input_method = :upcase
|
|
71
|
+
# DB[:items] # SELECT * FROM ITEMS
|
|
72
|
+
def identifier_input_method=(v)
|
|
73
|
+
reset_default_dataset
|
|
74
|
+
@identifier_input_method = v
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Set the method to call on identifiers coming from the database:
|
|
78
|
+
#
|
|
79
|
+
# DB[:items].first # {:id=>1, :name=>'foo'}
|
|
80
|
+
# DB.identifier_output_method = :upcase
|
|
81
|
+
# DB[:items].first # {:ID=>1, :NAME=>'foo'}
|
|
82
|
+
def identifier_output_method=(v)
|
|
83
|
+
reset_default_dataset
|
|
84
|
+
@identifier_output_method = v
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Set whether to quote identifiers (columns and tables) for this database:
|
|
88
|
+
#
|
|
89
|
+
# DB[:items] # SELECT * FROM items
|
|
90
|
+
# DB.quote_identifiers = true
|
|
91
|
+
# DB[:items] # SELECT * FROM "items"
|
|
92
|
+
def quote_identifiers=(v)
|
|
93
|
+
reset_default_dataset
|
|
94
|
+
@quote_identifiers = v
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Returns true if the database quotes identifiers.
|
|
98
|
+
def quote_identifiers?
|
|
99
|
+
@quote_identifiers
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
# Return a dataset that uses the default identifier input and output methods
|
|
105
|
+
# for this database. Used when parsing metadata so that column symbols are
|
|
106
|
+
# returned as expected.
|
|
107
|
+
def _metadata_dataset
|
|
108
|
+
super.
|
|
109
|
+
with_identifier_input_method(identifier_input_method_default).
|
|
110
|
+
with_identifier_output_method(identifier_output_method_default)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Upcase identifiers on input if database folds unquoted identifiers to
|
|
114
|
+
# uppercase.
|
|
115
|
+
def identifier_input_method_default
|
|
116
|
+
return super if defined?(super)
|
|
117
|
+
:upcase if folds_unquoted_identifiers_to_uppercase?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Downcase identifiers on output if database folds unquoted identifiers to
|
|
121
|
+
# uppercase.
|
|
122
|
+
def identifier_output_method_default
|
|
123
|
+
return super if defined?(super)
|
|
124
|
+
:downcase if folds_unquoted_identifiers_to_uppercase?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Reset the identifier mangling options. Overrides any already set on
|
|
128
|
+
# the instance. Only for internal use by shared adapters.
|
|
129
|
+
def reset_identifier_mangling
|
|
130
|
+
@quote_identifiers = @opts.fetch(:quote_identifiers){(qi = Database.quote_identifiers).nil? ? quote_identifiers_default : qi}
|
|
131
|
+
@identifier_input_method = @opts.fetch(:identifier_input_method){(iim = Database.identifier_input_method).nil? ? identifier_input_method_default : (iim if iim)}
|
|
132
|
+
@identifier_output_method = @opts.fetch(:identifier_output_method){(iom = Database.identifier_output_method).nil? ? identifier_output_method_default : (iom if iom)}
|
|
133
|
+
reset_default_dataset
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
module DatasetMethods
|
|
138
|
+
# The String instance method to call on identifiers before sending them to
|
|
139
|
+
# the database.
|
|
140
|
+
def identifier_input_method
|
|
141
|
+
@opts.fetch(:identifier_input_method, db.identifier_input_method)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Set the method to call on identifiers going into the database for this dataset
|
|
145
|
+
def identifier_input_method=(v)
|
|
146
|
+
raise_if_frozen!
|
|
147
|
+
skip_symbol_cache!
|
|
148
|
+
@opts[:identifier_input_method] = v
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# The String instance method to call on identifiers before sending them to
|
|
152
|
+
# the database.
|
|
153
|
+
def identifier_output_method
|
|
154
|
+
@opts.fetch(:identifier_output_method, db.identifier_output_method)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Set the method to call on identifiers coming the database for this dataset
|
|
158
|
+
def identifier_output_method=(v)
|
|
159
|
+
raise_if_frozen!
|
|
160
|
+
@opts[:identifier_output_method] = v
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Check with the database to see if identifier quoting is enabled
|
|
164
|
+
def quote_identifiers?
|
|
165
|
+
@opts.fetch(:quote_identifiers, db.quote_identifiers?)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Return a modified dataset with identifier_input_method set.
|
|
169
|
+
def with_identifier_input_method(meth)
|
|
170
|
+
clone(:identifier_input_method=>meth, :skip_symbol_cache=>true)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Return a modified dataset with identifier_output_method set.
|
|
174
|
+
def with_identifier_output_method(meth)
|
|
175
|
+
clone(:identifier_output_method=>meth)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
private
|
|
179
|
+
|
|
180
|
+
# Convert the identifier to the version used in the database via
|
|
181
|
+
# identifier_input_method.
|
|
182
|
+
def input_identifier(v)
|
|
183
|
+
(i = identifier_input_method) ? v.to_s.send(i) : v.to_s
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Modify the identifier returned from the database based on the
|
|
187
|
+
# identifier_output_method.
|
|
188
|
+
def output_identifier(v)
|
|
189
|
+
v = 'untitled' if v == ''
|
|
190
|
+
(i = identifier_output_method) ? v.to_s.send(i).to_sym : v.to_sym
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
Database.register_extension(:identifier_mangling, IdentifierMangling::DatabaseMethods)
|
|
196
|
+
end
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
#
|
|
6
6
|
# :float :: use to_f instead of Float()
|
|
7
7
|
# :integer :: use to_i instead of Integer()
|
|
8
|
-
# :decimal ::
|
|
8
|
+
# :decimal :: use 0.0 for unsupported strings
|
|
9
9
|
# :string :: silently allow hash and array conversion to string
|
|
10
10
|
#
|
|
11
11
|
# To load the extension into the database:
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
#
|
|
18
18
|
module Sequel
|
|
19
19
|
module LooserTypecasting
|
|
20
|
+
private
|
|
21
|
+
|
|
20
22
|
# Typecast the value to a Float using to_f instead of Kernel.Float
|
|
21
23
|
def typecast_value_float(value)
|
|
22
24
|
value.to_f
|
|
@@ -32,13 +34,15 @@ module Sequel
|
|
|
32
34
|
value.to_s
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if RUBY_VERSION >= '2.4'
|
|
38
|
+
def _typecast_value_string_to_decimal(value)
|
|
39
|
+
BigDecimal.new(value)
|
|
40
|
+
rescue
|
|
41
|
+
BigDecimal.new('0.0')
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
def _typecast_value_string_to_decimal(value)
|
|
39
45
|
BigDecimal.new(value)
|
|
40
|
-
else
|
|
41
|
-
super
|
|
42
46
|
end
|
|
43
47
|
end
|
|
44
48
|
end
|
|
@@ -687,7 +687,7 @@ module Sequel
|
|
|
687
687
|
checked_transaction(m) do
|
|
688
688
|
m.apply(db, direction)
|
|
689
689
|
fi = f.downcase
|
|
690
|
-
direction == :up ? ds.insert(column=>fi) : ds.
|
|
690
|
+
direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete
|
|
691
691
|
end
|
|
692
692
|
db.log_info("Finished applying migration #{f}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
|
|
693
693
|
end
|
|
@@ -41,7 +41,7 @@ module Sequel
|
|
|
41
41
|
module Nullifiable
|
|
42
42
|
# Return a cloned nullified dataset.
|
|
43
43
|
def nullify
|
|
44
|
-
clone.
|
|
44
|
+
clone.with_extend(NullDataset)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
# Nullify the current dataset
|
|
@@ -54,7 +54,10 @@ module Sequel
|
|
|
54
54
|
# Create a new dataset from the dataset (which won't
|
|
55
55
|
# be nulled) to get the columns if they aren't already cached.
|
|
56
56
|
def columns
|
|
57
|
-
|
|
57
|
+
if cols = _columns
|
|
58
|
+
return cols
|
|
59
|
+
end
|
|
60
|
+
self.columns = db.dataset.clone(@opts).columns
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
# Return 0 without sending a database query.
|
|
@@ -39,9 +39,14 @@ module Sequel
|
|
|
39
39
|
# number of records for this dataset.
|
|
40
40
|
def paginate(page_no, page_size, record_count=nil)
|
|
41
41
|
raise(Error, "You cannot paginate a dataset that already has a limit") if @opts[:limit]
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
|
|
43
|
+
record_count ||= count
|
|
44
|
+
page_count = (record_count / page_size.to_f).ceil
|
|
45
|
+
page_count = 1 if page_count == 0
|
|
46
|
+
|
|
47
|
+
limit(page_size, (page_no - 1) * page_size).
|
|
48
|
+
with_extend(Dataset::Pagination).
|
|
49
|
+
clone(:page_size=>page_size, :current_page=>page_no, :pagination_record_count=>record_count, :page_count=>page_count)
|
|
45
50
|
end
|
|
46
51
|
|
|
47
52
|
# Yields a paginated dataset for each page and returns the receiver. Does
|
|
@@ -61,49 +66,59 @@ module Sequel
|
|
|
61
66
|
# Holds methods that only relate to paginated datasets. Paginated dataset
|
|
62
67
|
# have pages starting at 1 (page 1 is offset 0, page 1 is offset page_size).
|
|
63
68
|
module Pagination
|
|
69
|
+
Sequel::Dataset.def_deprecated_opts_setter(self, :page_size, :page_count, :current_page, :pagination_record_count)
|
|
70
|
+
|
|
64
71
|
# The number of records per page (the final page may have fewer than
|
|
65
72
|
# this number of records).
|
|
66
|
-
|
|
73
|
+
def page_size
|
|
74
|
+
@opts[:page_size]
|
|
75
|
+
end
|
|
67
76
|
|
|
68
77
|
# The number of pages in the dataset before pagination, of which
|
|
69
78
|
# this paginated dataset is one. Empty datasets are considered
|
|
70
79
|
# to have a single page.
|
|
71
|
-
|
|
80
|
+
def page_count
|
|
81
|
+
@opts[:page_count]
|
|
82
|
+
end
|
|
72
83
|
|
|
73
84
|
# The current page of the dataset, starting at 1 and not 0.
|
|
74
|
-
|
|
85
|
+
def current_page
|
|
86
|
+
@opts[:current_page]
|
|
87
|
+
end
|
|
75
88
|
|
|
76
89
|
# The total number of records in the dataset before pagination.
|
|
77
|
-
|
|
90
|
+
def pagination_record_count
|
|
91
|
+
@opts[:pagination_record_count]
|
|
92
|
+
end
|
|
78
93
|
|
|
79
94
|
# Returns the record range for the current page
|
|
80
95
|
def current_page_record_range
|
|
81
|
-
return (0..0) if
|
|
96
|
+
return (0..0) if current_page > page_count
|
|
82
97
|
|
|
83
|
-
a = 1 + (
|
|
84
|
-
b = a +
|
|
85
|
-
b =
|
|
98
|
+
a = 1 + (current_page - 1) * page_size
|
|
99
|
+
b = a + page_size - 1
|
|
100
|
+
b = pagination_record_count if b > pagination_record_count
|
|
86
101
|
a..b
|
|
87
102
|
end
|
|
88
103
|
|
|
89
104
|
# Returns the number of records in the current page
|
|
90
105
|
def current_page_record_count
|
|
91
|
-
return 0 if
|
|
106
|
+
return 0 if current_page > page_count
|
|
92
107
|
|
|
93
|
-
a = 1 + (
|
|
94
|
-
b = a +
|
|
95
|
-
b =
|
|
108
|
+
a = 1 + (current_page - 1) * page_size
|
|
109
|
+
b = a + page_size - 1
|
|
110
|
+
b = pagination_record_count if b > pagination_record_count
|
|
96
111
|
b - a + 1
|
|
97
112
|
end
|
|
98
113
|
|
|
99
114
|
# Returns true if the current page is the first page
|
|
100
115
|
def first_page?
|
|
101
|
-
|
|
116
|
+
current_page == 1
|
|
102
117
|
end
|
|
103
118
|
|
|
104
119
|
# Returns true if the current page is the last page
|
|
105
120
|
def last_page?
|
|
106
|
-
|
|
121
|
+
current_page == page_count
|
|
107
122
|
end
|
|
108
123
|
|
|
109
124
|
# Returns the next page number or nil if the current page is the last page
|
|
@@ -121,15 +136,19 @@ module Sequel
|
|
|
121
136
|
current_page > 1 ? (current_page - 1) : nil
|
|
122
137
|
end
|
|
123
138
|
|
|
124
|
-
#
|
|
139
|
+
# SEQUEL5: Remove
|
|
140
|
+
# :nocov:
|
|
125
141
|
def set_pagination_info(page_no, page_size, record_count)
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
142
|
+
Sequel::Deprecation.deprecate("Dataset#set_pagination_info", "It should no longer be necessary to call this method.")
|
|
143
|
+
self.current_page = page_no
|
|
144
|
+
self.page_size = page_size
|
|
145
|
+
self.pagination_record_count = record_count
|
|
146
|
+
page_count = (record_count / page_size.to_f).ceil
|
|
147
|
+
page_count = 1 if page_count == 0
|
|
148
|
+
self.page_count = page_count
|
|
131
149
|
self
|
|
132
150
|
end
|
|
151
|
+
# :nocov:
|
|
133
152
|
end
|
|
134
153
|
end
|
|
135
154
|
|