sequel 5.33.0 → 5.58.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 +318 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +40 -9
- data/doc/association_basics.rdoc +77 -13
- data/doc/cheat_sheet.rdoc +13 -5
- data/doc/code_order.rdoc +0 -12
- data/doc/dataset_filtering.rdoc +2 -2
- data/doc/fork_safety.rdoc +84 -0
- data/doc/migration.rdoc +12 -6
- data/doc/model_plugins.rdoc +1 -1
- data/doc/opening_databases.rdoc +15 -3
- data/doc/postgresql.rdoc +9 -1
- data/doc/querying.rdoc +7 -5
- data/doc/release_notes/5.34.0.txt +40 -0
- data/doc/release_notes/5.35.0.txt +56 -0
- data/doc/release_notes/5.36.0.txt +60 -0
- data/doc/release_notes/5.37.0.txt +30 -0
- data/doc/release_notes/5.38.0.txt +28 -0
- data/doc/release_notes/5.39.0.txt +19 -0
- data/doc/release_notes/5.40.0.txt +40 -0
- data/doc/release_notes/5.41.0.txt +25 -0
- data/doc/release_notes/5.42.0.txt +136 -0
- data/doc/release_notes/5.43.0.txt +98 -0
- data/doc/release_notes/5.44.0.txt +32 -0
- data/doc/release_notes/5.45.0.txt +34 -0
- data/doc/release_notes/5.46.0.txt +87 -0
- data/doc/release_notes/5.47.0.txt +59 -0
- data/doc/release_notes/5.48.0.txt +14 -0
- data/doc/release_notes/5.49.0.txt +59 -0
- data/doc/release_notes/5.50.0.txt +78 -0
- data/doc/release_notes/5.51.0.txt +47 -0
- data/doc/release_notes/5.52.0.txt +87 -0
- data/doc/release_notes/5.53.0.txt +23 -0
- data/doc/release_notes/5.54.0.txt +27 -0
- data/doc/release_notes/5.55.0.txt +21 -0
- data/doc/release_notes/5.56.0.txt +51 -0
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/sql.rdoc +14 -2
- data/doc/testing.rdoc +10 -1
- data/doc/transactions.rdoc +0 -8
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/ado/access.rb +1 -1
- data/lib/sequel/adapters/ado.rb +17 -17
- data/lib/sequel/adapters/amalgalite.rb +3 -5
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +8 -0
- data/lib/sequel/adapters/jdbc/h2.rb +60 -10
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +4 -4
- data/lib/sequel/adapters/jdbc/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +29 -19
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +8 -6
- data/lib/sequel/adapters/oracle.rb +5 -4
- data/lib/sequel/adapters/postgres.rb +27 -29
- data/lib/sequel/adapters/shared/access.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +84 -7
- data/lib/sequel/adapters/shared/mysql.rb +33 -2
- data/lib/sequel/adapters/shared/oracle.rb +82 -7
- data/lib/sequel/adapters/shared/postgres.rb +158 -20
- data/lib/sequel/adapters/shared/sqlanywhere.rb +3 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -10
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +2 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +9 -8
- data/lib/sequel/connection_pool/sharded_threaded.rb +10 -10
- data/lib/sequel/connection_pool/single.rb +7 -9
- data/lib/sequel/connection_pool/threaded.rb +1 -1
- data/lib/sequel/core.rb +33 -24
- data/lib/sequel/database/connecting.rb +3 -4
- data/lib/sequel/database/misc.rb +37 -12
- data/lib/sequel/database/query.rb +3 -1
- data/lib/sequel/database/schema_generator.rb +50 -53
- data/lib/sequel/database/schema_methods.rb +45 -23
- data/lib/sequel/database/transactions.rb +9 -6
- data/lib/sequel/dataset/actions.rb +61 -8
- data/lib/sequel/dataset/features.rb +15 -0
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +114 -11
- data/lib/sequel/dataset/sql.rb +172 -46
- data/lib/sequel/deprecated.rb +3 -1
- data/lib/sequel/exceptions.rb +2 -0
- data/lib/sequel/extensions/_pretty_table.rb +1 -2
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -2
- data/lib/sequel/extensions/core_refinements.rb +38 -11
- data/lib/sequel/extensions/date_arithmetic.rb +36 -24
- data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
- data/lib/sequel/extensions/datetime_parse_to_time.rb +5 -1
- data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
- data/lib/sequel/extensions/eval_inspect.rb +2 -0
- data/lib/sequel/extensions/inflector.rb +9 -1
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/migration.rb +13 -2
- data/lib/sequel/extensions/named_timezones.rb +5 -1
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +1 -0
- data/lib/sequel/extensions/pg_array_ops.rb +6 -2
- data/lib/sequel/extensions/pg_enum.rb +3 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +55 -3
- data/lib/sequel/extensions/pg_inet.rb +2 -0
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +35 -8
- data/lib/sequel/extensions/pg_json.rb +3 -5
- data/lib/sequel/extensions/pg_json_ops.rb +119 -4
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +372 -0
- data/lib/sequel/extensions/pg_range.rb +7 -19
- data/lib/sequel/extensions/pg_range_ops.rb +39 -9
- data/lib/sequel/extensions/pg_row.rb +1 -1
- data/lib/sequel/extensions/pg_row_ops.rb +25 -1
- data/lib/sequel/extensions/query.rb +3 -0
- data/lib/sequel/extensions/run_transaction_hooks.rb +1 -1
- data/lib/sequel/extensions/s.rb +4 -1
- data/lib/sequel/extensions/schema_dumper.rb +16 -5
- data/lib/sequel/extensions/server_block.rb +8 -12
- data/lib/sequel/extensions/sql_comments.rb +110 -3
- data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
- data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
- data/lib/sequel/extensions/string_agg.rb +1 -1
- data/lib/sequel/extensions/string_date_time.rb +19 -23
- data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
- data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
- data/lib/sequel/extensions/to_dot.rb +9 -3
- data/lib/sequel/model/associations.rb +342 -114
- data/lib/sequel/model/base.rb +45 -24
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +8 -3
- data/lib/sequel/model.rb +3 -1
- data/lib/sequel/plugins/association_pks.rb +60 -18
- data/lib/sequel/plugins/association_proxies.rb +3 -0
- data/lib/sequel/plugins/async_thread_pool.rb +39 -0
- data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
- data/lib/sequel/plugins/auto_validations.rb +39 -5
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/blacklist_security.rb +1 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +3 -8
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +8 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/csv_serializer.rb +2 -0
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +44 -0
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/forbid_lazy_load.rb +2 -0
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +113 -0
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +4 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +8 -3
- data/lib/sequel/plugins/pg_array_associations.rb +58 -41
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +2 -0
- data/lib/sequel/plugins/prepared_statements.rb +15 -12
- data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
- data/lib/sequel/plugins/rcte_tree.rb +37 -35
- data/lib/sequel/plugins/serialization.rb +9 -3
- data/lib/sequel/plugins/serialization_modification_detection.rb +2 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +7 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/string_stripper.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +8 -2
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/tree.rb +9 -4
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +5 -1
- data/lib/sequel/plugins/validation_helpers.rb +18 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +20 -17
- data/lib/sequel/version.rb +1 -1
- metadata +93 -39
|
@@ -38,7 +38,6 @@ module Sequel
|
|
|
38
38
|
@constraints = []
|
|
39
39
|
@primary_key = nil
|
|
40
40
|
instance_exec(&block) if block
|
|
41
|
-
@columns.unshift(@primary_key) if @primary_key && !has_column?(primary_key_name)
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
# Use custom Bignum method to use :Bignum instead of Bignum class, to work
|
|
@@ -144,8 +143,17 @@ module Sequel
|
|
|
144
143
|
# :identity :: Create an identity column.
|
|
145
144
|
#
|
|
146
145
|
# MySQL specific options:
|
|
146
|
+
#
|
|
147
147
|
# :generated_type :: Set the type of column when using :generated_always_as,
|
|
148
148
|
# should be :virtual or :stored to force a type.
|
|
149
|
+
# :on_update_current_timestamp :: Use ON UPDATE CURRENT TIMESTAMP when defining the column,
|
|
150
|
+
# which will update the column value to CURRENT_TIMESTAMP
|
|
151
|
+
# on every UPDATE.
|
|
152
|
+
#
|
|
153
|
+
# Microsoft SQL Server specific options:
|
|
154
|
+
#
|
|
155
|
+
# :clustered :: When using :primary_key or :unique, marks the primary key or unique
|
|
156
|
+
# constraint as CLUSTERED (if true), or NONCLUSTERED (if false).
|
|
149
157
|
def column(name, type, opts = OPTS)
|
|
150
158
|
columns << {:name => name, :type => type}.merge!(opts)
|
|
151
159
|
if index_opts = opts[:index]
|
|
@@ -154,7 +162,7 @@ module Sequel
|
|
|
154
162
|
nil
|
|
155
163
|
end
|
|
156
164
|
|
|
157
|
-
# Adds a named constraint (or unnamed if name is nil),
|
|
165
|
+
# Adds a named CHECK constraint (or unnamed if name is nil),
|
|
158
166
|
# with the given block or args. To provide options for the constraint, pass
|
|
159
167
|
# a hash as the first argument.
|
|
160
168
|
#
|
|
@@ -162,6 +170,15 @@ module Sequel
|
|
|
162
170
|
# # CONSTRAINT blah CHECK num >= 1 AND num <= 5
|
|
163
171
|
# constraint({name: :blah, deferrable: true}, num: 1..5)
|
|
164
172
|
# # CONSTRAINT blah CHECK num >= 1 AND num <= 5 DEFERRABLE INITIALLY DEFERRED
|
|
173
|
+
#
|
|
174
|
+
# If the first argument is a hash, the following options are supported:
|
|
175
|
+
#
|
|
176
|
+
# Options:
|
|
177
|
+
# :name :: The name of the CHECK constraint
|
|
178
|
+
# :deferrable :: Whether the CHECK constraint should be marked DEFERRABLE.
|
|
179
|
+
#
|
|
180
|
+
# PostgreSQL specific options:
|
|
181
|
+
# :not_valid :: Whether the CHECK constraint should be marked NOT VALID.
|
|
165
182
|
def constraint(name, *args, &block)
|
|
166
183
|
opts = name.is_a?(Hash) ? name : {:name=>name}
|
|
167
184
|
constraints << opts.merge(:type=>:check, :check=>block || args)
|
|
@@ -200,14 +217,12 @@ module Sequel
|
|
|
200
217
|
end
|
|
201
218
|
|
|
202
219
|
# Add a full text index on the given columns.
|
|
220
|
+
# See #index for additional options.
|
|
203
221
|
#
|
|
204
222
|
# PostgreSQL specific options:
|
|
205
223
|
# :index_type :: Can be set to :gist to use a GIST index instead of the
|
|
206
224
|
# default GIN index.
|
|
207
225
|
# :language :: Set a language to use for the index (default: simple).
|
|
208
|
-
#
|
|
209
|
-
# Microsoft SQL Server specific options:
|
|
210
|
-
# :key_index :: The KEY INDEX to use for the full text index.
|
|
211
226
|
def full_text_index(columns, opts = OPTS)
|
|
212
227
|
index(columns, opts.merge(:type => :full_text))
|
|
213
228
|
end
|
|
@@ -217,35 +232,43 @@ module Sequel
|
|
|
217
232
|
columns.any?{|c| c[:name] == name}
|
|
218
233
|
end
|
|
219
234
|
|
|
220
|
-
# Add an index on the given column(s) with the given options.
|
|
235
|
+
# Add an index on the given column(s) with the given options. Examples:
|
|
236
|
+
#
|
|
237
|
+
# index :name
|
|
238
|
+
# # CREATE INDEX table_name_index ON table (name)
|
|
239
|
+
#
|
|
240
|
+
# index [:artist_id, :name]
|
|
241
|
+
# # CREATE INDEX table_artist_id_name_index ON table (artist_id, name)
|
|
242
|
+
#
|
|
243
|
+
# index [:artist_id, :name], name: :foo
|
|
244
|
+
# # CREATE INDEX foo ON table (artist_id, name)
|
|
245
|
+
#
|
|
221
246
|
# General options:
|
|
222
247
|
#
|
|
248
|
+
# :include :: Include additional column values in the index, without
|
|
249
|
+
# actually indexing on those values (only supported by
|
|
250
|
+
# some databases).
|
|
223
251
|
# :name :: The name to use for the index. If not given, a default name
|
|
224
252
|
# based on the table and columns is used.
|
|
225
|
-
# :type :: The type of index to use (only supported by some databases
|
|
253
|
+
# :type :: The type of index to use (only supported by some databases,
|
|
254
|
+
# :full_text and :spatial values are handled specially).
|
|
226
255
|
# :unique :: Make the index unique, so duplicate values are not allowed.
|
|
227
|
-
# :where ::
|
|
256
|
+
# :where :: A filter expression, used to create a partial index (only
|
|
257
|
+
# supported by some databases).
|
|
228
258
|
#
|
|
229
259
|
# PostgreSQL specific options:
|
|
230
260
|
#
|
|
231
261
|
# :concurrently :: Create the index concurrently, so it doesn't block
|
|
232
262
|
# operations on the table while the index is being
|
|
233
263
|
# built.
|
|
234
|
-
# :
|
|
235
|
-
# :
|
|
236
|
-
#
|
|
264
|
+
# :if_not_exists :: Only create the index if an index of the same name doesn't already exist.
|
|
265
|
+
# :opclass :: Set an opclass to use for all columns (per-column opclasses require
|
|
266
|
+
# custom SQL).
|
|
237
267
|
# :tablespace :: Specify tablespace for index.
|
|
238
268
|
#
|
|
239
269
|
# Microsoft SQL Server specific options:
|
|
240
270
|
#
|
|
241
|
-
# :
|
|
242
|
-
# actually indexing on those values.
|
|
243
|
-
#
|
|
244
|
-
# index :name
|
|
245
|
-
# # CREATE INDEX table_name_index ON table (name)
|
|
246
|
-
#
|
|
247
|
-
# index [:artist_id, :name]
|
|
248
|
-
# # CREATE INDEX table_artist_id_name_index ON table (artist_id, name)
|
|
271
|
+
# :key_index :: Sets the KEY INDEX to the given value.
|
|
249
272
|
def index(columns, opts = OPTS)
|
|
250
273
|
indexes << {:columns => Array(columns)}.merge!(opts)
|
|
251
274
|
nil
|
|
@@ -311,6 +334,7 @@ module Sequel
|
|
|
311
334
|
end
|
|
312
335
|
|
|
313
336
|
# Add a spatial index on the given columns.
|
|
337
|
+
# See #index for additional options.
|
|
314
338
|
def spatial_index(columns, opts = OPTS)
|
|
315
339
|
index(columns, opts.merge(:type => :spatial))
|
|
316
340
|
end
|
|
@@ -366,8 +390,7 @@ module Sequel
|
|
|
366
390
|
end
|
|
367
391
|
|
|
368
392
|
# Add a column with the given name, type, and opts.
|
|
369
|
-
# See CreateTableGenerator#column for the available options
|
|
370
|
-
# separate +add_index+ call to add an index for the column).
|
|
393
|
+
# See CreateTableGenerator#column for the available options.
|
|
371
394
|
#
|
|
372
395
|
# add_column(:name, String) # ADD COLUMN name varchar(255)
|
|
373
396
|
#
|
|
@@ -380,7 +403,10 @@ module Sequel
|
|
|
380
403
|
# :after :: The name of an existing column that the new column should be positioned after
|
|
381
404
|
# :first :: Create this new column before all other existing columns
|
|
382
405
|
def add_column(name, type, opts = OPTS)
|
|
383
|
-
|
|
406
|
+
op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
|
|
407
|
+
index_opts = op.delete(:index)
|
|
408
|
+
@operations << op
|
|
409
|
+
add_index(name, index_opts.is_a?(Hash) ? index_opts : OPTS) if index_opts
|
|
384
410
|
nil
|
|
385
411
|
end
|
|
386
412
|
|
|
@@ -409,8 +435,7 @@ module Sequel
|
|
|
409
435
|
end
|
|
410
436
|
|
|
411
437
|
# Add a foreign key with the given name and referencing the given table.
|
|
412
|
-
# See CreateTableGenerator#column for the available options
|
|
413
|
-
# separate +add_index+ call to add an index for the column).
|
|
438
|
+
# See CreateTableGenerator#column for the available options.
|
|
414
439
|
#
|
|
415
440
|
# You can also pass an array of column names for creating composite foreign
|
|
416
441
|
# keys. In this case, it will assume the columns exist and will only add
|
|
@@ -437,7 +462,7 @@ module Sequel
|
|
|
437
462
|
end
|
|
438
463
|
|
|
439
464
|
# Add a full text index on the given columns.
|
|
440
|
-
# See CreateTableGenerator#
|
|
465
|
+
# See CreateTableGenerator#full_text_index for available options.
|
|
441
466
|
def add_full_text_index(columns, opts = OPTS)
|
|
442
467
|
add_index(columns, {:type=>:full_text}.merge!(opts))
|
|
443
468
|
end
|
|
@@ -446,34 +471,6 @@ module Sequel
|
|
|
446
471
|
# CreateTableGenerator#index for available options.
|
|
447
472
|
#
|
|
448
473
|
# add_index(:artist_id) # CREATE INDEX table_artist_id_index ON table (artist_id)
|
|
449
|
-
#
|
|
450
|
-
# Options:
|
|
451
|
-
#
|
|
452
|
-
# :name :: Give a specific name for the index. Highly recommended if you plan on
|
|
453
|
-
# dropping the index later.
|
|
454
|
-
# :where :: A filter expression, used to setup a partial index (if supported).
|
|
455
|
-
# :unique :: Create a unique index.
|
|
456
|
-
#
|
|
457
|
-
# PostgreSQL specific options:
|
|
458
|
-
#
|
|
459
|
-
# :concurrently :: Create the index concurrently, so it doesn't require an exclusive lock
|
|
460
|
-
# on the table.
|
|
461
|
-
# :index_type :: The underlying index type to use for a full_text index, gin by default).
|
|
462
|
-
# :language :: The language to use for a full text index (simple by default).
|
|
463
|
-
# :opclass :: Set an opclass to use for all columns (per-column opclasses require
|
|
464
|
-
# custom SQL).
|
|
465
|
-
# :type :: Set the index type (e.g. full_text, spatial, hash, gin, gist, btree).
|
|
466
|
-
# :if_not_exists :: Only create the index if an index of the same name doesn't already exists
|
|
467
|
-
#
|
|
468
|
-
# MySQL specific options:
|
|
469
|
-
#
|
|
470
|
-
# :type :: Set the index type, with full_text and spatial indexes handled specially.
|
|
471
|
-
#
|
|
472
|
-
# Microsoft SQL Server specific options:
|
|
473
|
-
#
|
|
474
|
-
# :include :: Includes additional columns in the index.
|
|
475
|
-
# :key_index :: Sets the KEY INDEX to the given value.
|
|
476
|
-
# :type :: clustered uses a clustered index, full_text uses a full text index.
|
|
477
474
|
def add_index(columns, opts = OPTS)
|
|
478
475
|
@operations << {:op => :add_index, :columns => Array(columns)}.merge!(opts)
|
|
479
476
|
nil
|
|
@@ -63,7 +63,7 @@ module Sequel
|
|
|
63
63
|
# definitions using <tt>create_table</tt>, and +add_index+ accepts all the options
|
|
64
64
|
# available for index definition.
|
|
65
65
|
#
|
|
66
|
-
# See <tt>Schema::AlterTableGenerator</tt> and the {
|
|
66
|
+
# See <tt>Schema::AlterTableGenerator</tt> and the {Migrations guide}[rdoc-ref:doc/migration.rdoc].
|
|
67
67
|
def alter_table(name, &block)
|
|
68
68
|
generator = alter_table_generator(&block)
|
|
69
69
|
remove_cached_schema(name)
|
|
@@ -183,6 +183,15 @@ module Sequel
|
|
|
183
183
|
# keys.
|
|
184
184
|
# :tablespace :: The tablespace to use for the table.
|
|
185
185
|
#
|
|
186
|
+
# SQLite specific options:
|
|
187
|
+
# :strict :: Create a STRICT table, which checks that the values for the columns
|
|
188
|
+
# are the correct type (similar to all other SQL databases). Note that
|
|
189
|
+
# when using this option, all column types used should be one of the
|
|
190
|
+
# following: +int+, +integer+, +real+, +text+, +blob+, and +any+.
|
|
191
|
+
# The +any+ type is treated like a SQLite column in a non-strict table,
|
|
192
|
+
# allowing any type of data to be stored. This option is supported on
|
|
193
|
+
# SQLite 3.37.0+.
|
|
194
|
+
#
|
|
186
195
|
# See <tt>Schema::CreateTableGenerator</tt> and the {"Schema Modification" guide}[rdoc-ref:doc/schema_modification.rdoc].
|
|
187
196
|
def create_table(name, options=OPTS, &block)
|
|
188
197
|
remove_cached_schema(name)
|
|
@@ -240,7 +249,7 @@ module Sequel
|
|
|
240
249
|
if supports_create_or_replace_view?
|
|
241
250
|
options = options.merge(:replace=>true)
|
|
242
251
|
else
|
|
243
|
-
drop_view(name)
|
|
252
|
+
swallow_database_error{drop_view(name)}
|
|
244
253
|
end
|
|
245
254
|
|
|
246
255
|
create_view(name, source, options)
|
|
@@ -262,6 +271,10 @@ module Sequel
|
|
|
262
271
|
# # SELECT * FROM items WHERE foo
|
|
263
272
|
# # WITH CHECK OPTION
|
|
264
273
|
#
|
|
274
|
+
# DB.create_view(:bar_items, DB[:items].select(:foo), columns: [:bar])
|
|
275
|
+
# # CREATE VIEW bar_items (bar) AS
|
|
276
|
+
# # SELECT foo FROM items
|
|
277
|
+
#
|
|
265
278
|
# Options:
|
|
266
279
|
# :columns :: The column names to use for the view. If not given,
|
|
267
280
|
# automatically determined based on the input dataset.
|
|
@@ -494,7 +507,9 @@ module Sequel
|
|
|
494
507
|
when :drop_index
|
|
495
508
|
drop_index_sql(table, op)
|
|
496
509
|
else
|
|
497
|
-
|
|
510
|
+
if sql = alter_table_op_sql(table, op)
|
|
511
|
+
"ALTER TABLE #{quote_schema_table(table)} #{sql}"
|
|
512
|
+
end
|
|
498
513
|
end
|
|
499
514
|
end
|
|
500
515
|
|
|
@@ -578,14 +593,14 @@ module Sequel
|
|
|
578
593
|
sql << ' NULL'
|
|
579
594
|
end
|
|
580
595
|
end
|
|
581
|
-
|
|
596
|
+
|
|
582
597
|
# Add primary key SQL fragment to column creation SQL.
|
|
583
598
|
def column_definition_primary_key_sql(sql, column)
|
|
584
599
|
if column[:primary_key]
|
|
585
600
|
if name = column[:primary_key_constraint_name]
|
|
586
601
|
sql << " CONSTRAINT #{quote_identifier(name)}"
|
|
587
602
|
end
|
|
588
|
-
sql <<
|
|
603
|
+
sql << " " << primary_key_constraint_sql_fragment(column)
|
|
589
604
|
constraint_deferrable_sql_append(sql, column[:primary_key_deferrable])
|
|
590
605
|
end
|
|
591
606
|
end
|
|
@@ -606,7 +621,7 @@ module Sequel
|
|
|
606
621
|
if name = column[:unique_constraint_name]
|
|
607
622
|
sql << " CONSTRAINT #{quote_identifier(name)}"
|
|
608
623
|
end
|
|
609
|
-
sql << '
|
|
624
|
+
sql << ' ' << unique_constraint_sql_fragment(column)
|
|
610
625
|
constraint_deferrable_sql_append(sql, column[:unique_deferrable])
|
|
611
626
|
end
|
|
612
627
|
end
|
|
@@ -654,11 +669,11 @@ module Sequel
|
|
|
654
669
|
check = "(#{check})" unless check[0..0] == '(' && check[-1..-1] == ')'
|
|
655
670
|
sql << "CHECK #{check}"
|
|
656
671
|
when :primary_key
|
|
657
|
-
sql << "
|
|
672
|
+
sql << "#{primary_key_constraint_sql_fragment(constraint)} #{literal(constraint[:columns])}"
|
|
658
673
|
when :foreign_key
|
|
659
674
|
sql << column_references_table_constraint_sql(constraint.merge(:deferrable=>nil))
|
|
660
675
|
when :unique
|
|
661
|
-
sql << "
|
|
676
|
+
sql << "#{unique_constraint_sql_fragment(constraint)} #{literal(constraint[:columns])}"
|
|
662
677
|
else
|
|
663
678
|
raise Error, "Invalid constraint type #{constraint[:type]}, should be :check, :primary_key, :foreign_key, or :unique"
|
|
664
679
|
end
|
|
@@ -811,23 +826,20 @@ module Sequel
|
|
|
811
826
|
# Proxy the filter_expr call to the dataset, used for creating constraints.
|
|
812
827
|
# Support passing Proc arguments as blocks, as well as treating plain strings
|
|
813
828
|
# as literal strings, so that previous migrations that used this API do not break.
|
|
814
|
-
def filter_expr(
|
|
815
|
-
if
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
elsif arg.length > 1
|
|
826
|
-
args = [Sequel.&(*arg)]
|
|
827
|
-
end
|
|
829
|
+
def filter_expr(arg=nil, &block)
|
|
830
|
+
if arg.is_a?(Proc) && !block
|
|
831
|
+
block = arg
|
|
832
|
+
arg = nil
|
|
833
|
+
elsif arg.is_a?(String)
|
|
834
|
+
arg = Sequel.lit(arg)
|
|
835
|
+
elsif arg.is_a?(Array)
|
|
836
|
+
if arg.first.is_a?(String)
|
|
837
|
+
arg = Sequel.lit(*arg)
|
|
838
|
+
elsif arg.length > 1
|
|
839
|
+
arg = Sequel.&(*arg)
|
|
828
840
|
end
|
|
829
841
|
end
|
|
830
|
-
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr,
|
|
842
|
+
schema_utility_dataset.literal(schema_utility_dataset.send(:filter_expr, arg, &block))
|
|
831
843
|
end
|
|
832
844
|
|
|
833
845
|
# SQL statement for creating an index for the table with the given name
|
|
@@ -893,6 +905,11 @@ module Sequel
|
|
|
893
905
|
on_delete_clause(action)
|
|
894
906
|
end
|
|
895
907
|
|
|
908
|
+
# Add fragment for primary key specification, separated for easier overridding.
|
|
909
|
+
def primary_key_constraint_sql_fragment(_)
|
|
910
|
+
'PRIMARY KEY'
|
|
911
|
+
end
|
|
912
|
+
|
|
896
913
|
# Proxy the quote_schema_table method to the dataset
|
|
897
914
|
def quote_schema_table(table)
|
|
898
915
|
schema_utility_dataset.quote_schema_table(table)
|
|
@@ -1048,6 +1065,11 @@ module Sequel
|
|
|
1048
1065
|
"#{type}#{literal(Array(elements)) if elements}#{' UNSIGNED' if column[:unsigned]}"
|
|
1049
1066
|
end
|
|
1050
1067
|
|
|
1068
|
+
# Add fragment for unique specification, separated for easier overridding.
|
|
1069
|
+
def unique_constraint_sql_fragment(_)
|
|
1070
|
+
'UNIQUE'
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1051
1073
|
# Whether clob should be used for String text: true columns.
|
|
1052
1074
|
def uses_clob_for_text?
|
|
1053
1075
|
false
|
|
@@ -82,7 +82,7 @@ module Sequel
|
|
|
82
82
|
# :server :: The server/shard the transaction is being executed on.
|
|
83
83
|
def rollback_on_exit(opts=OPTS)
|
|
84
84
|
synchronize(opts[:server]) do |conn|
|
|
85
|
-
raise Error, "Cannot call Sequel:: Database#rollback_on_exit
|
|
85
|
+
raise Error, "Cannot call Sequel:: Database#rollback_on_exit unless inside a transaction" unless h = _trans(conn)
|
|
86
86
|
rollback = !opts[:cancel]
|
|
87
87
|
|
|
88
88
|
if supports_savepoints?
|
|
@@ -154,7 +154,7 @@ module Sequel
|
|
|
154
154
|
# Note that this should not be used unless the entire transaction
|
|
155
155
|
# block is idempotent, as otherwise it can cause non-idempotent
|
|
156
156
|
# behavior to execute multiple times.
|
|
157
|
-
# :rollback :: Can
|
|
157
|
+
# :rollback :: Can be set to :reraise to reraise any Sequel::Rollback exceptions
|
|
158
158
|
# raised, or :always to always rollback even if no exceptions occur
|
|
159
159
|
# (useful for testing).
|
|
160
160
|
# :server :: The server to use for the transaction. Set to :default, :read_only, or
|
|
@@ -205,6 +205,10 @@ module Sequel
|
|
|
205
205
|
end
|
|
206
206
|
end
|
|
207
207
|
|
|
208
|
+
if opts[:savepoint] && !supports_savepoints?
|
|
209
|
+
raise Sequel::InvalidOperation, "savepoints not supported on #{database_type}"
|
|
210
|
+
end
|
|
211
|
+
|
|
208
212
|
if already_in_transaction?(conn, opts)
|
|
209
213
|
if opts[:rollback] == :always && !opts.has_key?(:savepoint)
|
|
210
214
|
if supports_savepoints?
|
|
@@ -418,11 +422,10 @@ module Sequel
|
|
|
418
422
|
end
|
|
419
423
|
|
|
420
424
|
# Retrieve the savepoint hooks that should be run for the given
|
|
421
|
-
# connection and commit status.
|
|
425
|
+
# connection and commit status. This expacts that you are
|
|
426
|
+
# already inside a savepoint when calling.
|
|
422
427
|
def savepoint_hooks(conn, committed)
|
|
423
|
-
|
|
424
|
-
_trans(conn)[:savepoints].last[committed ? :after_commit : :after_rollback]
|
|
425
|
-
end
|
|
428
|
+
_trans(conn)[:savepoints].last[committed ? :after_commit : :after_rollback]
|
|
426
429
|
end
|
|
427
430
|
|
|
428
431
|
# Retrieve the transaction hooks that should be run for the given
|
|
@@ -19,7 +19,7 @@ module Sequel
|
|
|
19
19
|
METHS
|
|
20
20
|
|
|
21
21
|
# The clone options to use when retrieving columns for a dataset.
|
|
22
|
-
COLUMNS_CLONE_OPTIONS = {:distinct => nil, :limit =>
|
|
22
|
+
COLUMNS_CLONE_OPTIONS = {:distinct => nil, :limit => 0, :offset=>nil, :where=>nil, :having=>nil, :order=>nil, :row_proc=>nil, :graph=>nil, :eager_graph=>nil}.freeze
|
|
23
23
|
|
|
24
24
|
# Inserts the given argument into the database. Returns self so it
|
|
25
25
|
# can be used safely when chaining:
|
|
@@ -457,6 +457,55 @@ module Sequel
|
|
|
457
457
|
_aggregate(:max, arg)
|
|
458
458
|
end
|
|
459
459
|
|
|
460
|
+
# Execute a MERGE statement, which allows for INSERT, UPDATE, and DELETE
|
|
461
|
+
# behavior in a single query, based on whether rows from a source table
|
|
462
|
+
# match rows in the current table, based on the join conditions.
|
|
463
|
+
#
|
|
464
|
+
# Unless the dataset uses static SQL, to use #merge, you must first have
|
|
465
|
+
# called #merge_using to specify the merge source and join conditions.
|
|
466
|
+
# You will then likely to call one or more of the following methods
|
|
467
|
+
# to specify MERGE behavior by adding WHEN [NOT] MATCHED clauses:
|
|
468
|
+
#
|
|
469
|
+
# * #merge_insert
|
|
470
|
+
# * #merge_update
|
|
471
|
+
# * #merge_delete
|
|
472
|
+
#
|
|
473
|
+
# The WHEN [NOT] MATCHED clauses are added to the SQL in the order these
|
|
474
|
+
# methods were called on the dataset. If none of these methods are
|
|
475
|
+
# called, an error is raised.
|
|
476
|
+
#
|
|
477
|
+
# Example:
|
|
478
|
+
#
|
|
479
|
+
# DB[:m1]
|
|
480
|
+
# merge_using(:m2, i1: :i2).
|
|
481
|
+
# merge_insert(i1: :i2, a: Sequel[:b]+11).
|
|
482
|
+
# merge_delete{a > 30}.
|
|
483
|
+
# merge_update(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20).
|
|
484
|
+
# merge
|
|
485
|
+
#
|
|
486
|
+
# SQL:
|
|
487
|
+
#
|
|
488
|
+
# MERGE INTO m1 USING m2 ON (i1 = i2)
|
|
489
|
+
# WHEN NOT MATCHED THEN INSERT (i1, a) VALUES (i2, (b + 11))
|
|
490
|
+
# WHEN MATCHED AND (a > 30) THEN DELETE
|
|
491
|
+
# WHEN MATCHED THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
|
492
|
+
#
|
|
493
|
+
# On PostgreSQL, two additional merge methods are supported, for the
|
|
494
|
+
# PostgreSQL-specific DO NOTHING syntax.
|
|
495
|
+
#
|
|
496
|
+
# * #merge_do_nothing_when_matched
|
|
497
|
+
# * #merge_do_nothing_when_not_matched
|
|
498
|
+
#
|
|
499
|
+
# This method is supported on Oracle, but Oracle's MERGE support is
|
|
500
|
+
# non-standard, and has the following issues:
|
|
501
|
+
#
|
|
502
|
+
# * DELETE clause requires UPDATE clause
|
|
503
|
+
# * DELETE clause requires a condition
|
|
504
|
+
# * DELETE clause only affects rows updated by UPDATE clause
|
|
505
|
+
def merge
|
|
506
|
+
execute_ddl(merge_sql)
|
|
507
|
+
end
|
|
508
|
+
|
|
460
509
|
# Returns the minimum value for the given column/expression.
|
|
461
510
|
# Uses a virtual row block if no argument is given.
|
|
462
511
|
#
|
|
@@ -546,7 +595,7 @@ module Sequel
|
|
|
546
595
|
unless @opts[:order]
|
|
547
596
|
raise Sequel::Error, "Dataset#paged_each requires the dataset be ordered"
|
|
548
597
|
end
|
|
549
|
-
unless
|
|
598
|
+
unless defined?(yield)
|
|
550
599
|
return enum_for(:paged_each, opts)
|
|
551
600
|
end
|
|
552
601
|
|
|
@@ -607,14 +656,16 @@ module Sequel
|
|
|
607
656
|
# as_hash, it accepts an optional :hash parameter, into which entries will
|
|
608
657
|
# be merged.
|
|
609
658
|
#
|
|
610
|
-
# DB[:table].select_hash(:id, :name)
|
|
659
|
+
# DB[:table].select_hash(:id, :name)
|
|
660
|
+
# # SELECT id, name FROM table
|
|
611
661
|
# # => {1=>'a', 2=>'b', ...}
|
|
612
662
|
#
|
|
613
663
|
# You can also provide an array of column names for either the key_column,
|
|
614
664
|
# the value column, or both:
|
|
615
665
|
#
|
|
616
|
-
# DB[:table].select_hash([:id, :foo], [:name, :bar])
|
|
617
|
-
# #
|
|
666
|
+
# DB[:table].select_hash([:id, :foo], [:name, :bar])
|
|
667
|
+
# # SELECT id, foo, name, bar FROM table
|
|
668
|
+
# # => {[1, 3]=>['a', 'c'], [2, 4]=>['b', 'd'], ...}
|
|
618
669
|
#
|
|
619
670
|
# When using this method, you must be sure that each expression has an alias
|
|
620
671
|
# that Sequel can determine.
|
|
@@ -626,14 +677,16 @@ module Sequel
|
|
|
626
677
|
# Similar to to_hash_groups, but only selects the columns given. Like to_hash_groups,
|
|
627
678
|
# it accepts an optional :hash parameter, into which entries will be merged.
|
|
628
679
|
#
|
|
629
|
-
# DB[:table].select_hash_groups(:name, :id)
|
|
680
|
+
# DB[:table].select_hash_groups(:name, :id)
|
|
681
|
+
# # SELECT id, name FROM table
|
|
630
682
|
# # => {'a'=>[1, 4, ...], 'b'=>[2, ...], ...}
|
|
631
683
|
#
|
|
632
684
|
# You can also provide an array of column names for either the key_column,
|
|
633
685
|
# the value column, or both:
|
|
634
686
|
#
|
|
635
|
-
# DB[:table].select_hash_groups([:first, :middle], [:last, :id])
|
|
636
|
-
# #
|
|
687
|
+
# DB[:table].select_hash_groups([:first, :middle], [:last, :id])
|
|
688
|
+
# # SELECT first, middle, last, id FROM table
|
|
689
|
+
# # => {['a', 'b']=>[['c', 1], ['d', 2], ...], ...}
|
|
637
690
|
#
|
|
638
691
|
# When using this method, you must be sure that each expression has an alias
|
|
639
692
|
# that Sequel can determine.
|
|
@@ -51,6 +51,11 @@ module Sequel
|
|
|
51
51
|
false
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
# Whether deleting from joined datasets is supported, false by default.
|
|
55
|
+
def supports_deleting_joins?
|
|
56
|
+
supports_modifying_joins?
|
|
57
|
+
end
|
|
58
|
+
|
|
54
59
|
# Whether the database supports derived column lists (e.g.
|
|
55
60
|
# "table_expr AS table_alias(column_alias1, column_alias2, ...)"), true by
|
|
56
61
|
# default.
|
|
@@ -120,6 +125,11 @@ module Sequel
|
|
|
120
125
|
false
|
|
121
126
|
end
|
|
122
127
|
|
|
128
|
+
# Whether the MERGE statement is supported, false by default.
|
|
129
|
+
def supports_merge?
|
|
130
|
+
false
|
|
131
|
+
end
|
|
132
|
+
|
|
123
133
|
# Whether modifying joined datasets is supported, false by default.
|
|
124
134
|
def supports_modifying_joins?
|
|
125
135
|
false
|
|
@@ -178,6 +188,11 @@ module Sequel
|
|
|
178
188
|
true
|
|
179
189
|
end
|
|
180
190
|
|
|
191
|
+
# Whether updating joined datasets is supported, false by default.
|
|
192
|
+
def supports_updating_joins?
|
|
193
|
+
supports_modifying_joins?
|
|
194
|
+
end
|
|
195
|
+
|
|
181
196
|
# Whether the dataset supports the WINDOW clause to define windows used by multiple
|
|
182
197
|
# window functions, false by default.
|
|
183
198
|
def supports_window_clause?
|
|
@@ -114,10 +114,8 @@ module Sequel
|
|
|
114
114
|
prepared_sql << sql
|
|
115
115
|
prepared_sql << "$#{prepared_args[i]}"
|
|
116
116
|
end
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
prepared_sql << final_sql
|
|
120
|
-
end
|
|
117
|
+
frags << final_sql
|
|
118
|
+
prepared_sql << final_sql
|
|
121
119
|
|
|
122
120
|
[prepared_sql, frags]
|
|
123
121
|
end
|
|
@@ -213,9 +211,7 @@ module Sequel
|
|
|
213
211
|
end
|
|
214
212
|
ds.literal_append(s, v)
|
|
215
213
|
end
|
|
216
|
-
|
|
217
|
-
s << sql
|
|
218
|
-
end
|
|
214
|
+
s << @final_sql
|
|
219
215
|
s
|
|
220
216
|
end
|
|
221
217
|
end
|
|
@@ -201,7 +201,9 @@ module Sequel
|
|
|
201
201
|
when :insert_pk
|
|
202
202
|
fetch_rows(prepared_sql){|r| return r.values.first}
|
|
203
203
|
when Array
|
|
204
|
+
# :nocov:
|
|
204
205
|
case prepared_type[0]
|
|
206
|
+
# :nocov:
|
|
205
207
|
when :map, :as_hash, :to_hash, :to_hash_groups
|
|
206
208
|
public_send(*prepared_type, &block)
|
|
207
209
|
end
|