sequel 5.92.0 → 5.94.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/lib/sequel/adapters/ado/access.rb +2 -2
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/ibmdb.rb +1 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -2
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +21 -7
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +16 -0
- data/lib/sequel/adapters/shared/db2.rb +8 -3
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/mysql.rb +2 -2
- data/lib/sequel/adapters/shared/postgres.rb +206 -16
- data/lib/sequel/adapters/shared/sqlite.rb +3 -3
- data/lib/sequel/adapters/tinytds.rb +1 -1
- data/lib/sequel/adapters/trilogy.rb +1 -1
- data/lib/sequel/connection_pool/timed_queue.rb +1 -1
- data/lib/sequel/core.rb +1 -1
- data/lib/sequel/database/misc.rb +3 -3
- data/lib/sequel/database/query.rb +1 -1
- data/lib/sequel/database/schema_generator.rb +24 -10
- data/lib/sequel/database/schema_methods.rb +60 -26
- data/lib/sequel/dataset/prepared_statements.rb +68 -24
- data/lib/sequel/dataset/query.rb +10 -2
- data/lib/sequel/dataset/sql.rb +8 -5
- data/lib/sequel/extensions/async_thread_pool.rb +1 -1
- data/lib/sequel/extensions/caller_logging.rb +1 -3
- data/lib/sequel/extensions/eval_inspect.rb +1 -1
- data/lib/sequel/extensions/inflector.rb +2 -2
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/pg_auto_parameterize.rb +5 -0
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/provenance.rb +1 -3
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/plugins/constraint_validations.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +3 -3
- data/lib/sequel/plugins/unused_associations.rb +4 -2
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/sql.rb +7 -5
- data/lib/sequel/version.rb +1 -1
- metadata +1 -1
data/lib/sequel/database/misc.rb
CHANGED
@@ -36,13 +36,13 @@ module Sequel
|
|
36
36
|
|
37
37
|
# Register a hook that will be run when a new Database is instantiated. It is
|
38
38
|
# called with the new database handle.
|
39
|
-
def self.after_initialize
|
40
|
-
raise Error, "must provide block to after_initialize" unless
|
39
|
+
def self.after_initialize
|
40
|
+
raise Error, "must provide block to after_initialize" unless defined?(yield)
|
41
41
|
Sequel.synchronize do
|
42
42
|
previous = @initialize_hook
|
43
43
|
@initialize_hook = proc do |db|
|
44
44
|
previous.call(db)
|
45
|
-
|
45
|
+
yield(db)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -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
|
@@ -126,17 +126,21 @@ module Sequel
|
|
126
126
|
# (:restrict, :cascade, :set_null, :set_default, :no_action).
|
127
127
|
# :primary_key :: Make the column as a single primary key column. This should not
|
128
128
|
# be used if you want a single autoincrementing primary key column
|
129
|
-
# (use the primary_key method in that case).
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
129
|
+
# (use the primary_key method in that case). Can be a hash to provide
|
130
|
+
# options for the constraint:
|
131
|
+
# :name :: The name to give the primary key constraint.
|
132
|
+
# :deferrable :: Sets whether the primary key constraint is deferrable.
|
133
|
+
# :primary_key_constraint_name :: Older option to name primary key constraint.
|
134
|
+
# :primary_key_deferrable :: Older option to set primary key constraint as deferrable.
|
133
135
|
# :type :: Overrides the type given as the argument. Generally not used by column
|
134
136
|
# itself, but can be passed as an option to other methods that call column.
|
135
137
|
# :unique :: Mark the column as unique, generally has the same effect as
|
136
|
-
# creating a unique index on the column.
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
138
|
+
# creating a unique index on the column. Can be a hash to provide options for
|
139
|
+
# the constraint:
|
140
|
+
# :name :: The name to give the unique constraint.
|
141
|
+
# :deferrable :: Sets whether the unique constraint is deferrable.
|
142
|
+
# :unique_constraint_name :: Older option to name unique constraint.
|
143
|
+
# :unique_deferrable :: Older option to set unique constraint as deferrable.
|
140
144
|
#
|
141
145
|
# PostgreSQL specific options:
|
142
146
|
#
|
@@ -178,6 +182,7 @@ module Sequel
|
|
178
182
|
# :deferrable :: Whether the CHECK constraint should be marked DEFERRABLE.
|
179
183
|
#
|
180
184
|
# PostgreSQL specific options:
|
185
|
+
# :not_enforced :: Whether the CHECK constraint should be marked NOT ENFORCED.
|
181
186
|
# :not_valid :: Whether the CHECK constraint should be marked NOT VALID.
|
182
187
|
def constraint(name, *args, &block)
|
183
188
|
opts = name.is_a?(Hash) ? name : {:name=>name}
|
@@ -197,9 +202,18 @@ module Sequel
|
|
197
202
|
#
|
198
203
|
# :foreign_key_constraint_name :: The name to give the foreign key constraint
|
199
204
|
#
|
205
|
+
# PostgreSQL specific options:
|
206
|
+
#
|
207
|
+
# :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
|
208
|
+
#
|
200
209
|
# 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
|
-
#
|
210
|
+
# composite foreign key), you can provide an array of columns as the first argument.
|
211
|
+
# This changes the method to accept constraint options instead of column options.
|
212
|
+
# You can provide the :name option to name the constraint.
|
213
|
+
#
|
214
|
+
# PostgreSQL specific options:
|
215
|
+
#
|
216
|
+
# :not_enforced :: Whether the foreign key constraint should be marked NOT ENFORCED.
|
203
217
|
#
|
204
218
|
# foreign_key([:artist_name, :artist_location], :artists, name: :artist_fk)
|
205
219
|
# # ADD CONSTRAINT artist_fk FOREIGN KEY (artist_name, artist_location) REFERENCES artists
|
@@ -605,36 +605,63 @@ module Sequel
|
|
605
605
|
end
|
606
606
|
end
|
607
607
|
|
608
|
-
# Add primary key SQL fragment to column creation SQL.
|
608
|
+
# Add primary key SQL fragment to column creation SQL if column is a primary key.
|
609
609
|
def column_definition_primary_key_sql(sql, column)
|
610
|
-
if column[:primary_key]
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
610
|
+
column_definition_add_primary_key_sql(sql, column) if column[:primary_key]
|
611
|
+
end
|
612
|
+
|
613
|
+
# Add primary key SQL fragment to column creation SQL (column should be a primary key).
|
614
|
+
def column_definition_add_primary_key_sql(sql, column)
|
615
|
+
constraint = column_definition_constraint_hash(column, :primary_key)
|
616
|
+
append_named_constraint_prefix_sql(sql, constraint[:name])
|
617
|
+
sql << " " << primary_key_constraint_sql_fragment(constraint)
|
618
|
+
constraint_deferrable_sql_append(sql, constraint[:deferrable])
|
617
619
|
end
|
618
620
|
|
619
|
-
# Add foreign key reference SQL fragment to column creation SQL.
|
621
|
+
# Add foreign key reference SQL fragment to column creation SQL if column is a foreign key.
|
620
622
|
def column_definition_references_sql(sql, column)
|
621
|
-
if column[:table]
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
623
|
+
column_definition_add_references_sql(sql, column) if column[:table]
|
624
|
+
end
|
625
|
+
|
626
|
+
# Add foreign key reference SQL fragment to column creation SQL (column should be a foreign key).
|
627
|
+
def column_definition_add_references_sql(sql, column)
|
628
|
+
append_named_constraint_prefix_sql(sql, column[:foreign_key_constraint_name])
|
629
|
+
sql << column_references_column_constraint_sql(column)
|
627
630
|
end
|
628
631
|
|
629
|
-
# Add unique constraint SQL fragment to column creation SQL.
|
632
|
+
# Add unique constraint SQL fragment to column creation SQL if column has a unique constraint.
|
630
633
|
def column_definition_unique_sql(sql, column)
|
631
|
-
if column[:unique]
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
634
|
+
column_definition_add_unique_sql(sql, column) if column[:unique]
|
635
|
+
end
|
636
|
+
|
637
|
+
# Add unique constraint SQL fragment to column creation SQL (column should have unique constraint).
|
638
|
+
def column_definition_add_unique_sql(sql, column)
|
639
|
+
constraint = column_definition_constraint_hash(column, :unique)
|
640
|
+
append_named_constraint_prefix_sql(sql, constraint[:name])
|
641
|
+
sql << ' ' << unique_constraint_sql_fragment(constraint)
|
642
|
+
constraint_deferrable_sql_append(sql, constraint[:deferrable])
|
643
|
+
end
|
644
|
+
|
645
|
+
# Add the name of the constraint to the column creation SQL.
|
646
|
+
def append_named_constraint_prefix_sql(sql, name)
|
647
|
+
sql << " CONSTRAINT #{quote_identifier(name)}" if name
|
648
|
+
end
|
649
|
+
|
650
|
+
# Return a hash of constraint options for the primary key or column
|
651
|
+
# unique constraint.
|
652
|
+
def column_definition_constraint_hash(column, prefix)
|
653
|
+
constraint = column[prefix]
|
654
|
+
constraint = constraint.is_a?(Hash) ? constraint.dup : {}
|
655
|
+
|
656
|
+
if name = column[:"#{prefix}_constraint_name"]
|
657
|
+
constraint[:name] = name
|
637
658
|
end
|
659
|
+
|
660
|
+
if column.has_key?(:"#{prefix}_deferrable")
|
661
|
+
constraint[:deferrable] = column[:"#{prefix}_deferrable"]
|
662
|
+
end
|
663
|
+
|
664
|
+
constraint
|
638
665
|
end
|
639
666
|
|
640
667
|
# SQL for all given columns, used inside a CREATE TABLE block.
|
@@ -677,7 +704,7 @@ module Sequel
|
|
677
704
|
check = constraint[:check]
|
678
705
|
check = check.first if check.is_a?(Array) && check.length == 1
|
679
706
|
check = filter_expr(check)
|
680
|
-
check = "(#{check})" unless check
|
707
|
+
check = "(#{check})" unless check.start_with?('(') && check.end_with?(')')
|
681
708
|
sql << "CHECK #{check}"
|
682
709
|
when :primary_key
|
683
710
|
sql << "#{primary_key_constraint_sql_fragment(constraint)} #{literal(constraint[:columns])}"
|
@@ -733,17 +760,24 @@ module Sequel
|
|
733
760
|
def create_table_sql(name, generator, options)
|
734
761
|
unless supports_named_column_constraints?
|
735
762
|
# Split column constraints into table constraints if they have a name
|
763
|
+
fk_opt_keys = [:key, :on_delete, :on_update, :deferrable]
|
736
764
|
generator.columns.each do |c|
|
737
765
|
if (constraint_name = c.delete(:foreign_key_constraint_name)) && (table = c.delete(:table))
|
738
766
|
opts = {}
|
739
767
|
opts[:name] = constraint_name
|
740
|
-
|
768
|
+
fk_opt_keys.each{|k| opts[k] = c[k]}
|
741
769
|
generator.foreign_key([c[:name]], table, opts)
|
742
770
|
end
|
743
|
-
|
771
|
+
|
772
|
+
if c[:unique].is_a?(Hash) && c[:unique][:name]
|
773
|
+
generator.unique(c[:name], c.delete(:unique))
|
774
|
+
elsif (constraint_name = c.delete(:unique_constraint_name)) && c.delete(:unique)
|
744
775
|
generator.unique(c[:name], :name=>constraint_name)
|
745
776
|
end
|
746
|
-
|
777
|
+
|
778
|
+
if c[:primary_key].is_a?(Hash) && c[:primary_key][:name]
|
779
|
+
generator.primary_key([c[:name]], c.delete(:primary_key))
|
780
|
+
elsif (constraint_name = c.delete(:primary_key_constraint_name)) && c.delete(:primary_key)
|
747
781
|
generator.primary_key([c[:name]], :name=>constraint_name)
|
748
782
|
end
|
749
783
|
end
|
@@ -91,8 +91,14 @@ module Sequel
|
|
91
91
|
@opts[:log_sql]
|
92
92
|
end
|
93
93
|
|
94
|
-
# The type of
|
95
|
-
#
|
94
|
+
# The type of SQL to generate for the prepared statement. Generally
|
95
|
+
# the same as #prepared_type, but can be different.
|
96
|
+
def prepared_sql_type
|
97
|
+
@opts[:prepared_sql_type] || prepared_type
|
98
|
+
end
|
99
|
+
|
100
|
+
# The type of prepared statement, which controls how the prepared statement
|
101
|
+
# handles results from the database.
|
96
102
|
def prepared_type
|
97
103
|
@opts[:prepared_type]
|
98
104
|
end
|
@@ -141,7 +147,7 @@ module Sequel
|
|
141
147
|
# Returns the SQL for the prepared statement, depending on
|
142
148
|
# the type of the statement and the prepared_modify_values.
|
143
149
|
def prepared_sql
|
144
|
-
case
|
150
|
+
case prepared_sql_type
|
145
151
|
when :select, :all, :each
|
146
152
|
# Most common scenario, so listed first.
|
147
153
|
select_sql
|
@@ -182,34 +188,30 @@ module Sequel
|
|
182
188
|
|
183
189
|
# Run the method based on the type of prepared statement.
|
184
190
|
def run(&block)
|
185
|
-
case prepared_type
|
191
|
+
case type = prepared_type
|
186
192
|
when :select, :all
|
187
|
-
|
193
|
+
with_sql_all(prepared_sql, &block)
|
188
194
|
when :each
|
189
|
-
|
190
|
-
when :insert_select
|
191
|
-
|
192
|
-
when :first
|
193
|
-
first
|
195
|
+
with_sql_each(prepared_sql, &block)
|
196
|
+
when :insert_select, :first
|
197
|
+
with_sql_first(prepared_sql)
|
194
198
|
when :insert, :update, :delete
|
195
199
|
if opts[:returning] && supports_returning?(prepared_type)
|
196
200
|
returning_fetch_rows(prepared_sql)
|
197
|
-
elsif
|
198
|
-
|
201
|
+
elsif type == :delete
|
202
|
+
with_sql_delete(prepared_sql)
|
199
203
|
else
|
200
|
-
public_send(
|
204
|
+
force_prepared_sql.public_send(type, *prepared_modify_values)
|
201
205
|
end
|
202
|
-
when :insert_pk
|
203
|
-
|
206
|
+
when :insert_pk, :single_value
|
207
|
+
with_sql_single_value(prepared_sql)
|
204
208
|
when Array
|
205
209
|
# :nocov:
|
206
|
-
case
|
210
|
+
case type[0]
|
207
211
|
# :nocov:
|
208
212
|
when :map, :as_hash, :to_hash, :to_hash_groups
|
209
|
-
public_send(*
|
213
|
+
force_prepared_sql.public_send(*type, &block)
|
210
214
|
end
|
211
|
-
when :single_value
|
212
|
-
single_value
|
213
215
|
else
|
214
216
|
raise Error, "unsupported prepared statement type used: #{prepared_type.inspect}"
|
215
217
|
end
|
@@ -217,6 +219,16 @@ module Sequel
|
|
217
219
|
|
218
220
|
private
|
219
221
|
|
222
|
+
# If the prepared_sql_type does not match the prepared statement, return a clone that
|
223
|
+
# with the prepared SQL, to ensure the prepared_sql_type is respected.
|
224
|
+
def force_prepared_sql
|
225
|
+
if prepared_sql_type != prepared_type
|
226
|
+
with_sql(prepared_sql)
|
227
|
+
else
|
228
|
+
self
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
220
232
|
# Returns the value of the prepared_args hash for the given key.
|
221
233
|
def prepared_arg(k)
|
222
234
|
@opts[:bind_vars][k]
|
@@ -294,11 +306,12 @@ module Sequel
|
|
294
306
|
prepared_sql, frags = Sequel::Dataset::PlaceholderLiteralizer::Recorder.new.send(:prepared_sql_and_frags, self, prepared_args) do |pl, ds|
|
295
307
|
ds = ds.clone(:recorder=>pl)
|
296
308
|
|
297
|
-
|
309
|
+
sql_type = prepared_sql_type || type
|
310
|
+
case sql_type
|
298
311
|
when :first, :single_value
|
299
312
|
ds.limit(1)
|
300
313
|
when :update, :insert, :insert_select, :delete
|
301
|
-
ds.with_sql(:"#{
|
314
|
+
ds.with_sql(:"#{sql_type}_sql", *values)
|
302
315
|
when :insert_pk
|
303
316
|
ds.with_sql(:insert_sql, *values)
|
304
317
|
else
|
@@ -344,13 +357,23 @@ module Sequel
|
|
344
357
|
clone(:bind_vars=>bind_vars)
|
345
358
|
end
|
346
359
|
|
347
|
-
# For the given type
|
348
|
-
#
|
349
|
-
#
|
360
|
+
# For the given type, run the sql with the bind variables specified in the hash.
|
361
|
+
# +values+ is a hash passed to insert or update (if one of those types is used),
|
362
|
+
# which may contain placeholders.
|
363
|
+
#
|
364
|
+
# The following types are supported:
|
365
|
+
#
|
366
|
+
# * :select, :all, :each, :first, :single_value, :insert, :insert_select, :insert_pk, :update, :delete
|
367
|
+
# * Array where first element is :map, :as_hash, :to_hash, :to_hash_groups (remaining elements
|
368
|
+
# are passed to the related method)
|
350
369
|
#
|
351
370
|
# DB[:table].where(id: :$id).call(:first, id: 1)
|
352
371
|
# # SELECT * FROM table WHERE id = ? LIMIT 1 -- (1)
|
353
372
|
# # => {:id=>1}
|
373
|
+
#
|
374
|
+
# DB[:table].where(id: :$id).call(:update, {c: 1, id: 2}, col: :$c)
|
375
|
+
# # UPDATE table WHERE id = ? SET col = ? -- (2, 1)
|
376
|
+
# # => 1
|
354
377
|
def call(type, bind_variables=OPTS, *values, &block)
|
355
378
|
to_prepared_statement(type, values, :extend=>bound_variable_modules).call(bind_variables, &block)
|
356
379
|
end
|
@@ -371,6 +394,14 @@ module Sequel
|
|
371
394
|
# # => {:id=>1, :name=>'Blah'}
|
372
395
|
#
|
373
396
|
# DB.call(:select_by_name, name: 'Blah') # Same thing
|
397
|
+
#
|
398
|
+
# +values+ given are passed to +insert+ or +update+ if they are used:
|
399
|
+
#
|
400
|
+
# ps = DB[:table].where(id: :$i).prepare(:update, :update_name, name: :$n)
|
401
|
+
#
|
402
|
+
# ps.call(i: 1, n: 'Blah')
|
403
|
+
# # UPDATE table WHERE id = ? SET name = ? -- (1, 'Blah')
|
404
|
+
# # => 1
|
374
405
|
def prepare(type, name, *values)
|
375
406
|
ps = to_prepared_statement(type, values, :name=>name, :extend=>prepared_statement_modules, :no_delayed_evaluations=>true)
|
376
407
|
|
@@ -387,6 +418,19 @@ module Sequel
|
|
387
418
|
ps
|
388
419
|
end
|
389
420
|
|
421
|
+
# Set the type of SQL to use for prepared statements based on this
|
422
|
+
# dataset. Prepared statements default to using the same SQL type
|
423
|
+
# as the type that is passed to #prepare/#call, but there are cases
|
424
|
+
# where it is helpful to use a different SQL type.
|
425
|
+
#
|
426
|
+
# Available types are: :select, :first, :single_value, :update,
|
427
|
+
# :delete, :insert, :insert_select, :insert_pk
|
428
|
+
#
|
429
|
+
# Other types are treated as :select.
|
430
|
+
def prepare_sql_type(type)
|
431
|
+
clone(:prepared_sql_type => type)
|
432
|
+
end
|
433
|
+
|
390
434
|
protected
|
391
435
|
|
392
436
|
# Return a cloned copy of the current dataset extended with
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -231,8 +231,7 @@ module Sequel
|
|
231
231
|
#
|
232
232
|
# DB[:table].for_update # SELECT * FROM table FOR UPDATE
|
233
233
|
def for_update
|
234
|
-
|
235
|
-
cached_dataset(:_for_update_ds){lock_style(:update)}
|
234
|
+
cached_lock_style_dataset(:_for_update_ds, :update)
|
236
235
|
end
|
237
236
|
|
238
237
|
# Returns a copy of the dataset with the source changed. If no
|
@@ -1462,6 +1461,15 @@ module Sequel
|
|
1462
1461
|
end
|
1463
1462
|
end
|
1464
1463
|
|
1464
|
+
# Internals of for_update and adapter-specific lock methods.
|
1465
|
+
# Returns receiver if it already uses this lock style, and a cached
|
1466
|
+
# dataset using the given key otherwise. The key could be derived from
|
1467
|
+
# the style, but doing so would require allocation, so pass it in as
|
1468
|
+
# an argument.
|
1469
|
+
def cached_lock_style_dataset(key, style)
|
1470
|
+
opts[:lock] == style ? self : cached_dataset(key){lock_style(style)}
|
1471
|
+
end
|
1472
|
+
|
1465
1473
|
# The default :qualify option to use for join tables if one is not specified.
|
1466
1474
|
def default_join_table_qualification
|
1467
1475
|
:symbol
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -685,10 +685,10 @@ module Sequel
|
|
685
685
|
# being quoted, returns name as a string. If identifiers are being quoted
|
686
686
|
# quote the name with quoted_identifier.
|
687
687
|
def quote_identifier_append(sql, name)
|
688
|
+
name = name.value if name.is_a?(SQL::Identifier)
|
688
689
|
if name.is_a?(LiteralString)
|
689
690
|
sql << name
|
690
691
|
else
|
691
|
-
name = name.value if name.is_a?(SQL::Identifier)
|
692
692
|
name = input_identifier(name)
|
693
693
|
if quote_identifiers?
|
694
694
|
quoted_identifier_append(sql, name)
|
@@ -700,11 +700,14 @@ module Sequel
|
|
700
700
|
|
701
701
|
# Append literalization of identifier or unqualified identifier to SQL string.
|
702
702
|
def quote_schema_table_append(sql, table)
|
703
|
-
|
704
|
-
|
705
|
-
|
703
|
+
qualifiers = split_qualifiers(table)
|
704
|
+
table = qualifiers.pop
|
705
|
+
|
706
|
+
qualifiers.each do |q|
|
707
|
+
quote_identifier_append(sql, q)
|
706
708
|
sql << '.'
|
707
709
|
end
|
710
|
+
|
708
711
|
quote_identifier_append(sql, table)
|
709
712
|
end
|
710
713
|
|
@@ -1336,7 +1339,7 @@ module Sequel
|
|
1336
1339
|
# SQL fragment specifying a JOIN type, converts underscores to
|
1337
1340
|
# spaces and upcases.
|
1338
1341
|
def join_type_sql(join_type)
|
1339
|
-
"#{join_type.to_s.
|
1342
|
+
"#{join_type.to_s.tr('_', ' ').upcase} JOIN"
|
1340
1343
|
end
|
1341
1344
|
|
1342
1345
|
# Append USING clause for JOIN USING
|
@@ -357,7 +357,7 @@ module Sequel
|
|
357
357
|
define_singleton_method(:async_job_class){proxy_klass}
|
358
358
|
|
359
359
|
queue = @async_thread_queue = Queue.new
|
360
|
-
pool = @async_thread_pool = num_async_threads
|
360
|
+
pool = @async_thread_pool = Array.new(num_async_threads){JobProcessor.new(queue)}
|
361
361
|
ObjectSpace.define_finalizer(db, JobProcessor.create_finalizer(queue, pool))
|
362
362
|
|
363
363
|
extend_datasets(DatasetMethods)
|
@@ -60,9 +60,7 @@ module Sequel
|
|
60
60
|
def external_caller_for_log
|
61
61
|
ignore = caller_logging_ignore
|
62
62
|
c = caller.find do |line|
|
63
|
-
!(line.start_with?(SEQUEL_LIB_PATH) ||
|
64
|
-
line.start_with?(RUBY_STDLIB) ||
|
65
|
-
line.start_with?(INTERNAL) ||
|
63
|
+
!(line.start_with?(SEQUEL_LIB_PATH, RUBY_STDLIB, INTERNAL) ||
|
66
64
|
(ignore && line =~ ignore))
|
67
65
|
end
|
68
66
|
|
@@ -66,7 +66,7 @@ module Sequel
|
|
66
66
|
# in the order they were defined.
|
67
67
|
klass = self.class
|
68
68
|
args = inspect_args.map do |arg|
|
69
|
-
if arg.is_a?(String) && arg
|
69
|
+
if arg.is_a?(String) && arg.start_with?('*')
|
70
70
|
# Special case string arguments starting with *, indicating that
|
71
71
|
# they should return an array to be splatted as the remaining arguments.
|
72
72
|
# Allow calling private methods to get inspect output.
|
@@ -159,7 +159,7 @@ class String
|
|
159
159
|
# Example
|
160
160
|
# "puni_puni".dasherize #=> "puni-puni"
|
161
161
|
def dasherize
|
162
|
-
|
162
|
+
tr('_', '-')
|
163
163
|
end
|
164
164
|
|
165
165
|
# Removes the module part from the expression in the string
|
@@ -189,7 +189,7 @@ class String
|
|
189
189
|
# "employee_salary" #=> "Employee salary"
|
190
190
|
# "author_id" #=> "Author"
|
191
191
|
def humanize
|
192
|
-
gsub(/_id$/, "").
|
192
|
+
gsub(/_id$/, "").tr('_', " ").capitalize
|
193
193
|
end
|
194
194
|
|
195
195
|
# Returns the plural form of the word in the string.
|
@@ -845,7 +845,7 @@ module Sequel
|
|
845
845
|
begin
|
846
846
|
db.create_table(table){String c, :primary_key=>true}
|
847
847
|
rescue Sequel::DatabaseError => e
|
848
|
-
if db.database_type == :mysql && e.message
|
848
|
+
if db.database_type == :mysql && e.message.include?('max key length')
|
849
849
|
# Handle case where MySQL is used with utf8mb4 charset default, which
|
850
850
|
# only allows a maximum length of about 190 characters for string
|
851
851
|
# primary keys due to InnoDB limitations.
|
@@ -463,6 +463,11 @@ module Sequel
|
|
463
463
|
@opts[:no_auto_parameterize] ? super : QueryString.new
|
464
464
|
end
|
465
465
|
|
466
|
+
# A mutable string used as the prefix when explaining a query.
|
467
|
+
def explain_sql_string_origin(opts)
|
468
|
+
@opts[:no_auto_parameterize] ? super : (QueryString.new << super)
|
469
|
+
end
|
470
|
+
|
466
471
|
# If subquery uses with_sql with a method name symbol, get the dataset
|
467
472
|
# with_sql was called on, and use that as the subquery, recording the
|
468
473
|
# arguments to with_sql that will be used to calculate the sql.
|
@@ -136,7 +136,7 @@ module Sequel
|
|
136
136
|
module DatabaseMethods
|
137
137
|
def self.extended(db)
|
138
138
|
db.instance_exec do
|
139
|
-
add_named_conversion_proc(:hstore
|
139
|
+
add_named_conversion_proc(:hstore){|v| HStore.parse(v)}
|
140
140
|
@schema_type_classes[:hstore] = HStore
|
141
141
|
end
|
142
142
|
end
|
@@ -97,9 +97,7 @@ module Sequel
|
|
97
97
|
def provenance_source
|
98
98
|
ignore = db.opts[:provenance_caller_ignore]
|
99
99
|
caller.find do |line|
|
100
|
-
!(line.start_with?(SEQUEL_LIB_PATH) ||
|
101
|
-
line.start_with?(RUBY_STDLIB) ||
|
102
|
-
line.start_with?(INTERNAL) ||
|
100
|
+
!(line.start_with?(SEQUEL_LIB_PATH, RUBY_STDLIB, INTERNAL) ||
|
103
101
|
(ignore && line =~ ignore))
|
104
102
|
end
|
105
103
|
end
|
@@ -221,7 +221,7 @@ END_MIG
|
|
221
221
|
else
|
222
222
|
col_opts = if options[:same_db]
|
223
223
|
h = {:type=>schema[:db_type]}
|
224
|
-
if database_type == :mysql && h[:type]
|
224
|
+
if database_type == :mysql && h[:type].start_with?("timestamp")
|
225
225
|
h[:null] = true
|
226
226
|
end
|
227
227
|
if database_type == :mssql && schema[:max_length]
|
@@ -164,7 +164,7 @@ module Sequel
|
|
164
164
|
arg = constraint_validation_int_range(arg)
|
165
165
|
type = :includes
|
166
166
|
when *OPERATOR_MAP.keys
|
167
|
-
arg = arg.to_i if type.to_s
|
167
|
+
arg = arg.to_i if type.to_s.start_with?('int_')
|
168
168
|
operator = OPERATOR_MAP[type]
|
169
169
|
type = :operator
|
170
170
|
end
|
@@ -370,9 +370,9 @@ module Sequel
|
|
370
370
|
end
|
371
371
|
|
372
372
|
# Convert the receiver to a JSON data structure using the given arguments.
|
373
|
-
def to_json_data(*args
|
374
|
-
if
|
375
|
-
to_json(*args){|x| return
|
373
|
+
def to_json_data(*args)
|
374
|
+
if defined?(yield)
|
375
|
+
to_json(*args){|x| return yield(x)}
|
376
376
|
else
|
377
377
|
to_json(*args){|x| return x}
|
378
378
|
end
|
@@ -347,6 +347,8 @@ module Sequel
|
|
347
347
|
coverage_data = options[:coverage_data] || Sequel.parse_json(File.binread(@unused_associations_coverage_file))
|
348
348
|
|
349
349
|
unused_associations_data = {}
|
350
|
+
to_many_modification_methods = [:adder, :remover, :clearer]
|
351
|
+
modification_methods = [:setter, :adder, :remover, :clearer]
|
350
352
|
|
351
353
|
([self] + descendants).each do |sc|
|
352
354
|
next unless cov_data = coverage_data[sc.name]
|
@@ -383,8 +385,8 @@ module Sequel
|
|
383
385
|
if !info[:used]
|
384
386
|
(unused_associations_data[sc.name] ||= {})[assoc.to_s] = 'unused'
|
385
387
|
elsif unused = info[:unused]
|
386
|
-
if unused.include?(:setter) ||
|
387
|
-
|
388
|
+
if unused.include?(:setter) || to_many_modification_methods.all?{|k| unused.include?(k)}
|
389
|
+
modification_methods.each do |k|
|
388
390
|
unused.delete(k)
|
389
391
|
end
|
390
392
|
unused << :read_only
|
data/lib/sequel/sql.rb
CHANGED
@@ -1733,12 +1733,11 @@ module Sequel
|
|
1733
1733
|
|
1734
1734
|
# Automatically convert SQL::Identifiers to strings
|
1735
1735
|
def convert_identifier(identifier)
|
1736
|
-
|
1737
|
-
|
1738
|
-
identifier.
|
1739
|
-
else
|
1740
|
-
identifier
|
1736
|
+
if identifier.is_a?(SQL::Identifier)
|
1737
|
+
identifier = identifier.value
|
1738
|
+
identifier = identifier.to_s unless identifier.is_a?(LiteralString)
|
1741
1739
|
end
|
1740
|
+
identifier
|
1742
1741
|
end
|
1743
1742
|
end
|
1744
1743
|
|
@@ -2053,6 +2052,9 @@ module Sequel
|
|
2053
2052
|
end
|
2054
2053
|
end
|
2055
2054
|
|
2055
|
+
SQL::Constants::OLD = SQL::Identifier.new(LiteralString.new("OLD").freeze)
|
2056
|
+
SQL::Constants::NEW = SQL::Identifier.new(LiteralString.new("NEW").freeze)
|
2057
|
+
|
2056
2058
|
include SQL::Constants
|
2057
2059
|
extend SQL::Builders
|
2058
2060
|
extend SQL::OperatorBuilders
|
data/lib/sequel/version.rb
CHANGED
@@ -6,7 +6,7 @@ module Sequel
|
|
6
6
|
|
7
7
|
# The minor version of Sequel. Bumped for every non-patch level
|
8
8
|
# release, generally around once a month.
|
9
|
-
MINOR =
|
9
|
+
MINOR = 94
|
10
10
|
|
11
11
|
# The tiny version of Sequel. Usually 0, only bumped for bugfix
|
12
12
|
# releases that fix regressions from previous versions.
|