sequel 5.39.0 → 5.63.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 +308 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +57 -25
- data/bin/sequel +11 -3
- data/doc/advanced_associations.rdoc +13 -13
- data/doc/association_basics.rdoc +89 -24
- data/doc/cheat_sheet.rdoc +11 -3
- data/doc/migration.rdoc +12 -6
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +18 -11
- data/doc/postgresql.rdoc +16 -8
- data/doc/querying.rdoc +5 -3
- 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/release_notes/5.59.0.txt +73 -0
- data/doc/release_notes/5.60.0.txt +22 -0
- data/doc/release_notes/5.61.0.txt +43 -0
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/release_notes/5.63.0.txt +33 -0
- data/doc/schema_modification.rdoc +1 -1
- data/doc/security.rdoc +9 -9
- data/doc/sql.rdoc +27 -15
- data/doc/testing.rdoc +22 -11
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +2 -2
- 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/postgresql.rb +4 -4
- data/lib/sequel/adapters/jdbc.rb +16 -18
- data/lib/sequel/adapters/mysql.rb +80 -67
- data/lib/sequel/adapters/mysql2.rb +54 -49
- data/lib/sequel/adapters/odbc.rb +6 -2
- data/lib/sequel/adapters/oracle.rb +3 -3
- data/lib/sequel/adapters/postgres.rb +83 -40
- data/lib/sequel/adapters/shared/access.rb +11 -1
- data/lib/sequel/adapters/shared/db2.rb +30 -0
- data/lib/sequel/adapters/shared/mssql.rb +58 -7
- data/lib/sequel/adapters/shared/mysql.rb +40 -2
- data/lib/sequel/adapters/shared/oracle.rb +76 -0
- data/lib/sequel/adapters/shared/postgres.rb +418 -174
- data/lib/sequel/adapters/shared/sqlanywhere.rb +10 -0
- data/lib/sequel/adapters/shared/sqlite.rb +102 -11
- data/lib/sequel/adapters/sqlanywhere.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +60 -18
- data/lib/sequel/adapters/tinytds.rb +1 -1
- data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
- data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
- data/lib/sequel/ast_transformer.rb +6 -0
- data/lib/sequel/connection_pool/sharded_single.rb +5 -7
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -1
- data/lib/sequel/connection_pool/single.rb +6 -8
- data/lib/sequel/connection_pool/threaded.rb +8 -8
- data/lib/sequel/connection_pool/timed_queue.rb +257 -0
- data/lib/sequel/connection_pool.rb +47 -30
- data/lib/sequel/core.rb +28 -18
- data/lib/sequel/database/connecting.rb +26 -2
- data/lib/sequel/database/misc.rb +69 -14
- data/lib/sequel/database/query.rb +38 -1
- data/lib/sequel/database/schema_generator.rb +45 -52
- data/lib/sequel/database/schema_methods.rb +17 -1
- data/lib/sequel/dataset/actions.rb +107 -13
- data/lib/sequel/dataset/features.rb +20 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/prepared_statements.rb +2 -0
- data/lib/sequel/dataset/query.rb +118 -16
- data/lib/sequel/dataset/sql.rb +177 -47
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/any_not_empty.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +438 -0
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/blank.rb +8 -0
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/core_refinements.rb +36 -11
- data/lib/sequel/extensions/date_arithmetic.rb +71 -31
- 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 +1 -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 +141 -0
- data/lib/sequel/extensions/looser_typecasting.rb +3 -0
- data/lib/sequel/extensions/migration.rb +7 -2
- data/lib/sequel/extensions/named_timezones.rb +26 -6
- data/lib/sequel/extensions/pagination.rb +1 -1
- data/lib/sequel/extensions/pg_array.rb +23 -3
- data/lib/sequel/extensions/pg_array_ops.rb +2 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +478 -0
- data/lib/sequel/extensions/pg_enum.rb +1 -1
- data/lib/sequel/extensions/pg_extended_date_support.rb +28 -25
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +6 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +53 -3
- data/lib/sequel/extensions/pg_inet.rb +10 -11
- data/lib/sequel/extensions/pg_inet_ops.rb +1 -1
- data/lib/sequel/extensions/pg_interval.rb +45 -19
- data/lib/sequel/extensions/pg_json.rb +13 -15
- data/lib/sequel/extensions/pg_json_ops.rb +73 -2
- data/lib/sequel/extensions/pg_loose_count.rb +3 -1
- data/lib/sequel/extensions/pg_multirange.rb +367 -0
- data/lib/sequel/extensions/pg_range.rb +10 -23
- data/lib/sequel/extensions/pg_range_ops.rb +37 -9
- data/lib/sequel/extensions/pg_row.rb +19 -13
- data/lib/sequel/extensions/pg_row_ops.rb +1 -1
- data/lib/sequel/extensions/query.rb +2 -0
- data/lib/sequel/extensions/s.rb +2 -1
- data/lib/sequel/extensions/schema_dumper.rb +13 -2
- 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.rb +2 -0
- data/lib/sequel/model/associations.rb +325 -96
- data/lib/sequel/model/base.rb +51 -27
- data/lib/sequel/model/errors.rb +10 -1
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model/plugins.rb +5 -0
- data/lib/sequel/plugins/association_proxies.rb +2 -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 +87 -15
- data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/column_encryption.rb +728 -0
- data/lib/sequel/plugins/composition.rb +10 -4
- data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
- data/lib/sequel/plugins/constraint_validations.rb +2 -1
- data/lib/sequel/plugins/dataset_associations.rb +4 -1
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/enum.rb +124 -0
- data/lib/sequel/plugins/finder.rb +3 -1
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/instance_specific_default.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +39 -24
- data/lib/sequel/plugins/lazy_attributes.rb +3 -0
- data/lib/sequel/plugins/list.rb +3 -1
- data/lib/sequel/plugins/many_through_many.rb +108 -9
- data/lib/sequel/plugins/nested_attributes.rb +12 -7
- data/lib/sequel/plugins/pg_array_associations.rb +56 -38
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +3 -1
- data/lib/sequel/plugins/prepared_statements.rb +10 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/rcte_tree.rb +27 -19
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- 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 +8 -0
- data/lib/sequel/plugins/sql_comments.rb +189 -0
- data/lib/sequel/plugins/static_cache.rb +1 -1
- data/lib/sequel/plugins/subclasses.rb +28 -11
- data/lib/sequel/plugins/tactical_eager_loading.rb +23 -10
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/unused_associations.rb +521 -0
- data/lib/sequel/plugins/update_or_create.rb +1 -1
- data/lib/sequel/plugins/validate_associated.rb +22 -12
- data/lib/sequel/plugins/validation_helpers.rb +38 -11
- data/lib/sequel/plugins/xml_serializer.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/timezones.rb +12 -14
- data/lib/sequel/version.rb +1 -1
- metadata +97 -43
|
@@ -175,6 +175,9 @@ module Sequel
|
|
|
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
|
|
177
177
|
end
|
|
178
|
+
if !c[:max_value] && !c[:min_value] && c[:type] == :integer && (min_max = column_schema_integer_min_max_values(c[:db_type]))
|
|
179
|
+
c[:min_value], c[:max_value] = min_max
|
|
180
|
+
end
|
|
178
181
|
end
|
|
179
182
|
schema_post_process(cols)
|
|
180
183
|
|
|
@@ -236,7 +239,7 @@ module Sequel
|
|
|
236
239
|
when :date
|
|
237
240
|
Sequel.string_to_date(default)
|
|
238
241
|
when :datetime
|
|
239
|
-
|
|
242
|
+
Sequel.string_to_datetime(default)
|
|
240
243
|
when :time
|
|
241
244
|
Sequel.string_to_time(default)
|
|
242
245
|
when :decimal
|
|
@@ -272,6 +275,40 @@ module Sequel
|
|
|
272
275
|
column_schema_default_to_ruby_value(default, type) rescue nil
|
|
273
276
|
end
|
|
274
277
|
|
|
278
|
+
INTEGER1_MIN_MAX = [-128, 127].freeze
|
|
279
|
+
INTEGER2_MIN_MAX = [-32768, 32767].freeze
|
|
280
|
+
INTEGER3_MIN_MAX = [-8388608, 8388607].freeze
|
|
281
|
+
INTEGER4_MIN_MAX = [-2147483648, 2147483647].freeze
|
|
282
|
+
INTEGER8_MIN_MAX = [-9223372036854775808, 9223372036854775807].freeze
|
|
283
|
+
UNSIGNED_INTEGER1_MIN_MAX = [0, 255].freeze
|
|
284
|
+
UNSIGNED_INTEGER2_MIN_MAX = [0, 65535].freeze
|
|
285
|
+
UNSIGNED_INTEGER3_MIN_MAX = [0, 16777215].freeze
|
|
286
|
+
UNSIGNED_INTEGER4_MIN_MAX = [0, 4294967295].freeze
|
|
287
|
+
UNSIGNED_INTEGER8_MIN_MAX = [0, 18446744073709551615].freeze
|
|
288
|
+
|
|
289
|
+
# Look at the db_type and guess the minimum and maximum integer values for
|
|
290
|
+
# the column.
|
|
291
|
+
def column_schema_integer_min_max_values(db_type)
|
|
292
|
+
unsigned = /unsigned/i =~ db_type
|
|
293
|
+
case db_type
|
|
294
|
+
when /big|int8/i
|
|
295
|
+
unsigned ? UNSIGNED_INTEGER8_MIN_MAX : INTEGER8_MIN_MAX
|
|
296
|
+
when /medium/i
|
|
297
|
+
unsigned ? UNSIGNED_INTEGER3_MIN_MAX : INTEGER3_MIN_MAX
|
|
298
|
+
when /small|int2/i
|
|
299
|
+
unsigned ? UNSIGNED_INTEGER2_MIN_MAX : INTEGER2_MIN_MAX
|
|
300
|
+
when /tiny/i
|
|
301
|
+
(unsigned || column_schema_tinyint_type_is_unsigned?) ? UNSIGNED_INTEGER1_MIN_MAX : INTEGER1_MIN_MAX
|
|
302
|
+
else
|
|
303
|
+
unsigned ? UNSIGNED_INTEGER4_MIN_MAX : INTEGER4_MIN_MAX
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
# Whether the tinyint type (if supported by the database) is unsigned by default.
|
|
308
|
+
def column_schema_tinyint_type_is_unsigned?
|
|
309
|
+
false
|
|
310
|
+
end
|
|
311
|
+
|
|
275
312
|
# Look at the db_type and guess the maximum length of the column.
|
|
276
313
|
# This assumes types such as varchar(255).
|
|
277
314
|
def column_schema_max_length(db_type)
|
|
@@ -146,6 +146,9 @@ module Sequel
|
|
|
146
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.
|
|
149
152
|
#
|
|
150
153
|
# Microsoft SQL Server specific options:
|
|
151
154
|
#
|
|
@@ -159,7 +162,7 @@ module Sequel
|
|
|
159
162
|
nil
|
|
160
163
|
end
|
|
161
164
|
|
|
162
|
-
# Adds a named constraint (or unnamed if name is nil),
|
|
165
|
+
# Adds a named CHECK constraint (or unnamed if name is nil),
|
|
163
166
|
# with the given block or args. To provide options for the constraint, pass
|
|
164
167
|
# a hash as the first argument.
|
|
165
168
|
#
|
|
@@ -167,6 +170,15 @@ module Sequel
|
|
|
167
170
|
# # CONSTRAINT blah CHECK num >= 1 AND num <= 5
|
|
168
171
|
# constraint({name: :blah, deferrable: true}, num: 1..5)
|
|
169
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.
|
|
170
182
|
def constraint(name, *args, &block)
|
|
171
183
|
opts = name.is_a?(Hash) ? name : {:name=>name}
|
|
172
184
|
constraints << opts.merge(:type=>:check, :check=>block || args)
|
|
@@ -205,14 +217,12 @@ module Sequel
|
|
|
205
217
|
end
|
|
206
218
|
|
|
207
219
|
# Add a full text index on the given columns.
|
|
220
|
+
# See #index for additional options.
|
|
208
221
|
#
|
|
209
222
|
# PostgreSQL specific options:
|
|
210
223
|
# :index_type :: Can be set to :gist to use a GIST index instead of the
|
|
211
224
|
# default GIN index.
|
|
212
225
|
# :language :: Set a language to use for the index (default: simple).
|
|
213
|
-
#
|
|
214
|
-
# Microsoft SQL Server specific options:
|
|
215
|
-
# :key_index :: The KEY INDEX to use for the full text index.
|
|
216
226
|
def full_text_index(columns, opts = OPTS)
|
|
217
227
|
index(columns, opts.merge(:type => :full_text))
|
|
218
228
|
end
|
|
@@ -222,35 +232,44 @@ module Sequel
|
|
|
222
232
|
columns.any?{|c| c[:name] == name}
|
|
223
233
|
end
|
|
224
234
|
|
|
225
|
-
# 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
|
+
#
|
|
226
246
|
# General options:
|
|
227
247
|
#
|
|
248
|
+
# :include :: Include additional column values in the index, without
|
|
249
|
+
# actually indexing on those values (only supported by
|
|
250
|
+
# some databases).
|
|
228
251
|
# :name :: The name to use for the index. If not given, a default name
|
|
229
252
|
# based on the table and columns is used.
|
|
230
|
-
# :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).
|
|
231
255
|
# :unique :: Make the index unique, so duplicate values are not allowed.
|
|
232
|
-
# :where ::
|
|
256
|
+
# :where :: A filter expression, used to create a partial index (only
|
|
257
|
+
# supported by some databases).
|
|
233
258
|
#
|
|
234
259
|
# PostgreSQL specific options:
|
|
235
260
|
#
|
|
236
261
|
# :concurrently :: Create the index concurrently, so it doesn't block
|
|
237
262
|
# operations on the table while the index is being
|
|
238
263
|
# built.
|
|
239
|
-
# :
|
|
240
|
-
# :
|
|
241
|
-
#
|
|
264
|
+
# :if_not_exists :: Only create the index if an index of the same name doesn't already exist.
|
|
265
|
+
# :nulls_distinct :: Set whether separate NULLs should be considered distinct values in unique indexes.
|
|
266
|
+
# :opclass :: Set an opclass to use for all columns (per-column opclasses require
|
|
267
|
+
# custom SQL).
|
|
242
268
|
# :tablespace :: Specify tablespace for index.
|
|
243
269
|
#
|
|
244
270
|
# Microsoft SQL Server specific options:
|
|
245
271
|
#
|
|
246
|
-
# :
|
|
247
|
-
# actually indexing on those values.
|
|
248
|
-
#
|
|
249
|
-
# index :name
|
|
250
|
-
# # CREATE INDEX table_name_index ON table (name)
|
|
251
|
-
#
|
|
252
|
-
# index [:artist_id, :name]
|
|
253
|
-
# # CREATE INDEX table_artist_id_name_index ON table (artist_id, name)
|
|
272
|
+
# :key_index :: Sets the KEY INDEX to the given value.
|
|
254
273
|
def index(columns, opts = OPTS)
|
|
255
274
|
indexes << {:columns => Array(columns)}.merge!(opts)
|
|
256
275
|
nil
|
|
@@ -316,6 +335,7 @@ module Sequel
|
|
|
316
335
|
end
|
|
317
336
|
|
|
318
337
|
# Add a spatial index on the given columns.
|
|
338
|
+
# See #index for additional options.
|
|
319
339
|
def spatial_index(columns, opts = OPTS)
|
|
320
340
|
index(columns, opts.merge(:type => :spatial))
|
|
321
341
|
end
|
|
@@ -371,8 +391,7 @@ module Sequel
|
|
|
371
391
|
end
|
|
372
392
|
|
|
373
393
|
# Add a column with the given name, type, and opts.
|
|
374
|
-
# See CreateTableGenerator#column for the available options
|
|
375
|
-
# separate +add_index+ call to add an index for the column).
|
|
394
|
+
# See CreateTableGenerator#column for the available options.
|
|
376
395
|
#
|
|
377
396
|
# add_column(:name, String) # ADD COLUMN name varchar(255)
|
|
378
397
|
#
|
|
@@ -385,7 +404,10 @@ module Sequel
|
|
|
385
404
|
# :after :: The name of an existing column that the new column should be positioned after
|
|
386
405
|
# :first :: Create this new column before all other existing columns
|
|
387
406
|
def add_column(name, type, opts = OPTS)
|
|
388
|
-
|
|
407
|
+
op = {:op => :add_column, :name => name, :type => type}.merge!(opts)
|
|
408
|
+
index_opts = op.delete(:index)
|
|
409
|
+
@operations << op
|
|
410
|
+
add_index(name, index_opts.is_a?(Hash) ? index_opts : OPTS) if index_opts
|
|
389
411
|
nil
|
|
390
412
|
end
|
|
391
413
|
|
|
@@ -414,8 +436,7 @@ module Sequel
|
|
|
414
436
|
end
|
|
415
437
|
|
|
416
438
|
# Add a foreign key with the given name and referencing the given table.
|
|
417
|
-
# See CreateTableGenerator#column for the available options
|
|
418
|
-
# separate +add_index+ call to add an index for the column).
|
|
439
|
+
# See CreateTableGenerator#column for the available options.
|
|
419
440
|
#
|
|
420
441
|
# You can also pass an array of column names for creating composite foreign
|
|
421
442
|
# keys. In this case, it will assume the columns exist and will only add
|
|
@@ -442,7 +463,7 @@ module Sequel
|
|
|
442
463
|
end
|
|
443
464
|
|
|
444
465
|
# Add a full text index on the given columns.
|
|
445
|
-
# See CreateTableGenerator#
|
|
466
|
+
# See CreateTableGenerator#full_text_index for available options.
|
|
446
467
|
def add_full_text_index(columns, opts = OPTS)
|
|
447
468
|
add_index(columns, {:type=>:full_text}.merge!(opts))
|
|
448
469
|
end
|
|
@@ -451,34 +472,6 @@ module Sequel
|
|
|
451
472
|
# CreateTableGenerator#index for available options.
|
|
452
473
|
#
|
|
453
474
|
# add_index(:artist_id) # CREATE INDEX table_artist_id_index ON table (artist_id)
|
|
454
|
-
#
|
|
455
|
-
# Options:
|
|
456
|
-
#
|
|
457
|
-
# :name :: Give a specific name for the index. Highly recommended if you plan on
|
|
458
|
-
# dropping the index later.
|
|
459
|
-
# :where :: A filter expression, used to setup a partial index (if supported).
|
|
460
|
-
# :unique :: Create a unique index.
|
|
461
|
-
#
|
|
462
|
-
# PostgreSQL specific options:
|
|
463
|
-
#
|
|
464
|
-
# :concurrently :: Create the index concurrently, so it doesn't require an exclusive lock
|
|
465
|
-
# on the table.
|
|
466
|
-
# :index_type :: The underlying index type to use for a full_text index, gin by default).
|
|
467
|
-
# :language :: The language to use for a full text index (simple by default).
|
|
468
|
-
# :opclass :: Set an opclass to use for all columns (per-column opclasses require
|
|
469
|
-
# custom SQL).
|
|
470
|
-
# :type :: Set the index type (e.g. full_text, spatial, hash, gin, gist, btree).
|
|
471
|
-
# :if_not_exists :: Only create the index if an index of the same name doesn't already exists
|
|
472
|
-
#
|
|
473
|
-
# MySQL specific options:
|
|
474
|
-
#
|
|
475
|
-
# :type :: Set the index type, with full_text and spatial indexes handled specially.
|
|
476
|
-
#
|
|
477
|
-
# Microsoft SQL Server specific options:
|
|
478
|
-
#
|
|
479
|
-
# :include :: Includes additional columns in the index.
|
|
480
|
-
# :key_index :: Sets the KEY INDEX to the given value.
|
|
481
|
-
# :type :: clustered uses a clustered index, full_text uses a full text index.
|
|
482
475
|
def add_index(columns, opts = OPTS)
|
|
483
476
|
@operations << {:op => :add_index, :columns => Array(columns)}.merge!(opts)
|
|
484
477
|
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)
|
|
@@ -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.
|
|
@@ -282,6 +295,9 @@ module Sequel
|
|
|
282
295
|
# in a subquery, if you are providing a Dataset as the source
|
|
283
296
|
# argument, if should probably call the union method with the
|
|
284
297
|
# all: true and from_self: false options.
|
|
298
|
+
# :security_invoker :: Set the security_invoker property on the view, making
|
|
299
|
+
# the access to the view use the current user's permissions,
|
|
300
|
+
# instead of the view owner's permissions.
|
|
285
301
|
# :tablespace :: The tablespace to use for materialized views.
|
|
286
302
|
def create_view(name, source, options = OPTS)
|
|
287
303
|
execute_ddl(create_view_sql(name, source, options))
|
|
@@ -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:
|
|
@@ -127,6 +127,18 @@ module Sequel
|
|
|
127
127
|
#
|
|
128
128
|
# DB[:table].delete # DELETE * FROM table
|
|
129
129
|
# # => 3
|
|
130
|
+
#
|
|
131
|
+
# Some databases support using multiple tables in a DELETE query. This requires
|
|
132
|
+
# multiple FROM tables (JOINs can also be used). As multiple FROM tables use
|
|
133
|
+
# an implicit CROSS JOIN, you should make sure your WHERE condition uses the
|
|
134
|
+
# appropriate filters for the FROM tables:
|
|
135
|
+
#
|
|
136
|
+
# DB.from(:a, :b).join(:c, :d=>Sequel[:b][:e]).where{{a[:f]=>b[:g], a[:id]=>c[:h]}}.
|
|
137
|
+
# delete
|
|
138
|
+
# # DELETE FROM a
|
|
139
|
+
# # USING b
|
|
140
|
+
# # INNER JOIN c ON (c.d = b.e)
|
|
141
|
+
# # WHERE ((a.f = b.g) AND (a.id = c.h))
|
|
130
142
|
def delete(&block)
|
|
131
143
|
sql = delete_sql
|
|
132
144
|
if uses_returning?(:delete)
|
|
@@ -313,14 +325,18 @@ module Sequel
|
|
|
313
325
|
|
|
314
326
|
# Inserts multiple records into the associated table. This method can be
|
|
315
327
|
# used to efficiently insert a large number of records into a table in a
|
|
316
|
-
# single query if the database supports it. Inserts
|
|
317
|
-
#
|
|
328
|
+
# single query if the database supports it. Inserts are automatically
|
|
329
|
+
# wrapped in a transaction if necessary.
|
|
318
330
|
#
|
|
319
331
|
# This method is called with a columns array and an array of value arrays:
|
|
320
332
|
#
|
|
321
333
|
# DB[:table].import([:x, :y], [[1, 2], [3, 4]])
|
|
322
334
|
# # INSERT INTO table (x, y) VALUES (1, 2)
|
|
323
|
-
# # INSERT INTO table (x, y) VALUES (3, 4)
|
|
335
|
+
# # INSERT INTO table (x, y) VALUES (3, 4)
|
|
336
|
+
#
|
|
337
|
+
# or, if the database supports it:
|
|
338
|
+
#
|
|
339
|
+
# # INSERT INTO table (x, y) VALUES (1, 2), (3, 4)
|
|
324
340
|
#
|
|
325
341
|
# This method also accepts a dataset instead of an array of value arrays:
|
|
326
342
|
#
|
|
@@ -328,9 +344,13 @@ module Sequel
|
|
|
328
344
|
# # INSERT INTO table (x, y) SELECT a, b FROM table2
|
|
329
345
|
#
|
|
330
346
|
# Options:
|
|
331
|
-
# :commit_every :: Open a new transaction for every given number of
|
|
332
|
-
# For example, if you provide a value of 50,
|
|
333
|
-
# after every 50 records.
|
|
347
|
+
# :commit_every :: Open a new transaction for every given number of
|
|
348
|
+
# records. For example, if you provide a value of 50,
|
|
349
|
+
# will commit after every 50 records. When a
|
|
350
|
+
# transaction is not required, this option controls
|
|
351
|
+
# the maximum number of values to insert with a single
|
|
352
|
+
# statement; it does not force the use of a
|
|
353
|
+
# transaction.
|
|
334
354
|
# :return :: When this is set to :primary_key, returns an array of
|
|
335
355
|
# autoincremented primary key values for the rows inserted.
|
|
336
356
|
# This does not have an effect if +values+ is a Dataset.
|
|
@@ -457,6 +477,55 @@ module Sequel
|
|
|
457
477
|
_aggregate(:max, arg)
|
|
458
478
|
end
|
|
459
479
|
|
|
480
|
+
# Execute a MERGE statement, which allows for INSERT, UPDATE, and DELETE
|
|
481
|
+
# behavior in a single query, based on whether rows from a source table
|
|
482
|
+
# match rows in the current table, based on the join conditions.
|
|
483
|
+
#
|
|
484
|
+
# Unless the dataset uses static SQL, to use #merge, you must first have
|
|
485
|
+
# called #merge_using to specify the merge source and join conditions.
|
|
486
|
+
# You will then likely to call one or more of the following methods
|
|
487
|
+
# to specify MERGE behavior by adding WHEN [NOT] MATCHED clauses:
|
|
488
|
+
#
|
|
489
|
+
# * #merge_insert
|
|
490
|
+
# * #merge_update
|
|
491
|
+
# * #merge_delete
|
|
492
|
+
#
|
|
493
|
+
# The WHEN [NOT] MATCHED clauses are added to the SQL in the order these
|
|
494
|
+
# methods were called on the dataset. If none of these methods are
|
|
495
|
+
# called, an error is raised.
|
|
496
|
+
#
|
|
497
|
+
# Example:
|
|
498
|
+
#
|
|
499
|
+
# DB[:m1]
|
|
500
|
+
# merge_using(:m2, i1: :i2).
|
|
501
|
+
# merge_insert(i1: :i2, a: Sequel[:b]+11).
|
|
502
|
+
# merge_delete{a > 30}.
|
|
503
|
+
# merge_update(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20).
|
|
504
|
+
# merge
|
|
505
|
+
#
|
|
506
|
+
# SQL:
|
|
507
|
+
#
|
|
508
|
+
# MERGE INTO m1 USING m2 ON (i1 = i2)
|
|
509
|
+
# WHEN NOT MATCHED THEN INSERT (i1, a) VALUES (i2, (b + 11))
|
|
510
|
+
# WHEN MATCHED AND (a > 30) THEN DELETE
|
|
511
|
+
# WHEN MATCHED THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
|
512
|
+
#
|
|
513
|
+
# On PostgreSQL, two additional merge methods are supported, for the
|
|
514
|
+
# PostgreSQL-specific DO NOTHING syntax.
|
|
515
|
+
#
|
|
516
|
+
# * #merge_do_nothing_when_matched
|
|
517
|
+
# * #merge_do_nothing_when_not_matched
|
|
518
|
+
#
|
|
519
|
+
# This method is supported on Oracle, but Oracle's MERGE support is
|
|
520
|
+
# non-standard, and has the following issues:
|
|
521
|
+
#
|
|
522
|
+
# * DELETE clause requires UPDATE clause
|
|
523
|
+
# * DELETE clause requires a condition
|
|
524
|
+
# * DELETE clause only affects rows updated by UPDATE clause
|
|
525
|
+
def merge
|
|
526
|
+
execute_ddl(merge_sql)
|
|
527
|
+
end
|
|
528
|
+
|
|
460
529
|
# Returns the minimum value for the given column/expression.
|
|
461
530
|
# Uses a virtual row block if no argument is given.
|
|
462
531
|
#
|
|
@@ -527,7 +596,7 @@ module Sequel
|
|
|
527
596
|
# # SELECT * FROM table ORDER BY id LIMIT 1000 OFFSET 1000
|
|
528
597
|
# # ...
|
|
529
598
|
#
|
|
530
|
-
# DB[:table].order(:id).paged_each(:
|
|
599
|
+
# DB[:table].order(:id).paged_each(rows_per_fetch: 100){|row| }
|
|
531
600
|
# # SELECT * FROM table ORDER BY id LIMIT 100
|
|
532
601
|
# # SELECT * FROM table ORDER BY id LIMIT 100 OFFSET 100
|
|
533
602
|
# # ...
|
|
@@ -546,7 +615,7 @@ module Sequel
|
|
|
546
615
|
unless @opts[:order]
|
|
547
616
|
raise Sequel::Error, "Dataset#paged_each requires the dataset be ordered"
|
|
548
617
|
end
|
|
549
|
-
unless
|
|
618
|
+
unless defined?(yield)
|
|
550
619
|
return enum_for(:paged_each, opts)
|
|
551
620
|
end
|
|
552
621
|
|
|
@@ -869,6 +938,19 @@ module Sequel
|
|
|
869
938
|
#
|
|
870
939
|
# DB[:table].update(x: Sequel[:x]+1, y: 0) # UPDATE table SET x = (x + 1), y = 0
|
|
871
940
|
# # => 10
|
|
941
|
+
#
|
|
942
|
+
# Some databases support using multiple tables in an UPDATE query. This requires
|
|
943
|
+
# multiple FROM tables (JOINs can also be used). As multiple FROM tables use
|
|
944
|
+
# an implicit CROSS JOIN, you should make sure your WHERE condition uses the
|
|
945
|
+
# appropriate filters for the FROM tables:
|
|
946
|
+
#
|
|
947
|
+
# DB.from(:a, :b).join(:c, :d=>Sequel[:b][:e]).where{{a[:f]=>b[:g], a[:id]=>10}}.
|
|
948
|
+
# update(:f=>Sequel[:c][:h])
|
|
949
|
+
# # UPDATE a
|
|
950
|
+
# # SET f = c.h
|
|
951
|
+
# # FROM b
|
|
952
|
+
# # INNER JOIN c ON (c.d = b.e)
|
|
953
|
+
# # WHERE ((a.f = b.g) AND (a.id = 10))
|
|
872
954
|
def update(values=OPTS, &block)
|
|
873
955
|
sql = update_sql(values)
|
|
874
956
|
if uses_returning?(:update)
|
|
@@ -974,18 +1056,19 @@ module Sequel
|
|
|
974
1056
|
|
|
975
1057
|
# Internals of #import. If primary key values are requested, use
|
|
976
1058
|
# separate insert commands for each row. Otherwise, call #multi_insert_sql
|
|
977
|
-
# and execute each statement it gives separately.
|
|
1059
|
+
# and execute each statement it gives separately. A transaction is only used
|
|
1060
|
+
# if there are multiple statements to execute.
|
|
978
1061
|
def _import(columns, values, opts)
|
|
979
1062
|
trans_opts = Hash[opts]
|
|
980
1063
|
trans_opts[:server] = @opts[:server]
|
|
981
1064
|
if opts[:return] == :primary_key
|
|
982
|
-
|
|
1065
|
+
_import_transaction(values, trans_opts){values.map{|v| insert(columns, v)}}
|
|
983
1066
|
else
|
|
984
1067
|
stmts = multi_insert_sql(columns, values)
|
|
985
|
-
|
|
1068
|
+
_import_transaction(stmts, trans_opts){stmts.each{|st| execute_dui(st)}}
|
|
986
1069
|
end
|
|
987
1070
|
end
|
|
988
|
-
|
|
1071
|
+
|
|
989
1072
|
# Return an array of arrays of values given by the symbols in ret_cols.
|
|
990
1073
|
def _select_map_multiple(ret_cols)
|
|
991
1074
|
map{|r| r.values_at(*ret_cols)}
|
|
@@ -1024,6 +1107,17 @@ module Sequel
|
|
|
1024
1107
|
end
|
|
1025
1108
|
end
|
|
1026
1109
|
|
|
1110
|
+
# Use a transaction when yielding to the block if multiple values/statements
|
|
1111
|
+
# are provided. When only a single value or statement is provided, then yield
|
|
1112
|
+
# without using a transaction.
|
|
1113
|
+
def _import_transaction(values, trans_opts, &block)
|
|
1114
|
+
if values.length > 1
|
|
1115
|
+
@db.transaction(trans_opts, &block)
|
|
1116
|
+
else
|
|
1117
|
+
yield
|
|
1118
|
+
end
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1027
1121
|
# Internals of +select_hash+ and +select_hash_groups+
|
|
1028
1122
|
def _select_hash(meth, key_column, value_column, opts=OPTS)
|
|
1029
1123
|
select(*(key_column.is_a?(Array) ? key_column : [key_column]) + (value_column.is_a?(Array) ? value_column : [value_column])).
|
|
@@ -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
|
|
@@ -142,6 +152,11 @@ module Sequel
|
|
|
142
152
|
supports_distinct_on?
|
|
143
153
|
end
|
|
144
154
|
|
|
155
|
+
# Whether placeholder literalizers are supported, true by default.
|
|
156
|
+
def supports_placeholder_literalizer?
|
|
157
|
+
true
|
|
158
|
+
end
|
|
159
|
+
|
|
145
160
|
# Whether the dataset supports pattern matching by regular expressions, false by default.
|
|
146
161
|
def supports_regexp?
|
|
147
162
|
false
|
|
@@ -178,6 +193,11 @@ module Sequel
|
|
|
178
193
|
true
|
|
179
194
|
end
|
|
180
195
|
|
|
196
|
+
# Whether updating joined datasets is supported, false by default.
|
|
197
|
+
def supports_updating_joins?
|
|
198
|
+
supports_modifying_joins?
|
|
199
|
+
end
|
|
200
|
+
|
|
181
201
|
# Whether the dataset supports the WINDOW clause to define windows used by multiple
|
|
182
202
|
# window functions, false by default.
|
|
183
203
|
def supports_window_clause?
|
data/lib/sequel/dataset/misc.rb
CHANGED
|
@@ -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
|