sequel 5.83.0 → 5.106.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/MIT-LICENSE +1 -1
- data/lib/sequel/adapters/ado/access.rb +2 -2
- data/lib/sequel/adapters/ado.rb +2 -2
- data/lib/sequel/adapters/amalgalite.rb +16 -1
- data/lib/sequel/adapters/ibmdb.rb +2 -1
- data/lib/sequel/adapters/jdbc/db2.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +4 -2
- data/lib/sequel/adapters/jdbc/h2.rb +4 -4
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -2
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -3
- data/lib/sequel/adapters/jdbc/oracle.rb +6 -6
- data/lib/sequel/adapters/jdbc/postgresql.rb +5 -5
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +6 -6
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -3
- data/lib/sequel/adapters/jdbc.rb +29 -15
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +10 -3
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +16 -0
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/access.rb +1 -0
- data/lib/sequel/adapters/shared/db2.rb +8 -3
- data/lib/sequel/adapters/shared/mssql.rb +9 -8
- data/lib/sequel/adapters/shared/mysql.rb +16 -11
- data/lib/sequel/adapters/shared/oracle.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +438 -47
- data/lib/sequel/adapters/shared/sqlite.rb +9 -7
- data/lib/sequel/adapters/sqlite.rb +20 -2
- data/lib/sequel/adapters/tinytds.rb +2 -2
- data/lib/sequel/adapters/trilogy.rb +2 -3
- data/lib/sequel/ast_transformer.rb +2 -0
- data/lib/sequel/connection_pool/sharded_timed_queue.rb +42 -11
- data/lib/sequel/connection_pool/timed_queue.rb +33 -10
- data/lib/sequel/connection_pool.rb +8 -2
- data/lib/sequel/core.rb +31 -2
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +3 -3
- data/lib/sequel/database/misc.rb +29 -11
- data/lib/sequel/database/query.rb +12 -12
- data/lib/sequel/database/schema_generator.rb +117 -16
- data/lib/sequel/database/schema_methods.rb +85 -30
- data/lib/sequel/dataset/actions.rb +83 -11
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +1 -1
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -0
- data/lib/sequel/dataset/prepared_statements.rb +76 -28
- data/lib/sequel/dataset/query.rb +26 -11
- data/lib/sequel/dataset/sql.rb +40 -17
- data/lib/sequel/extensions/async_thread_pool.rb +1 -1
- data/lib/sequel/extensions/caller_logging.rb +1 -3
- data/lib/sequel/extensions/connection_checkout_event_callback.rb +151 -0
- data/lib/sequel/extensions/connection_expiration.rb +44 -5
- data/lib/sequel/extensions/connection_validator.rb +15 -10
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/dataset_run.rb +41 -0
- data/lib/sequel/extensions/date_arithmetic.rb +6 -6
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -0
- data/lib/sequel/extensions/eval_inspect.rb +3 -1
- data/lib/sequel/extensions/inflector.rb +2 -2
- data/lib/sequel/extensions/lit_require_frozen.rb +131 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -12
- data/lib/sequel/extensions/migration.rb +38 -21
- data/lib/sequel/extensions/null_dataset.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +41 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +10 -3
- data/lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb +191 -0
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +94 -10
- data/lib/sequel/extensions/pg_enum.rb +4 -4
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +10 -5
- data/lib/sequel/extensions/pg_json_ops.rb +674 -18
- data/lib/sequel/extensions/pg_multirange.rb +1 -1
- data/lib/sequel/extensions/pg_range.rb +14 -2
- data/lib/sequel/extensions/pg_row.rb +5 -3
- data/lib/sequel/extensions/pg_schema_caching.rb +90 -0
- data/lib/sequel/extensions/provenance.rb +1 -3
- data/lib/sequel/extensions/query_blocker.rb +172 -0
- data/lib/sequel/extensions/schema_caching.rb +24 -9
- data/lib/sequel/extensions/schema_dumper.rb +17 -5
- data/lib/sequel/extensions/set_literalizer.rb +20 -39
- data/lib/sequel/extensions/split_array_nil.rb +12 -2
- data/lib/sequel/extensions/sqlite_json_ops.rb +1 -1
- data/lib/sequel/extensions/string_agg.rb +2 -2
- data/lib/sequel/extensions/to_dot.rb +5 -0
- data/lib/sequel/extensions/virtual_row_method_block.rb +1 -0
- data/lib/sequel/model/associations.rb +215 -15
- data/lib/sequel/model/base.rb +198 -35
- data/lib/sequel/model/plugins.rb +12 -1
- data/lib/sequel/model.rb +1 -0
- data/lib/sequel/plugins/accessed_columns.rb +4 -0
- data/lib/sequel/plugins/active_model.rb +5 -6
- data/lib/sequel/plugins/association_pks.rb +2 -0
- data/lib/sequel/plugins/auto_validations.rb +2 -0
- data/lib/sequel/plugins/class_table_inheritance_constraint_validations.rb +82 -0
- data/lib/sequel/plugins/columns_updated.rb +4 -0
- data/lib/sequel/plugins/composition.rb +3 -1
- data/lib/sequel/plugins/constraint_validations.rb +15 -10
- data/lib/sequel/plugins/dataset_associations.rb +20 -1
- data/lib/sequel/plugins/deprecated_associations.rb +151 -0
- data/lib/sequel/plugins/detect_unnecessary_association_options.rb +164 -0
- data/lib/sequel/plugins/dirty.rb +9 -2
- data/lib/sequel/plugins/enum.rb +1 -1
- data/lib/sequel/plugins/forbid_lazy_load.rb +15 -1
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/insert_returning_select.rb +10 -1
- data/lib/sequel/plugins/inspect_pk.rb +44 -0
- data/lib/sequel/plugins/instance_filters.rb +8 -1
- data/lib/sequel/plugins/instance_hooks.rb +4 -0
- data/lib/sequel/plugins/inverted_subsets.rb +1 -0
- data/lib/sequel/plugins/json_serializer.rb +6 -10
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +21 -0
- data/lib/sequel/plugins/modification_detection.rb +2 -0
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +10 -5
- data/lib/sequel/plugins/paged_operations.rb +5 -2
- data/lib/sequel/plugins/pg_array_associations.rb +2 -2
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +6 -1
- data/lib/sequel/plugins/pg_auto_validate_enums.rb +88 -0
- data/lib/sequel/plugins/pg_eager_any_typed_array.rb +95 -0
- data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +6 -6
- data/lib/sequel/plugins/serialization.rb +23 -6
- data/lib/sequel/plugins/serialization_modification_detection.rb +4 -0
- data/lib/sequel/plugins/single_statement_dataset_destroy.rb +49 -0
- data/lib/sequel/plugins/split_values.rb +12 -0
- data/lib/sequel/plugins/sql_comments.rb +7 -2
- data/lib/sequel/plugins/static_cache.rb +13 -0
- data/lib/sequel/plugins/static_cache_cache.rb +50 -13
- data/lib/sequel/plugins/subset_conditions.rb +85 -5
- data/lib/sequel/plugins/subset_static_cache.rb +278 -0
- data/lib/sequel/plugins/table_select.rb +7 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +4 -0
- data/lib/sequel/plugins/unused_associations.rb +11 -3
- data/lib/sequel/plugins/update_primary_key.rb +4 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_contexts.rb +4 -0
- data/lib/sequel/sql.rb +27 -12
- data/lib/sequel/version.rb +1 -1
- metadata +17 -240
- data/CHANGELOG +0 -1393
- data/README.rdoc +0 -936
- data/doc/advanced_associations.rdoc +0 -884
- data/doc/association_basics.rdoc +0 -1859
- data/doc/bin_sequel.rdoc +0 -146
- data/doc/cheat_sheet.rdoc +0 -255
- data/doc/code_order.rdoc +0 -104
- data/doc/core_extensions.rdoc +0 -405
- data/doc/dataset_basics.rdoc +0 -96
- data/doc/dataset_filtering.rdoc +0 -222
- data/doc/extensions.rdoc +0 -77
- data/doc/fork_safety.rdoc +0 -84
- data/doc/mass_assignment.rdoc +0 -98
- data/doc/migration.rdoc +0 -660
- data/doc/model_dataset_method_design.rdoc +0 -129
- data/doc/model_hooks.rdoc +0 -254
- data/doc/model_plugins.rdoc +0 -270
- data/doc/mssql_stored_procedures.rdoc +0 -43
- data/doc/object_model.rdoc +0 -563
- data/doc/opening_databases.rdoc +0 -439
- data/doc/postgresql.rdoc +0 -611
- data/doc/prepared_statements.rdoc +0 -144
- data/doc/querying.rdoc +0 -1070
- data/doc/reflection.rdoc +0 -120
- data/doc/release_notes/5.0.0.txt +0 -159
- data/doc/release_notes/5.1.0.txt +0 -31
- data/doc/release_notes/5.10.0.txt +0 -84
- data/doc/release_notes/5.11.0.txt +0 -83
- data/doc/release_notes/5.12.0.txt +0 -141
- data/doc/release_notes/5.13.0.txt +0 -27
- data/doc/release_notes/5.14.0.txt +0 -63
- data/doc/release_notes/5.15.0.txt +0 -39
- data/doc/release_notes/5.16.0.txt +0 -110
- data/doc/release_notes/5.17.0.txt +0 -31
- data/doc/release_notes/5.18.0.txt +0 -69
- data/doc/release_notes/5.19.0.txt +0 -28
- data/doc/release_notes/5.2.0.txt +0 -33
- data/doc/release_notes/5.20.0.txt +0 -89
- data/doc/release_notes/5.21.0.txt +0 -87
- data/doc/release_notes/5.22.0.txt +0 -48
- data/doc/release_notes/5.23.0.txt +0 -56
- data/doc/release_notes/5.24.0.txt +0 -56
- data/doc/release_notes/5.25.0.txt +0 -32
- data/doc/release_notes/5.26.0.txt +0 -35
- data/doc/release_notes/5.27.0.txt +0 -21
- data/doc/release_notes/5.28.0.txt +0 -16
- data/doc/release_notes/5.29.0.txt +0 -22
- data/doc/release_notes/5.3.0.txt +0 -121
- data/doc/release_notes/5.30.0.txt +0 -20
- data/doc/release_notes/5.31.0.txt +0 -148
- data/doc/release_notes/5.32.0.txt +0 -46
- data/doc/release_notes/5.33.0.txt +0 -24
- data/doc/release_notes/5.34.0.txt +0 -40
- data/doc/release_notes/5.35.0.txt +0 -56
- data/doc/release_notes/5.36.0.txt +0 -60
- data/doc/release_notes/5.37.0.txt +0 -30
- data/doc/release_notes/5.38.0.txt +0 -28
- data/doc/release_notes/5.39.0.txt +0 -19
- data/doc/release_notes/5.4.0.txt +0 -80
- data/doc/release_notes/5.40.0.txt +0 -40
- data/doc/release_notes/5.41.0.txt +0 -25
- data/doc/release_notes/5.42.0.txt +0 -136
- data/doc/release_notes/5.43.0.txt +0 -98
- data/doc/release_notes/5.44.0.txt +0 -32
- data/doc/release_notes/5.45.0.txt +0 -34
- data/doc/release_notes/5.46.0.txt +0 -87
- data/doc/release_notes/5.47.0.txt +0 -59
- data/doc/release_notes/5.48.0.txt +0 -14
- data/doc/release_notes/5.49.0.txt +0 -59
- data/doc/release_notes/5.5.0.txt +0 -61
- data/doc/release_notes/5.50.0.txt +0 -78
- data/doc/release_notes/5.51.0.txt +0 -47
- data/doc/release_notes/5.52.0.txt +0 -87
- data/doc/release_notes/5.53.0.txt +0 -23
- data/doc/release_notes/5.54.0.txt +0 -27
- data/doc/release_notes/5.55.0.txt +0 -21
- data/doc/release_notes/5.56.0.txt +0 -51
- data/doc/release_notes/5.57.0.txt +0 -23
- data/doc/release_notes/5.58.0.txt +0 -31
- data/doc/release_notes/5.59.0.txt +0 -73
- data/doc/release_notes/5.6.0.txt +0 -31
- data/doc/release_notes/5.60.0.txt +0 -22
- data/doc/release_notes/5.61.0.txt +0 -43
- data/doc/release_notes/5.62.0.txt +0 -132
- data/doc/release_notes/5.63.0.txt +0 -33
- data/doc/release_notes/5.64.0.txt +0 -50
- data/doc/release_notes/5.65.0.txt +0 -21
- data/doc/release_notes/5.66.0.txt +0 -24
- data/doc/release_notes/5.67.0.txt +0 -32
- data/doc/release_notes/5.68.0.txt +0 -61
- data/doc/release_notes/5.69.0.txt +0 -26
- data/doc/release_notes/5.7.0.txt +0 -108
- data/doc/release_notes/5.70.0.txt +0 -35
- data/doc/release_notes/5.71.0.txt +0 -21
- data/doc/release_notes/5.72.0.txt +0 -33
- data/doc/release_notes/5.73.0.txt +0 -66
- data/doc/release_notes/5.74.0.txt +0 -45
- data/doc/release_notes/5.75.0.txt +0 -35
- data/doc/release_notes/5.76.0.txt +0 -86
- data/doc/release_notes/5.77.0.txt +0 -63
- data/doc/release_notes/5.78.0.txt +0 -67
- data/doc/release_notes/5.79.0.txt +0 -28
- data/doc/release_notes/5.8.0.txt +0 -170
- data/doc/release_notes/5.80.0.txt +0 -40
- data/doc/release_notes/5.81.0.txt +0 -31
- data/doc/release_notes/5.82.0.txt +0 -61
- data/doc/release_notes/5.83.0.txt +0 -56
- data/doc/release_notes/5.9.0.txt +0 -99
- data/doc/schema_modification.rdoc +0 -679
- data/doc/security.rdoc +0 -443
- data/doc/sharding.rdoc +0 -286
- data/doc/sql.rdoc +0 -648
- data/doc/testing.rdoc +0 -204
- data/doc/thread_safety.rdoc +0 -15
- data/doc/transactions.rdoc +0 -250
- data/doc/validations.rdoc +0 -558
- data/doc/virtual_rows.rdoc +0 -265
|
@@ -170,7 +170,7 @@ module Sequel
|
|
|
170
170
|
c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type]) unless c.has_key?(:ruby_default)
|
|
171
171
|
if c[:primary_key] && !auto_increment_set
|
|
172
172
|
# If adapter didn't set it, assume that integer primary keys are auto incrementing
|
|
173
|
-
c[:auto_increment] = primary_keys == 1 && !!(c[:db_type] =~ /int/
|
|
173
|
+
c[:auto_increment] = primary_keys == 1 && !!(c[:db_type] =~ /int/i)
|
|
174
174
|
end
|
|
175
175
|
if !c[:max_length] && c[:type] == :string && (max_length = column_schema_max_length(c[:db_type]))
|
|
176
176
|
c[:max_length] = max_length
|
|
@@ -269,7 +269,7 @@ module Sequel
|
|
|
269
269
|
def column_schema_to_ruby_default(default, type)
|
|
270
270
|
return default unless default.is_a?(String)
|
|
271
271
|
if COLUMN_SCHEMA_DATETIME_TYPES.include?(type)
|
|
272
|
-
if /now|today|CURRENT|getdate|\ADate\(\)\z/i
|
|
272
|
+
if /now|today|CURRENT|getdate|\ADate\(\)\z/i =~ default
|
|
273
273
|
if type == :date
|
|
274
274
|
return Sequel::CURRENT_DATE
|
|
275
275
|
else
|
|
@@ -390,25 +390,25 @@ module Sequel
|
|
|
390
390
|
# such as :integer or :string.
|
|
391
391
|
def schema_column_type(db_type)
|
|
392
392
|
case db_type
|
|
393
|
-
when /\A(character( varying)?|n?(var)?char|n?text|string|clob)/
|
|
393
|
+
when /\A(character( varying)?|n?(var)?char|n?text|string|clob)/i
|
|
394
394
|
:string
|
|
395
|
-
when /\A(int(eger)?|(big|small|tiny)int)/
|
|
395
|
+
when /\A(int(eger)?|(big|small|tiny)int)/i
|
|
396
396
|
:integer
|
|
397
|
-
when /\Adate\z/
|
|
397
|
+
when /\Adate\z/i
|
|
398
398
|
:date
|
|
399
|
-
when /\A((small)?datetime
|
|
399
|
+
when /\A((small)?datetime(\(\d\))?|timestamp(\(\d\))?( with(out)? time zone)?)\z/i
|
|
400
400
|
:datetime
|
|
401
|
-
when /\Atime( with(out)? time zone)?\z/
|
|
401
|
+
when /\Atime( with(out)? time zone)?\z/i
|
|
402
402
|
:time
|
|
403
|
-
when /\A(bool(ean)?)\z/
|
|
403
|
+
when /\A(bool(ean)?)\z/i
|
|
404
404
|
:boolean
|
|
405
|
-
when /\A(real|float( unsigned)?|double( precision)?|double\(\d+,\d+\)( unsigned)?)\z/
|
|
405
|
+
when /\A(real|float( unsigned)?|double( precision)?|double\(\d+,\d+\)( unsigned)?)\z/i
|
|
406
406
|
:float
|
|
407
|
-
when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(-?\d+|false|true)\))?))\z/
|
|
407
|
+
when /\A(?:(?:(?:num(?:ber|eric)?|decimal)(?:\(\d+,\s*(-?\d+|false|true)\))?))\z/i
|
|
408
408
|
$1 && ['0', 'false'].include?($1) ? :integer : :decimal
|
|
409
|
-
when /bytea|blob|image|(var)?binary/
|
|
409
|
+
when /bytea|blob|image|(var)?binary/i
|
|
410
410
|
:blob
|
|
411
|
-
when /\Aenum/
|
|
411
|
+
when /\Aenum/i
|
|
412
412
|
:enum
|
|
413
413
|
end
|
|
414
414
|
end
|
|
@@ -3,6 +3,33 @@
|
|
|
3
3
|
module Sequel
|
|
4
4
|
# The Schema module holds the schema generators.
|
|
5
5
|
module Schema
|
|
6
|
+
module ColumnOptionMerger
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# Merge given options into the column's default options. For backwards compatibility,
|
|
10
|
+
# the options take priority, but in cases where the option value overrides the argument
|
|
11
|
+
# value, and the values are different, we warn as this is likely to be an error in the
|
|
12
|
+
# code.
|
|
13
|
+
def _merge_column_options(defaults, opts)
|
|
14
|
+
defaults.merge!(opts) do |k, defv, v|
|
|
15
|
+
unless defv == v
|
|
16
|
+
# :nocov:
|
|
17
|
+
if RUBY_VERSION >= "3.2"
|
|
18
|
+
# :nocov:
|
|
19
|
+
caller_loc = Thread.each_caller_location do |loc|
|
|
20
|
+
break loc unless loc.path == __FILE__
|
|
21
|
+
end
|
|
22
|
+
caller_loc &&= "#{caller_loc.path}:#{caller_loc.lineno}: "
|
|
23
|
+
end
|
|
24
|
+
warn("#{caller_loc}#{k.inspect} option value (#{v.inspect}) overrides argument value (#{defv.inspect})")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
v
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
private_constant :ColumnOptionMerger
|
|
32
|
+
|
|
6
33
|
# Schema::CreateTableGenerator is an internal class that the user is not expected
|
|
7
34
|
# to instantiate directly. Instances are created by Database#create_table.
|
|
8
35
|
# It is used to specify table creation parameters. It takes a Database
|
|
@@ -17,6 +44,8 @@ module Sequel
|
|
|
17
44
|
# For more information on Sequel's support for schema modification, see
|
|
18
45
|
# the {"Schema Modification" guide}[rdoc-ref:doc/schema_modification.rdoc].
|
|
19
46
|
class CreateTableGenerator
|
|
47
|
+
include ColumnOptionMerger
|
|
48
|
+
|
|
20
49
|
# Classes specifying generic types that Sequel will convert to database-specific types.
|
|
21
50
|
GENERIC_TYPES=%w'String Integer Float Numeric BigDecimal Date DateTime Time File TrueClass FalseClass'.freeze
|
|
22
51
|
|
|
@@ -118,6 +147,11 @@ module Sequel
|
|
|
118
147
|
# that this column references. Unnecessary if this column
|
|
119
148
|
# references the primary key of the associated table, except if you are
|
|
120
149
|
# using MySQL.
|
|
150
|
+
# :not_null :: Similar to setting <tt>null: false</tt>, but you can provide a hash value
|
|
151
|
+
# to specify options for the NOT NULL constraint on PostgreSQL 18+:
|
|
152
|
+
# :name :: The name of the NOT NULL constraint
|
|
153
|
+
# :no_inherit :: Set NO INHERIT on the constraint, so it will not propogate to
|
|
154
|
+
# child tables.
|
|
121
155
|
# :null :: Mark the column as allowing NULL values (if true),
|
|
122
156
|
# or not allowing NULL values (if false). The default is to allow NULL values.
|
|
123
157
|
# :on_delete :: Specify the behavior of this column when being deleted
|
|
@@ -126,21 +160,34 @@ module Sequel
|
|
|
126
160
|
# (:restrict, :cascade, :set_null, :set_default, :no_action).
|
|
127
161
|
# :primary_key :: Make the column as a single primary key column. This should not
|
|
128
162
|
# be used if you want a single autoincrementing primary key column
|
|
129
|
-
# (use the primary_key method in that case).
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
163
|
+
# (use the primary_key method in that case). Can be a hash to provide
|
|
164
|
+
# options for the constraint:
|
|
165
|
+
# :name :: The name to give the primary key constraint.
|
|
166
|
+
# :deferrable :: Sets whether the primary key constraint is deferrable.
|
|
167
|
+
# :include :: Include additional columns in the underlying index, to
|
|
168
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
169
|
+
# :primary_key_constraint_name :: Older option to name primary key constraint.
|
|
170
|
+
# :primary_key_deferrable :: Older option to set primary key constraint as deferrable.
|
|
133
171
|
# :type :: Overrides the type given as the argument. Generally not used by column
|
|
134
172
|
# itself, but can be passed as an option to other methods that call column.
|
|
135
173
|
# :unique :: Mark the column as unique, generally has the same effect as
|
|
136
|
-
# creating a unique index on the column.
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
#
|
|
174
|
+
# creating a unique index on the column. Can be a hash to provide options for
|
|
175
|
+
# the constraint:
|
|
176
|
+
# :name :: The name to give the unique constraint.
|
|
177
|
+
# :deferrable :: Sets whether the unique constraint is deferrable.
|
|
178
|
+
# :include :: Include additional columns in the underlying index, to
|
|
179
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
180
|
+
# :nulls_not_distinct :: Use NULLS NOT DISTINCT to setup a constraint where NULL
|
|
181
|
+
# entries are considered distinct (PostgreSQL 15+)
|
|
182
|
+
# :unique_constraint_name :: Older option to name unique constraint.
|
|
183
|
+
# :unique_deferrable :: Older option to set unique constraint as deferrable.
|
|
140
184
|
#
|
|
141
185
|
# PostgreSQL specific options:
|
|
142
186
|
#
|
|
143
187
|
# :identity :: Create an identity column.
|
|
188
|
+
# :virtual :: When using :generated_always_as, create a VIRTUAL column instead of a STORED
|
|
189
|
+
# column (PostgreSQL 18+). VIRTUAL is the default if not specified on
|
|
190
|
+
# PostgreSQL 18+, but for backwards compatibility, Sequel's default is STORED.
|
|
144
191
|
#
|
|
145
192
|
# MySQL specific options:
|
|
146
193
|
#
|
|
@@ -155,13 +202,13 @@ module Sequel
|
|
|
155
202
|
# :clustered :: When using :primary_key or :unique, marks the primary key or unique
|
|
156
203
|
# constraint as CLUSTERED (if true), or NONCLUSTERED (if false).
|
|
157
204
|
def column(name, type, opts = OPTS)
|
|
158
|
-
columns << {:name => name, :type => type}
|
|
205
|
+
columns << _merge_column_options({:name => name, :type => type}, opts)
|
|
159
206
|
if index_opts = opts[:index]
|
|
160
207
|
index(name, index_opts.is_a?(Hash) ? index_opts : OPTS)
|
|
161
208
|
end
|
|
162
209
|
nil
|
|
163
210
|
end
|
|
164
|
-
|
|
211
|
+
|
|
165
212
|
# Adds a named CHECK constraint (or unnamed if name is nil),
|
|
166
213
|
# with the given block or args. To provide options for the constraint, pass
|
|
167
214
|
# a hash as the first argument.
|
|
@@ -178,6 +225,9 @@ module Sequel
|
|
|
178
225
|
# :deferrable :: Whether the CHECK constraint should be marked DEFERRABLE.
|
|
179
226
|
#
|
|
180
227
|
# PostgreSQL specific options:
|
|
228
|
+
# :no_inherit :: Set NO INHERIT on the constraint, so it will not propogate to
|
|
229
|
+
# child tables.
|
|
230
|
+
# :not_enforced :: Whether the CHECK constraint should be marked NOT ENFORCED.
|
|
181
231
|
# :not_valid :: Whether the CHECK constraint should be marked NOT VALID.
|
|
182
232
|
def constraint(name, *args, &block)
|
|
183
233
|
opts = name.is_a?(Hash) ? name : {:name=>name}
|
|
@@ -197,9 +247,21 @@ module Sequel
|
|
|
197
247
|
#
|
|
198
248
|
# :foreign_key_constraint_name :: The name to give the foreign key constraint
|
|
199
249
|
#
|
|
250
|
+
# PostgreSQL specific options:
|
|
251
|
+
#
|
|
252
|
+
# :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
|
|
253
|
+
#
|
|
200
254
|
# If you want a foreign key constraint without adding a column (usually because it is a
|
|
201
|
-
# composite foreign key), you can provide an array of columns as the first argument
|
|
202
|
-
#
|
|
255
|
+
# composite foreign key), you can provide an array of columns as the first argument.
|
|
256
|
+
# This changes the method to accept constraint options instead of column options.
|
|
257
|
+
# You can provide the :name option to name the constraint.
|
|
258
|
+
#
|
|
259
|
+
# PostgreSQL specific options:
|
|
260
|
+
#
|
|
261
|
+
# :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
|
|
262
|
+
# :period :: Use PERIOD to setup a constraint where the final column is a range
|
|
263
|
+
# or multirange column, and the range or multirange is covered by
|
|
264
|
+
# existing ranges in the referenced table (which can be in separate rows).
|
|
203
265
|
#
|
|
204
266
|
# foreign_key([:artist_name, :artist_location], :artists, name: :artist_fk)
|
|
205
267
|
# # ADD CONSTRAINT artist_fk FOREIGN KEY (artist_name, artist_location) REFERENCES artists
|
|
@@ -213,7 +275,7 @@ module Sequel
|
|
|
213
275
|
opts.merge(:table=>table)
|
|
214
276
|
end
|
|
215
277
|
return composite_foreign_key(name, opts) if name.is_a?(Array)
|
|
216
|
-
column(name, Integer, opts)
|
|
278
|
+
column(name, opts.fetch(:type, Integer), opts)
|
|
217
279
|
end
|
|
218
280
|
|
|
219
281
|
# Add a full text index on the given columns.
|
|
@@ -266,6 +328,7 @@ module Sequel
|
|
|
266
328
|
# :opclass :: Set an opclass to use for all columns (per-column opclasses require
|
|
267
329
|
# custom SQL).
|
|
268
330
|
# :tablespace :: Specify tablespace for index.
|
|
331
|
+
# :only :: Create index only for given table, not for any child tables (PostgreSQL 11+)
|
|
269
332
|
#
|
|
270
333
|
# Microsoft SQL Server specific options:
|
|
271
334
|
#
|
|
@@ -303,6 +366,13 @@ module Sequel
|
|
|
303
366
|
# :keep_order :: For non-composite primary keys, respects the existing order of
|
|
304
367
|
# columns, overriding the default behavior of making the primary
|
|
305
368
|
# key the first column.
|
|
369
|
+
#
|
|
370
|
+
# PostgreSQL specific options:
|
|
371
|
+
#
|
|
372
|
+
# :include :: Include additional columns in the underlying index, to
|
|
373
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
374
|
+
# :without_overlaps :: Use WITHOUT OVERLAPS clause to specify an exclusion constraint
|
|
375
|
+
# on the final column (PostgreSQL 18+, composite primary keys only).
|
|
306
376
|
#
|
|
307
377
|
# Examples:
|
|
308
378
|
# primary_key(:id)
|
|
@@ -346,6 +416,15 @@ module Sequel
|
|
|
346
416
|
#
|
|
347
417
|
# Supports the same :deferrable option as #column. The :name option can be used
|
|
348
418
|
# to name the constraint.
|
|
419
|
+
#
|
|
420
|
+
# PostgreSQL specific options:
|
|
421
|
+
#
|
|
422
|
+
# :include :: Include additional columns in the underlying index, to
|
|
423
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
424
|
+
# :nulls_not_distinct :: Use NULLS NOT DISTINCT to setup a constraint where NULL
|
|
425
|
+
# entries are considered distinct (PostgreSQL 15+)
|
|
426
|
+
# :without_overlaps :: Use WITHOUT OVERLAPS clause to specify an exclusion constraint
|
|
427
|
+
# on the final column (PostgreSQL 18+, composite unique only).
|
|
349
428
|
def unique(columns, opts = OPTS)
|
|
350
429
|
constraints << {:type => :unique, :columns => Array(columns)}.merge!(opts)
|
|
351
430
|
nil
|
|
@@ -379,6 +458,8 @@ module Sequel
|
|
|
379
458
|
# For more information on Sequel's support for schema modification, see
|
|
380
459
|
# the {"Schema Modification" guide}[link:files/doc/schema_modification_rdoc.html].
|
|
381
460
|
class AlterTableGenerator
|
|
461
|
+
include ColumnOptionMerger
|
|
462
|
+
|
|
382
463
|
# An array of operations to perform
|
|
383
464
|
attr_reader :operations
|
|
384
465
|
|
|
@@ -404,7 +485,7 @@ module Sequel
|
|
|
404
485
|
# :after :: The name of an existing column that the new column should be positioned after
|
|
405
486
|
# :first :: Create this new column before all other existing columns
|
|
406
487
|
def add_column(name, type, opts = OPTS)
|
|
407
|
-
op = {:op => :add_column, :name => name, :type => type}
|
|
488
|
+
op = _merge_column_options({:op => :add_column, :name => name, :type => type}, opts)
|
|
408
489
|
index_opts = op.delete(:index)
|
|
409
490
|
@operations << op
|
|
410
491
|
add_index(name, index_opts.is_a?(Hash) ? index_opts : OPTS) if index_opts
|
|
@@ -430,6 +511,16 @@ module Sequel
|
|
|
430
511
|
# add_unique_constraint(:name, name: :unique_name) # ADD CONSTRAINT unique_name UNIQUE (name)
|
|
431
512
|
#
|
|
432
513
|
# Supports the same :deferrable option as CreateTableGenerator#column.
|
|
514
|
+
#
|
|
515
|
+
# PostgreSQL specific options:
|
|
516
|
+
#
|
|
517
|
+
# :include :: Include additional columns in the underlying index, to
|
|
518
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
519
|
+
# :nulls_not_distinct :: Use NULLS NOT DISTINCT to setup a constraint where NULL
|
|
520
|
+
# entries are considered distinct (PostgreSQL 15+)
|
|
521
|
+
# :using_index :: Use the USING INDEX clause to specify an existing unique index
|
|
522
|
+
# :without_overlaps :: Use WITHOUT OVERLAPS clause to specify an exclusion constraint
|
|
523
|
+
# on the final column (PostgreSQL 18+, composite unique constraints only).
|
|
433
524
|
def add_unique_constraint(columns, opts = OPTS)
|
|
434
525
|
@operations << {:op => :add_constraint, :type => :unique, :columns => Array(columns)}.merge!(opts)
|
|
435
526
|
nil
|
|
@@ -459,7 +550,7 @@ module Sequel
|
|
|
459
550
|
# sense when using an array of columns.
|
|
460
551
|
def add_foreign_key(name, table, opts = OPTS)
|
|
461
552
|
return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
|
|
462
|
-
add_column(name, Integer, {:table=>table}.merge!(opts))
|
|
553
|
+
add_column(name, opts.fetch(:type, Integer), {:table=>table}.merge!(opts))
|
|
463
554
|
end
|
|
464
555
|
|
|
465
556
|
# Add a full text index on the given columns.
|
|
@@ -483,6 +574,14 @@ module Sequel
|
|
|
483
574
|
#
|
|
484
575
|
# add_primary_key(:id) # ADD COLUMN id serial PRIMARY KEY
|
|
485
576
|
# add_primary_key([:artist_id, :name]) # ADD PRIMARY KEY (artist_id, name)
|
|
577
|
+
#
|
|
578
|
+
# PostgreSQL specific options:
|
|
579
|
+
#
|
|
580
|
+
# :include :: Include additional columns in the underlying index, to
|
|
581
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
|
582
|
+
# :using_index :: Use the USING INDEX clause to specify an existing unique index
|
|
583
|
+
# :without_overlaps :: Use WITHOUT OVERLAPS clause to specify an exclusion constraint
|
|
584
|
+
# on the final column (PostgreSQL 18+, composite primary keys only).
|
|
486
585
|
def add_primary_key(name, opts = OPTS)
|
|
487
586
|
return add_composite_primary_key(name, opts) if name.is_a?(Array)
|
|
488
587
|
opts = @db.serial_primary_key_options.merge(opts)
|
|
@@ -589,9 +688,11 @@ module Sequel
|
|
|
589
688
|
nil
|
|
590
689
|
end
|
|
591
690
|
|
|
592
|
-
# Modify the type of one of the table's column.
|
|
691
|
+
# Modify the type of one of the table's column. The given options are considered when
|
|
692
|
+
# determining the new type.
|
|
593
693
|
#
|
|
594
694
|
# set_column_type(:artist_name, 'char(10)') # ALTER COLUMN artist_name TYPE char(10)
|
|
695
|
+
# set_column_type(:artist_name, String, size: 10) # ALTER COLUMN artist_name TYPE varchar(10)
|
|
595
696
|
#
|
|
596
697
|
# PostgreSQL specific options:
|
|
597
698
|
#
|
|
@@ -191,6 +191,8 @@ module Sequel
|
|
|
191
191
|
# The +any+ type is treated like a SQLite column in a non-strict table,
|
|
192
192
|
# allowing any type of data to be stored. This option is supported on
|
|
193
193
|
# SQLite 3.37.0+.
|
|
194
|
+
# :using :: Create a VIRTUAL table with the given USING clause. The value should be
|
|
195
|
+
# a string, as it is used directly in the SQL query.
|
|
194
196
|
# :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special
|
|
195
197
|
# 'rowid' column, that uniquely identifies that row within the table.
|
|
196
198
|
# If this option is used, the 'rowid' column is omitted, which can
|
|
@@ -484,7 +486,9 @@ module Sequel
|
|
|
484
486
|
end
|
|
485
487
|
|
|
486
488
|
def alter_table_set_column_type_sql(table, op)
|
|
487
|
-
"ALTER COLUMN #{quote_identifier(op[:name])} TYPE #{type_literal(op)}"
|
|
489
|
+
sql = "ALTER COLUMN #{quote_identifier(op[:name])} TYPE #{type_literal(op)}".dup
|
|
490
|
+
column_definition_collate_sql(sql, op)
|
|
491
|
+
sql
|
|
488
492
|
end
|
|
489
493
|
|
|
490
494
|
def alter_table_set_column_default_sql(table, op)
|
|
@@ -590,7 +594,12 @@ module Sequel
|
|
|
590
594
|
|
|
591
595
|
# Add null/not null SQL fragment to column creation SQL.
|
|
592
596
|
def column_definition_null_sql(sql, column)
|
|
593
|
-
null =
|
|
597
|
+
null = if column[:not_null]
|
|
598
|
+
false
|
|
599
|
+
else
|
|
600
|
+
column.fetch(:null, column[:allow_null])
|
|
601
|
+
end
|
|
602
|
+
|
|
594
603
|
if null.nil? && !can_add_primary_key_constraint_on_nullable_columns? && column[:primary_key]
|
|
595
604
|
null = false
|
|
596
605
|
end
|
|
@@ -603,36 +612,71 @@ module Sequel
|
|
|
603
612
|
end
|
|
604
613
|
end
|
|
605
614
|
|
|
606
|
-
# Add primary key SQL fragment to column creation SQL.
|
|
615
|
+
# Add primary key SQL fragment to column creation SQL if column is a primary key.
|
|
607
616
|
def column_definition_primary_key_sql(sql, column)
|
|
608
|
-
if column[:primary_key]
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
617
|
+
column_definition_add_primary_key_sql(sql, column) if column[:primary_key]
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# Add primary key SQL fragment to column creation SQL (column should be a primary key).
|
|
621
|
+
def column_definition_add_primary_key_sql(sql, column)
|
|
622
|
+
constraint = column_definition_constraint_hash(column, :primary_key)
|
|
623
|
+
append_named_constraint_prefix_sql(sql, constraint[:name])
|
|
624
|
+
column_definition_append_primary_key_sql(sql, constraint)
|
|
625
|
+
constraint_deferrable_sql_append(sql, constraint[:deferrable])
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
def column_definition_append_primary_key_sql(sql, constraint)
|
|
629
|
+
sql << " " << primary_key_constraint_sql_fragment(constraint)
|
|
615
630
|
end
|
|
616
631
|
|
|
617
|
-
# Add foreign key reference SQL fragment to column creation SQL.
|
|
632
|
+
# Add foreign key reference SQL fragment to column creation SQL if column is a foreign key.
|
|
618
633
|
def column_definition_references_sql(sql, column)
|
|
619
|
-
if column[:table]
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
634
|
+
column_definition_add_references_sql(sql, column) if column[:table]
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# Add foreign key reference SQL fragment to column creation SQL (column should be a foreign key).
|
|
638
|
+
def column_definition_add_references_sql(sql, column)
|
|
639
|
+
append_named_constraint_prefix_sql(sql, column[:foreign_key_constraint_name])
|
|
640
|
+
sql << column_references_column_constraint_sql(column)
|
|
625
641
|
end
|
|
626
642
|
|
|
627
|
-
# Add unique constraint SQL fragment to column creation SQL.
|
|
643
|
+
# Add unique constraint SQL fragment to column creation SQL if column has a unique constraint.
|
|
628
644
|
def column_definition_unique_sql(sql, column)
|
|
629
|
-
if column[:unique]
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
645
|
+
column_definition_add_unique_sql(sql, column) if column[:unique]
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
# Add unique constraint SQL fragment to column creation SQL (column should have unique constraint).
|
|
649
|
+
def column_definition_add_unique_sql(sql, column)
|
|
650
|
+
constraint = column_definition_constraint_hash(column, :unique)
|
|
651
|
+
append_named_constraint_prefix_sql(sql, constraint[:name])
|
|
652
|
+
column_definition_append_unique_sql(sql, constraint)
|
|
653
|
+
constraint_deferrable_sql_append(sql, constraint[:deferrable])
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
def column_definition_append_unique_sql(sql, constraint)
|
|
657
|
+
sql << ' ' << unique_constraint_sql_fragment(constraint)
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# Add the name of the constraint to the column creation SQL.
|
|
661
|
+
def append_named_constraint_prefix_sql(sql, name)
|
|
662
|
+
sql << " CONSTRAINT #{quote_identifier(name)}" if name
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
# Return a hash of constraint options for the primary key or column
|
|
666
|
+
# unique constraint.
|
|
667
|
+
def column_definition_constraint_hash(column, prefix)
|
|
668
|
+
constraint = column[prefix]
|
|
669
|
+
constraint = constraint.is_a?(Hash) ? constraint.dup : {}
|
|
670
|
+
|
|
671
|
+
if name = column[:"#{prefix}_constraint_name"]
|
|
672
|
+
constraint[:name] = name
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
if column.has_key?(:"#{prefix}_deferrable")
|
|
676
|
+
constraint[:deferrable] = column[:"#{prefix}_deferrable"]
|
|
635
677
|
end
|
|
678
|
+
|
|
679
|
+
constraint
|
|
636
680
|
end
|
|
637
681
|
|
|
638
682
|
# SQL for all given columns, used inside a CREATE TABLE block.
|
|
@@ -649,12 +693,16 @@ module Sequel
|
|
|
649
693
|
def column_references_sql(column)
|
|
650
694
|
sql = String.new
|
|
651
695
|
sql << " REFERENCES #{quote_schema_table(column[:table])}"
|
|
652
|
-
sql
|
|
696
|
+
column_references_append_key_sql(sql, column) if column[:key]
|
|
653
697
|
sql << " ON DELETE #{on_delete_clause(column[:on_delete])}" if column[:on_delete]
|
|
654
698
|
sql << " ON UPDATE #{on_update_clause(column[:on_update])}" if column[:on_update]
|
|
655
699
|
constraint_deferrable_sql_append(sql, column[:deferrable])
|
|
656
700
|
sql
|
|
657
701
|
end
|
|
702
|
+
|
|
703
|
+
def column_references_append_key_sql(sql, column)
|
|
704
|
+
sql << "(#{Array(column[:key]).map{|x| quote_identifier(x)}.join(', ')})"
|
|
705
|
+
end
|
|
658
706
|
|
|
659
707
|
# SQL fragment for table foreign key references (table constraints)
|
|
660
708
|
def column_references_table_constraint_sql(constraint)
|
|
@@ -675,7 +723,7 @@ module Sequel
|
|
|
675
723
|
check = constraint[:check]
|
|
676
724
|
check = check.first if check.is_a?(Array) && check.length == 1
|
|
677
725
|
check = filter_expr(check)
|
|
678
|
-
check = "(#{check})" unless check
|
|
726
|
+
check = "(#{check})" unless check.start_with?('(') && check.end_with?(')')
|
|
679
727
|
sql << "CHECK #{check}"
|
|
680
728
|
when :primary_key
|
|
681
729
|
sql << "#{primary_key_constraint_sql_fragment(constraint)} #{literal(constraint[:columns])}"
|
|
@@ -731,17 +779,24 @@ module Sequel
|
|
|
731
779
|
def create_table_sql(name, generator, options)
|
|
732
780
|
unless supports_named_column_constraints?
|
|
733
781
|
# Split column constraints into table constraints if they have a name
|
|
782
|
+
fk_opt_keys = [:key, :on_delete, :on_update, :deferrable]
|
|
734
783
|
generator.columns.each do |c|
|
|
735
784
|
if (constraint_name = c.delete(:foreign_key_constraint_name)) && (table = c.delete(:table))
|
|
736
785
|
opts = {}
|
|
737
786
|
opts[:name] = constraint_name
|
|
738
|
-
|
|
787
|
+
fk_opt_keys.each{|k| opts[k] = c[k]}
|
|
739
788
|
generator.foreign_key([c[:name]], table, opts)
|
|
740
789
|
end
|
|
741
|
-
|
|
790
|
+
|
|
791
|
+
if c[:unique].is_a?(Hash) && c[:unique][:name]
|
|
792
|
+
generator.unique(c[:name], c.delete(:unique))
|
|
793
|
+
elsif (constraint_name = c.delete(:unique_constraint_name)) && c.delete(:unique)
|
|
742
794
|
generator.unique(c[:name], :name=>constraint_name)
|
|
743
795
|
end
|
|
744
|
-
|
|
796
|
+
|
|
797
|
+
if c[:primary_key].is_a?(Hash) && c[:primary_key][:name]
|
|
798
|
+
generator.primary_key([c[:name]], c.delete(:primary_key))
|
|
799
|
+
elsif (constraint_name = c.delete(:primary_key_constraint_name)) && c.delete(:primary_key)
|
|
745
800
|
generator.primary_key([c[:name]], :name=>constraint_name)
|
|
746
801
|
end
|
|
747
802
|
end
|
|
@@ -764,7 +819,7 @@ module Sequel
|
|
|
764
819
|
# SELECT sql statement.
|
|
765
820
|
def create_table_as(name, sql, options)
|
|
766
821
|
sql = sql.sql if sql.is_a?(Sequel::Dataset)
|
|
767
|
-
run(create_table_as_sql(name, sql, options))
|
|
822
|
+
run(create_table_as_sql(name, sql, options).freeze)
|
|
768
823
|
end
|
|
769
824
|
|
|
770
825
|
# SQL statement for creating a table from the result of a SELECT statement.
|
|
@@ -11,11 +11,12 @@ module Sequel
|
|
|
11
11
|
|
|
12
12
|
# Action methods defined by Sequel that execute code on the database.
|
|
13
13
|
ACTION_METHODS = (<<-METHS).split.map(&:to_sym).freeze
|
|
14
|
-
<< [] all as_hash avg count columns columns! delete each
|
|
14
|
+
<< [] all as_hash as_set avg count columns columns! delete each
|
|
15
15
|
empty? fetch_rows first first! get import insert last
|
|
16
|
-
map max min multi_insert paged_each select_hash select_hash_groups
|
|
17
|
-
single_record single_record!
|
|
18
|
-
|
|
16
|
+
map max min multi_insert paged_each select_hash select_hash_groups
|
|
17
|
+
select_map select_order_map select_set single_record single_record!
|
|
18
|
+
single_value single_value! sum to_hash to_hash_groups
|
|
19
|
+
truncate update where_all where_each where_single_value
|
|
19
20
|
METHS
|
|
20
21
|
|
|
21
22
|
# The clone options to use when retrieving columns for a dataset.
|
|
@@ -51,6 +52,26 @@ module Sequel
|
|
|
51
52
|
_all(block){|a| each{|r| a << r}}
|
|
52
53
|
end
|
|
53
54
|
|
|
55
|
+
# Returns sets for column values for each record in the dataset.
|
|
56
|
+
#
|
|
57
|
+
# DB[:table].as_set(:id) # SELECT * FROM table
|
|
58
|
+
# # => Set[1, 2, 3, ...]
|
|
59
|
+
#
|
|
60
|
+
# You can also provide an array of column names, in which case the elements
|
|
61
|
+
# of the returned set are arrays (not sets):
|
|
62
|
+
#
|
|
63
|
+
# DB[:table].as_set([:id, :name]) # SELECT * FROM table
|
|
64
|
+
# # => Set[[1, 'A'], [2, 'B'], [3, 'C'], ...]
|
|
65
|
+
def as_set(column)
|
|
66
|
+
return naked.as_set(column) if row_proc
|
|
67
|
+
|
|
68
|
+
if column.is_a?(Array)
|
|
69
|
+
to_set{|r| r.values_at(*column)}
|
|
70
|
+
else
|
|
71
|
+
to_set{|r| r[column]}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
54
75
|
# Returns the average value for the given column/expression.
|
|
55
76
|
# Uses a virtual row block if no argument is given.
|
|
56
77
|
#
|
|
@@ -217,7 +238,7 @@ module Sequel
|
|
|
217
238
|
case args.length
|
|
218
239
|
when 0
|
|
219
240
|
unless block
|
|
220
|
-
return single_record
|
|
241
|
+
return(@opts[:sql] ? single_record! : single_record)
|
|
221
242
|
end
|
|
222
243
|
when 1
|
|
223
244
|
arg = args[0]
|
|
@@ -282,6 +303,12 @@ module Sequel
|
|
|
282
303
|
#
|
|
283
304
|
# DB[:table].get{[sum(id).as(sum), name]} # SELECT sum(id) AS sum, name FROM table LIMIT 1
|
|
284
305
|
# # => [6, 'foo']
|
|
306
|
+
#
|
|
307
|
+
# If called on a dataset with raw SQL, returns the
|
|
308
|
+
# first value in the dataset without changing the selection or setting a limit:
|
|
309
|
+
#
|
|
310
|
+
# DB["SELECT id FROM table"].get # SELECT id FROM table
|
|
311
|
+
# # => 3
|
|
285
312
|
def get(column=(no_arg=true; nil), &block)
|
|
286
313
|
ds = naked
|
|
287
314
|
if block
|
|
@@ -289,6 +316,8 @@ module Sequel
|
|
|
289
316
|
ds = ds.select(&block)
|
|
290
317
|
column = ds.opts[:select]
|
|
291
318
|
column = nil if column.is_a?(Array) && column.length < 2
|
|
319
|
+
elsif no_arg && opts[:sql]
|
|
320
|
+
return ds.single_value!
|
|
292
321
|
else
|
|
293
322
|
case column
|
|
294
323
|
when Array
|
|
@@ -343,6 +372,15 @@ module Sequel
|
|
|
343
372
|
# DB[:table].import([:x, :y], DB[:table2].select(:a, :b))
|
|
344
373
|
# # INSERT INTO table (x, y) SELECT a, b FROM table2
|
|
345
374
|
#
|
|
375
|
+
# The return value of this method is undefined and should not be used,
|
|
376
|
+
# except in two cases:
|
|
377
|
+
#
|
|
378
|
+
# * When the <tt>return: :primary_key</tt> option is used.
|
|
379
|
+
# * On PostgreSQL, when the dataset uses RETURNING. In this case, if
|
|
380
|
+
# a single value is returned per row, the return value is an array
|
|
381
|
+
# of those values. If multiple values are returned per row, the
|
|
382
|
+
# return value is an array of hashes.
|
|
383
|
+
#
|
|
346
384
|
# Options:
|
|
347
385
|
# :commit_every :: Open a new transaction for every given number of
|
|
348
386
|
# records. For example, if you provide a value of 50,
|
|
@@ -719,10 +757,7 @@ module Sequel
|
|
|
719
757
|
end
|
|
720
758
|
|
|
721
759
|
# Selects the column given (either as an argument or as a block), and
|
|
722
|
-
# returns an array of all values of that column in the dataset.
|
|
723
|
-
# give a block argument that returns an array with multiple entries,
|
|
724
|
-
# the contents of the resulting array are undefined. Raises an Error
|
|
725
|
-
# if called with both an argument and a block.
|
|
760
|
+
# returns an array of all values of that column in the dataset.
|
|
726
761
|
#
|
|
727
762
|
# DB[:table].select_map(:id) # SELECT id FROM table
|
|
728
763
|
# # => [3, 5, 8, 1, ...]
|
|
@@ -760,6 +795,34 @@ module Sequel
|
|
|
760
795
|
_select_map(column, true, &block)
|
|
761
796
|
end
|
|
762
797
|
|
|
798
|
+
# Selects the column given (either as an argument or as a block), and
|
|
799
|
+
# returns a set of all values of that column in the dataset.
|
|
800
|
+
#
|
|
801
|
+
# DB[:table].select_set(:id) # SELECT id FROM table
|
|
802
|
+
# # => Set[3, 5, 8, 1, ...]
|
|
803
|
+
#
|
|
804
|
+
# DB[:table].select_set{id * 2} # SELECT (id * 2) FROM table
|
|
805
|
+
# # => Set[6, 10, 16, 2, ...]
|
|
806
|
+
#
|
|
807
|
+
# You can also provide an array of column names, which returns a set
|
|
808
|
+
# with array elements (not set elements):
|
|
809
|
+
#
|
|
810
|
+
# DB[:table].select_map([:id, :name]) # SELECT id, name FROM table
|
|
811
|
+
# # => Set[[1, 'A'], [2, 'B'], [3, 'C'], ...]
|
|
812
|
+
#
|
|
813
|
+
# If you provide an array of expressions, you must be sure that each entry
|
|
814
|
+
# in the array has an alias that Sequel can determine.
|
|
815
|
+
def select_set(column=nil, &block)
|
|
816
|
+
ds = ungraphed.naked
|
|
817
|
+
columns = Array(column)
|
|
818
|
+
virtual_row_columns(columns, block)
|
|
819
|
+
if column.is_a?(Array) || (columns.length > 1)
|
|
820
|
+
ds.select(*columns)._select_set_multiple(hash_key_symbols(columns))
|
|
821
|
+
else
|
|
822
|
+
ds.select(auto_alias_expression(columns.first))._select_set_single
|
|
823
|
+
end
|
|
824
|
+
end
|
|
825
|
+
|
|
763
826
|
# Limits the dataset to one record, and returns the first record in the dataset,
|
|
764
827
|
# or nil if the dataset has no records. Users should probably use +first+ instead of
|
|
765
828
|
# this method. Example:
|
|
@@ -1084,6 +1147,17 @@ module Sequel
|
|
|
1084
1147
|
map{|r| r[k||=r.keys.first]}
|
|
1085
1148
|
end
|
|
1086
1149
|
|
|
1150
|
+
# Return a set of arrays of values given by the symbols in ret_cols.
|
|
1151
|
+
def _select_set_multiple(ret_cols)
|
|
1152
|
+
to_set{|r| r.values_at(*ret_cols)}
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
# Returns a set of the first value in each row.
|
|
1156
|
+
def _select_set_single
|
|
1157
|
+
k = nil
|
|
1158
|
+
to_set{|r| r[k||=r.keys.first]}
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1087
1161
|
# A dataset for returning single values from the current dataset.
|
|
1088
1162
|
def single_value_ds
|
|
1089
1163
|
clone(:limit=>1).ungraphed.naked
|
|
@@ -1248,8 +1322,6 @@ module Sequel
|
|
|
1248
1322
|
# receiver's current order. This yields the row and the array of order expressions
|
|
1249
1323
|
# to the block, which should return an array of values to use.
|
|
1250
1324
|
def ignore_values_preceding(row)
|
|
1251
|
-
@opts[:order].map{|v| v.is_a?(SQL::OrderedExpression) ? v.expression : v}
|
|
1252
|
-
|
|
1253
1325
|
order_exprs = @opts[:order].map do |v|
|
|
1254
1326
|
if v.is_a?(SQL::OrderedExpression)
|
|
1255
1327
|
descending = v.descending
|