sequel 5.83.0 → 5.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/lib/sequel/adapters/ado/access.rb +2 -2
- data/lib/sequel/adapters/ado.rb +2 -2
- data/lib/sequel/adapters/amalgalite.rb +16 -1
- data/lib/sequel/adapters/ibmdb.rb +2 -1
- data/lib/sequel/adapters/jdbc/db2.rb +2 -2
- data/lib/sequel/adapters/jdbc/derby.rb +4 -2
- data/lib/sequel/adapters/jdbc/h2.rb +4 -4
- data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -2
- data/lib/sequel/adapters/jdbc/jtds.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +3 -3
- data/lib/sequel/adapters/jdbc/oracle.rb +6 -6
- data/lib/sequel/adapters/jdbc/postgresql.rb +5 -5
- data/lib/sequel/adapters/jdbc/sqlanywhere.rb +6 -6
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlserver.rb +3 -3
- data/lib/sequel/adapters/jdbc.rb +29 -15
- data/lib/sequel/adapters/mysql.rb +1 -1
- data/lib/sequel/adapters/mysql2.rb +10 -3
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +16 -0
- data/lib/sequel/adapters/postgres.rb +2 -1
- data/lib/sequel/adapters/shared/access.rb +1 -0
- data/lib/sequel/adapters/shared/db2.rb +8 -3
- data/lib/sequel/adapters/shared/mssql.rb +9 -8
- data/lib/sequel/adapters/shared/mysql.rb +16 -11
- data/lib/sequel/adapters/shared/oracle.rb +1 -0
- data/lib/sequel/adapters/shared/postgres.rb +438 -47
- data/lib/sequel/adapters/shared/sqlite.rb +9 -7
- data/lib/sequel/adapters/sqlite.rb +20 -2
- data/lib/sequel/adapters/tinytds.rb +2 -2
- data/lib/sequel/adapters/trilogy.rb +2 -3
- data/lib/sequel/ast_transformer.rb +2 -0
- data/lib/sequel/connection_pool/sharded_timed_queue.rb +42 -11
- data/lib/sequel/connection_pool/timed_queue.rb +33 -10
- data/lib/sequel/connection_pool.rb +8 -2
- data/lib/sequel/core.rb +31 -2
- data/lib/sequel/database/connecting.rb +1 -1
- data/lib/sequel/database/dataset_defaults.rb +3 -3
- data/lib/sequel/database/misc.rb +29 -11
- data/lib/sequel/database/query.rb +12 -12
- data/lib/sequel/database/schema_generator.rb +117 -16
- data/lib/sequel/database/schema_methods.rb +85 -30
- data/lib/sequel/dataset/actions.rb +83 -11
- data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +1 -1
- data/lib/sequel/dataset/placeholder_literalizer.rb +3 -0
- data/lib/sequel/dataset/prepared_statements.rb +76 -28
- data/lib/sequel/dataset/query.rb +26 -11
- data/lib/sequel/dataset/sql.rb +40 -17
- data/lib/sequel/extensions/async_thread_pool.rb +1 -1
- data/lib/sequel/extensions/caller_logging.rb +1 -3
- data/lib/sequel/extensions/connection_checkout_event_callback.rb +151 -0
- data/lib/sequel/extensions/connection_expiration.rb +44 -5
- data/lib/sequel/extensions/connection_validator.rb +15 -10
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/dataset_run.rb +41 -0
- data/lib/sequel/extensions/date_arithmetic.rb +6 -6
- data/lib/sequel/extensions/empty_array_consider_nulls.rb +7 -0
- data/lib/sequel/extensions/eval_inspect.rb +3 -1
- data/lib/sequel/extensions/inflector.rb +2 -2
- data/lib/sequel/extensions/lit_require_frozen.rb +131 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -12
- data/lib/sequel/extensions/migration.rb +38 -21
- data/lib/sequel/extensions/null_dataset.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +41 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +10 -3
- data/lib/sequel/extensions/pg_auto_parameterize_duplicate_query_detection.rb +191 -0
- data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +94 -10
- data/lib/sequel/extensions/pg_enum.rb +4 -4
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +10 -5
- data/lib/sequel/extensions/pg_json_ops.rb +674 -18
- data/lib/sequel/extensions/pg_multirange.rb +1 -1
- data/lib/sequel/extensions/pg_range.rb +14 -2
- data/lib/sequel/extensions/pg_row.rb +5 -3
- data/lib/sequel/extensions/pg_schema_caching.rb +90 -0
- data/lib/sequel/extensions/provenance.rb +1 -3
- data/lib/sequel/extensions/query_blocker.rb +172 -0
- data/lib/sequel/extensions/schema_caching.rb +24 -9
- data/lib/sequel/extensions/schema_dumper.rb +17 -5
- data/lib/sequel/extensions/set_literalizer.rb +20 -39
- data/lib/sequel/extensions/split_array_nil.rb +12 -2
- data/lib/sequel/extensions/sqlite_json_ops.rb +1 -1
- data/lib/sequel/extensions/string_agg.rb +2 -2
- data/lib/sequel/extensions/to_dot.rb +5 -0
- data/lib/sequel/extensions/virtual_row_method_block.rb +1 -0
- data/lib/sequel/model/associations.rb +215 -15
- data/lib/sequel/model/base.rb +198 -35
- data/lib/sequel/model/plugins.rb +12 -1
- data/lib/sequel/model.rb +1 -0
- data/lib/sequel/plugins/accessed_columns.rb +4 -0
- data/lib/sequel/plugins/active_model.rb +5 -6
- data/lib/sequel/plugins/association_pks.rb +2 -0
- data/lib/sequel/plugins/auto_validations.rb +2 -0
- data/lib/sequel/plugins/class_table_inheritance_constraint_validations.rb +82 -0
- data/lib/sequel/plugins/columns_updated.rb +4 -0
- data/lib/sequel/plugins/composition.rb +3 -1
- data/lib/sequel/plugins/constraint_validations.rb +15 -10
- data/lib/sequel/plugins/dataset_associations.rb +20 -1
- data/lib/sequel/plugins/deprecated_associations.rb +151 -0
- data/lib/sequel/plugins/detect_unnecessary_association_options.rb +164 -0
- data/lib/sequel/plugins/dirty.rb +9 -2
- data/lib/sequel/plugins/enum.rb +1 -1
- data/lib/sequel/plugins/forbid_lazy_load.rb +15 -1
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/insert_returning_select.rb +10 -1
- data/lib/sequel/plugins/inspect_pk.rb +44 -0
- data/lib/sequel/plugins/instance_filters.rb +8 -1
- data/lib/sequel/plugins/instance_hooks.rb +4 -0
- data/lib/sequel/plugins/inverted_subsets.rb +1 -0
- data/lib/sequel/plugins/json_serializer.rb +6 -10
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +21 -0
- data/lib/sequel/plugins/modification_detection.rb +2 -0
- data/lib/sequel/plugins/mssql_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +10 -5
- data/lib/sequel/plugins/paged_operations.rb +5 -2
- data/lib/sequel/plugins/pg_array_associations.rb +2 -2
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +6 -1
- data/lib/sequel/plugins/pg_auto_validate_enums.rb +88 -0
- data/lib/sequel/plugins/pg_eager_any_typed_array.rb +95 -0
- data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +6 -6
- data/lib/sequel/plugins/serialization.rb +23 -6
- data/lib/sequel/plugins/serialization_modification_detection.rb +4 -0
- data/lib/sequel/plugins/single_statement_dataset_destroy.rb +49 -0
- data/lib/sequel/plugins/split_values.rb +12 -0
- data/lib/sequel/plugins/sql_comments.rb +7 -2
- data/lib/sequel/plugins/static_cache.rb +13 -0
- data/lib/sequel/plugins/static_cache_cache.rb +50 -13
- data/lib/sequel/plugins/subset_conditions.rb +85 -5
- data/lib/sequel/plugins/subset_static_cache.rb +278 -0
- data/lib/sequel/plugins/table_select.rb +7 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +4 -0
- data/lib/sequel/plugins/unused_associations.rb +11 -3
- data/lib/sequel/plugins/update_primary_key.rb +4 -0
- data/lib/sequel/plugins/validation_class_methods.rb +1 -1
- data/lib/sequel/plugins/validation_contexts.rb +4 -0
- data/lib/sequel/sql.rb +27 -12
- data/lib/sequel/version.rb +1 -1
- metadata +17 -240
- data/CHANGELOG +0 -1393
- data/README.rdoc +0 -936
- data/doc/advanced_associations.rdoc +0 -884
- data/doc/association_basics.rdoc +0 -1859
- data/doc/bin_sequel.rdoc +0 -146
- data/doc/cheat_sheet.rdoc +0 -255
- data/doc/code_order.rdoc +0 -104
- data/doc/core_extensions.rdoc +0 -405
- data/doc/dataset_basics.rdoc +0 -96
- data/doc/dataset_filtering.rdoc +0 -222
- data/doc/extensions.rdoc +0 -77
- data/doc/fork_safety.rdoc +0 -84
- data/doc/mass_assignment.rdoc +0 -98
- data/doc/migration.rdoc +0 -660
- data/doc/model_dataset_method_design.rdoc +0 -129
- data/doc/model_hooks.rdoc +0 -254
- data/doc/model_plugins.rdoc +0 -270
- data/doc/mssql_stored_procedures.rdoc +0 -43
- data/doc/object_model.rdoc +0 -563
- data/doc/opening_databases.rdoc +0 -439
- data/doc/postgresql.rdoc +0 -611
- data/doc/prepared_statements.rdoc +0 -144
- data/doc/querying.rdoc +0 -1070
- data/doc/reflection.rdoc +0 -120
- data/doc/release_notes/5.0.0.txt +0 -159
- data/doc/release_notes/5.1.0.txt +0 -31
- data/doc/release_notes/5.10.0.txt +0 -84
- data/doc/release_notes/5.11.0.txt +0 -83
- data/doc/release_notes/5.12.0.txt +0 -141
- data/doc/release_notes/5.13.0.txt +0 -27
- data/doc/release_notes/5.14.0.txt +0 -63
- data/doc/release_notes/5.15.0.txt +0 -39
- data/doc/release_notes/5.16.0.txt +0 -110
- data/doc/release_notes/5.17.0.txt +0 -31
- data/doc/release_notes/5.18.0.txt +0 -69
- data/doc/release_notes/5.19.0.txt +0 -28
- data/doc/release_notes/5.2.0.txt +0 -33
- data/doc/release_notes/5.20.0.txt +0 -89
- data/doc/release_notes/5.21.0.txt +0 -87
- data/doc/release_notes/5.22.0.txt +0 -48
- data/doc/release_notes/5.23.0.txt +0 -56
- data/doc/release_notes/5.24.0.txt +0 -56
- data/doc/release_notes/5.25.0.txt +0 -32
- data/doc/release_notes/5.26.0.txt +0 -35
- data/doc/release_notes/5.27.0.txt +0 -21
- data/doc/release_notes/5.28.0.txt +0 -16
- data/doc/release_notes/5.29.0.txt +0 -22
- data/doc/release_notes/5.3.0.txt +0 -121
- data/doc/release_notes/5.30.0.txt +0 -20
- data/doc/release_notes/5.31.0.txt +0 -148
- data/doc/release_notes/5.32.0.txt +0 -46
- data/doc/release_notes/5.33.0.txt +0 -24
- data/doc/release_notes/5.34.0.txt +0 -40
- data/doc/release_notes/5.35.0.txt +0 -56
- data/doc/release_notes/5.36.0.txt +0 -60
- data/doc/release_notes/5.37.0.txt +0 -30
- data/doc/release_notes/5.38.0.txt +0 -28
- data/doc/release_notes/5.39.0.txt +0 -19
- data/doc/release_notes/5.4.0.txt +0 -80
- data/doc/release_notes/5.40.0.txt +0 -40
- data/doc/release_notes/5.41.0.txt +0 -25
- data/doc/release_notes/5.42.0.txt +0 -136
- data/doc/release_notes/5.43.0.txt +0 -98
- data/doc/release_notes/5.44.0.txt +0 -32
- data/doc/release_notes/5.45.0.txt +0 -34
- data/doc/release_notes/5.46.0.txt +0 -87
- data/doc/release_notes/5.47.0.txt +0 -59
- data/doc/release_notes/5.48.0.txt +0 -14
- data/doc/release_notes/5.49.0.txt +0 -59
- data/doc/release_notes/5.5.0.txt +0 -61
- data/doc/release_notes/5.50.0.txt +0 -78
- data/doc/release_notes/5.51.0.txt +0 -47
- data/doc/release_notes/5.52.0.txt +0 -87
- data/doc/release_notes/5.53.0.txt +0 -23
- data/doc/release_notes/5.54.0.txt +0 -27
- data/doc/release_notes/5.55.0.txt +0 -21
- data/doc/release_notes/5.56.0.txt +0 -51
- data/doc/release_notes/5.57.0.txt +0 -23
- data/doc/release_notes/5.58.0.txt +0 -31
- data/doc/release_notes/5.59.0.txt +0 -73
- data/doc/release_notes/5.6.0.txt +0 -31
- data/doc/release_notes/5.60.0.txt +0 -22
- data/doc/release_notes/5.61.0.txt +0 -43
- data/doc/release_notes/5.62.0.txt +0 -132
- data/doc/release_notes/5.63.0.txt +0 -33
- data/doc/release_notes/5.64.0.txt +0 -50
- data/doc/release_notes/5.65.0.txt +0 -21
- data/doc/release_notes/5.66.0.txt +0 -24
- data/doc/release_notes/5.67.0.txt +0 -32
- data/doc/release_notes/5.68.0.txt +0 -61
- data/doc/release_notes/5.69.0.txt +0 -26
- data/doc/release_notes/5.7.0.txt +0 -108
- data/doc/release_notes/5.70.0.txt +0 -35
- data/doc/release_notes/5.71.0.txt +0 -21
- data/doc/release_notes/5.72.0.txt +0 -33
- data/doc/release_notes/5.73.0.txt +0 -66
- data/doc/release_notes/5.74.0.txt +0 -45
- data/doc/release_notes/5.75.0.txt +0 -35
- data/doc/release_notes/5.76.0.txt +0 -86
- data/doc/release_notes/5.77.0.txt +0 -63
- data/doc/release_notes/5.78.0.txt +0 -67
- data/doc/release_notes/5.79.0.txt +0 -28
- data/doc/release_notes/5.8.0.txt +0 -170
- data/doc/release_notes/5.80.0.txt +0 -40
- data/doc/release_notes/5.81.0.txt +0 -31
- data/doc/release_notes/5.82.0.txt +0 -61
- data/doc/release_notes/5.83.0.txt +0 -56
- data/doc/release_notes/5.9.0.txt +0 -99
- data/doc/schema_modification.rdoc +0 -679
- data/doc/security.rdoc +0 -443
- data/doc/sharding.rdoc +0 -286
- data/doc/sql.rdoc +0 -648
- data/doc/testing.rdoc +0 -204
- data/doc/thread_safety.rdoc +0 -15
- data/doc/transactions.rdoc +0 -250
- data/doc/validations.rdoc +0 -558
- data/doc/virtual_rows.rdoc +0 -265
|
@@ -46,8 +46,10 @@ module Sequel
|
|
|
46
46
|
# Initialize the data structures used by this extension.
|
|
47
47
|
def self.extended(pool)
|
|
48
48
|
case pool.pool_type
|
|
49
|
-
when :
|
|
50
|
-
|
|
49
|
+
when :threaded, :sharded_threaded, :timed_queue, :sharded_timed_queue
|
|
50
|
+
nil
|
|
51
|
+
else
|
|
52
|
+
raise Error, "cannot load connection_expiration extension if using single or sharded_single connection pool (or other unsupported connection pool)"
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
pool.instance_exec do
|
|
@@ -55,6 +57,39 @@ module Sequel
|
|
|
55
57
|
@connection_expiration_timestamps ||= {}
|
|
56
58
|
@connection_expiration_timeout ||= 14400
|
|
57
59
|
@connection_expiration_random_delay ||= 0
|
|
60
|
+
|
|
61
|
+
# Record an expiration timestamp for any connections that already
|
|
62
|
+
# exist in the pool, so that a connection opened before the extension
|
|
63
|
+
# was loaded (e.g. via Sequel.connect) will eventually be expired.
|
|
64
|
+
register = method(:register_connection_expiration_time)
|
|
65
|
+
|
|
66
|
+
case pool_type
|
|
67
|
+
when :timed_queue, :sharded_timed_queue
|
|
68
|
+
register_queued_connections = lambda do |queue|
|
|
69
|
+
conns = []
|
|
70
|
+
while conn = queue.pop(timeout: 0)
|
|
71
|
+
conns << conn
|
|
72
|
+
end
|
|
73
|
+
conns.each do |conn|
|
|
74
|
+
queue.push(register_connection_expiration_time(conn))
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
case pool_type
|
|
80
|
+
when :threaded
|
|
81
|
+
@available_connections.each(®ister)
|
|
82
|
+
@allocated.each_value(®ister)
|
|
83
|
+
when :sharded_threaded
|
|
84
|
+
@available_connections.each_value{|conns| conns.each(®ister)}
|
|
85
|
+
@allocated.each_value{|threads| threads.each_value(®ister)}
|
|
86
|
+
when :timed_queue
|
|
87
|
+
register_queued_connections.call(@queue)
|
|
88
|
+
@allocated.each_value(®ister)
|
|
89
|
+
else # when :sharded_timed_queue
|
|
90
|
+
@queues.each_value(®ister_queued_connections)
|
|
91
|
+
@allocated.each_value{|threads| threads.each_value(®ister)}
|
|
92
|
+
end
|
|
58
93
|
end
|
|
59
94
|
end
|
|
60
95
|
end
|
|
@@ -69,8 +104,12 @@ module Sequel
|
|
|
69
104
|
|
|
70
105
|
# Record the time the connection was created.
|
|
71
106
|
def make_new(*)
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
register_connection_expiration_time(super)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Record an expiration entry for a connection, returns the connection.
|
|
111
|
+
def register_connection_expiration_time(conn)
|
|
112
|
+
@connection_expiration_timestamps[conn] ||= [Sequel.start_timer, @connection_expiration_timeout + (rand * @connection_expiration_random_delay)].freeze
|
|
74
113
|
conn
|
|
75
114
|
end
|
|
76
115
|
|
|
@@ -91,7 +130,7 @@ module Sequel
|
|
|
91
130
|
sync{@allocated.delete(Sequel.current)}
|
|
92
131
|
end
|
|
93
132
|
|
|
94
|
-
|
|
133
|
+
disconnect_acquired_connection(conn, *a)
|
|
95
134
|
redo
|
|
96
135
|
end
|
|
97
136
|
end
|
|
@@ -105,18 +105,23 @@ module Sequel
|
|
|
105
105
|
1.times do
|
|
106
106
|
if (conn = super) &&
|
|
107
107
|
(timer = sync{@connection_timestamps.delete(conn)}) &&
|
|
108
|
-
Sequel.elapsed_seconds_since(timer) > @connection_validation_timeout
|
|
109
|
-
!db.valid_connection?(conn)
|
|
108
|
+
Sequel.elapsed_seconds_since(timer) > @connection_validation_timeout
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
begin
|
|
111
|
+
valid = db.valid_connection?(conn)
|
|
112
|
+
ensure
|
|
113
|
+
unless valid
|
|
114
|
+
case pool_type
|
|
115
|
+
when :sharded_threaded, :sharded_timed_queue
|
|
116
|
+
sync{@allocated[a.last].delete(Sequel.current)}
|
|
117
|
+
else
|
|
118
|
+
sync{@allocated.delete(Sequel.current)}
|
|
119
|
+
end
|
|
117
120
|
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
disconnect_acquired_connection(conn, *a)
|
|
122
|
+
redo if valid == false
|
|
123
|
+
end
|
|
124
|
+
end
|
|
120
125
|
end
|
|
121
126
|
end
|
|
122
127
|
|
|
@@ -436,7 +436,7 @@ module Sequel
|
|
|
436
436
|
else
|
|
437
437
|
raise Error, "validates includes with a range only supports integers currently, cannot handle: #{arg.inspect}"
|
|
438
438
|
end
|
|
439
|
-
elsif arg.is_a?(Array)
|
|
439
|
+
elsif arg.is_a?(Array) || arg.is_a?(Set)
|
|
440
440
|
if arg.all?{|x| x.is_a?(Integer)}
|
|
441
441
|
validation_type = :includes_int_array
|
|
442
442
|
elsif arg.all?{|x| x.is_a?(String)}
|
|
@@ -444,9 +444,9 @@ module Sequel
|
|
|
444
444
|
else
|
|
445
445
|
raise Error, "validates includes with an array only supports strings and integers currently, cannot handle: #{arg.inspect}"
|
|
446
446
|
end
|
|
447
|
-
arg =
|
|
447
|
+
arg = Sequel.array_or_set_join(arg, ',')
|
|
448
448
|
else
|
|
449
|
-
raise Error, "validates includes only supports arrays and ranges currently, cannot handle: #{arg.inspect}"
|
|
449
|
+
raise Error, "validates includes only supports arrays, sets, and ranges currently, cannot handle: #{arg.inspect}"
|
|
450
450
|
end
|
|
451
451
|
when :like, :ilike
|
|
452
452
|
generator.constraint(constraint, constraint_validation_expression(columns, allow_nil){|c| Sequel.public_send(validation_type, c, arg)})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The dataset_run extension is designed for cases where you want
|
|
4
|
+
# to use dataset methods to build a query, but want to run that
|
|
5
|
+
# query without returning a result. The most common need would
|
|
6
|
+
# be to easily use placeholders in an SQL string, which Database#run
|
|
7
|
+
# does not support directly.
|
|
8
|
+
#
|
|
9
|
+
# You can load this extension into specific datasets:
|
|
10
|
+
#
|
|
11
|
+
# ds = DB["GRANT SELECT ON ? TO ?", :table, :user]
|
|
12
|
+
# ds = ds.extension(:dataset_run)
|
|
13
|
+
# ds.run
|
|
14
|
+
#
|
|
15
|
+
# Or you can load it into all of a database's datasets, which
|
|
16
|
+
# is probably the desired behavior if you are using this extension:
|
|
17
|
+
#
|
|
18
|
+
# DB.extension(:dataset_run)
|
|
19
|
+
# DB["GRANT SELECT ON ? TO ?", :table, :user].run
|
|
20
|
+
#
|
|
21
|
+
# Related module: Sequel::DatasetRun
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
module Sequel
|
|
25
|
+
module DatasetRun
|
|
26
|
+
# Run the dataset's SQL on the database. Returns NULL. This is
|
|
27
|
+
# useful when you want to run SQL without returning a result.
|
|
28
|
+
#
|
|
29
|
+
# DB["GRANT SELECT ON ? TO ?", :table, :user].run
|
|
30
|
+
# # GRANT SELECT ON "table" TO "user"
|
|
31
|
+
def run
|
|
32
|
+
if server = @opts[:server]
|
|
33
|
+
db.run(sql.freeze, :server=>server)
|
|
34
|
+
else
|
|
35
|
+
db.run(sql.freeze)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
Dataset.register_extension(:dataset_run, DatasetRun)
|
|
41
|
+
end
|
|
@@ -82,12 +82,12 @@ module Sequel
|
|
|
82
82
|
DURATION_UNITS = [:years, :months, :days, :hours, :minutes, :seconds].freeze
|
|
83
83
|
DEF_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s.freeze}).freeze
|
|
84
84
|
POSTGRES_DURATION_UNITS = DURATION_UNITS.zip([:years, :months, :days, :hours, :mins, :secs].map{|s| s.to_s.freeze}).freeze
|
|
85
|
-
MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1]).freeze}).freeze
|
|
86
|
-
MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1]).freeze}).freeze
|
|
85
|
+
MYSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.upcase[0...-1].freeze).freeze}).freeze
|
|
86
|
+
MSSQL_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s[0...-1].freeze).freeze}).freeze
|
|
87
87
|
H2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| s.to_s[0...-1].freeze}).freeze
|
|
88
|
-
DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}").freeze}).freeze
|
|
88
|
+
DERBY_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit("SQL_TSI_#{s.to_s.upcase[0...-1]}".freeze).freeze}).freeze
|
|
89
89
|
ACCESS_DURATION_UNITS = DURATION_UNITS.zip(%w'yyyy m d h n s'.map(&:freeze)).freeze
|
|
90
|
-
DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s).freeze}).freeze
|
|
90
|
+
DB2_DURATION_UNITS = DURATION_UNITS.zip(DURATION_UNITS.map{|s| Sequel.lit(s.to_s.freeze).freeze}).freeze
|
|
91
91
|
|
|
92
92
|
# Append the SQL fragment for the DateAdd expression to the SQL query.
|
|
93
93
|
def date_add_sql_append(sql, da)
|
|
@@ -107,7 +107,7 @@ module Sequel
|
|
|
107
107
|
placeholder = []
|
|
108
108
|
vals = []
|
|
109
109
|
each_valid_interval_unit(h, POSTGRES_DURATION_UNITS) do |value, sql_unit|
|
|
110
|
-
placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := "
|
|
110
|
+
placeholder << "#{', ' unless placeholder.empty?}#{sql_unit} := ".freeze
|
|
111
111
|
vals << value
|
|
112
112
|
end
|
|
113
113
|
interval = Sequel.function(:make_interval, Sequel.lit(placeholder, *vals)) unless vals.empty?
|
|
@@ -156,7 +156,7 @@ module Sequel
|
|
|
156
156
|
expr = Sequel.cast_string(expr) + ' 00:00:00'
|
|
157
157
|
end
|
|
158
158
|
each_valid_interval_unit(h, DERBY_DURATION_UNITS) do |value, sql_unit|
|
|
159
|
-
expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ", ", timestamp(", "))}"], value, expr)
|
|
159
|
+
expr = Sequel.lit(["{fn timestampadd(#{sql_unit}, ".freeze, ", timestamp(", "))}"], value, expr)
|
|
160
160
|
end
|
|
161
161
|
when :oracle
|
|
162
162
|
each_valid_interval_unit(h, MYSQL_DURATION_UNITS) do |value, sql_unit|
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
# DB[:test].exclude(name: [])
|
|
10
10
|
# # SELECT * FROM test WHERE (name = name)
|
|
11
11
|
#
|
|
12
|
+
# This works for sets in addition to arrays:
|
|
13
|
+
#
|
|
14
|
+
# DB[:test].where(name: Set[])
|
|
15
|
+
# # SELECT * FROM test WHERE (name != name)
|
|
16
|
+
# DB[:test].exclude(name: Set[])
|
|
17
|
+
# # SELECT * FROM test WHERE (name = name)
|
|
18
|
+
#
|
|
12
19
|
# The default Sequel behavior is to ignore NULLs, as the above
|
|
13
20
|
# query is not generally optimized well by databases.
|
|
14
21
|
#
|
|
@@ -34,6 +34,8 @@ module Sequel
|
|
|
34
34
|
"#{obj.class}.new(#{obj.to_a.inspect})"
|
|
35
35
|
when Array
|
|
36
36
|
"[#{obj.map{|o| eval_inspect(o)}.join(', ')}]"
|
|
37
|
+
when Set
|
|
38
|
+
"Set[#{obj.map{|o| eval_inspect(o)}.join(', ')}]"
|
|
37
39
|
when Hash
|
|
38
40
|
"{#{obj.map{|k, v| "#{eval_inspect(k)} => #{eval_inspect(v)}"}.join(', ')}}"
|
|
39
41
|
when Time
|
|
@@ -66,7 +68,7 @@ module Sequel
|
|
|
66
68
|
# in the order they were defined.
|
|
67
69
|
klass = self.class
|
|
68
70
|
args = inspect_args.map do |arg|
|
|
69
|
-
if arg.is_a?(String) && arg
|
|
71
|
+
if arg.is_a?(String) && arg.start_with?('*')
|
|
70
72
|
# Special case string arguments starting with *, indicating that
|
|
71
73
|
# they should return an array to be splatted as the remaining arguments.
|
|
72
74
|
# 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.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
#
|
|
3
|
+
# The lit_require_frozen extension disallows the use of unfrozen strings
|
|
4
|
+
# as literal strings in database and dataset methods. If you try to use an
|
|
5
|
+
# unfrozen string as a literal string for a dataset using this extension,
|
|
6
|
+
# an exception will be raised.
|
|
7
|
+
#
|
|
8
|
+
# While this works for all Ruby versions, it is designed for use on Ruby 3+
|
|
9
|
+
# where all files are using the frozen-string-literal magic comment. In this
|
|
10
|
+
# case, uninterpolated literal strings are frozen, but interpolated strings
|
|
11
|
+
# are not frozen. This allows you to catch potentially dangerous code:
|
|
12
|
+
#
|
|
13
|
+
# # Probably safe, no exception raised
|
|
14
|
+
# DB["SELECT * FROM t WHERE c > :v", v: user_provided_string)
|
|
15
|
+
#
|
|
16
|
+
# # Potentially unsafe, raises Sequel::LitRequireFrozen::Error
|
|
17
|
+
# DB["SELECT * FROM t WHERE c > '#{user_provided_string}'"]
|
|
18
|
+
#
|
|
19
|
+
# The assumption made is that a frozen string is unlikely to contain unsafe
|
|
20
|
+
# input, while an unfrozen string has potentially been interpolated and may
|
|
21
|
+
# contain unsafe input.
|
|
22
|
+
#
|
|
23
|
+
# This disallows the the following cases:
|
|
24
|
+
#
|
|
25
|
+
# * Sequel::LiteralString instances that are unfrozen and are not based on a
|
|
26
|
+
# frozen string
|
|
27
|
+
# * Sequel::SQL::PlaceholderLiteralString instances when the placeholder string
|
|
28
|
+
# is not frozen
|
|
29
|
+
# * Unfrozen strings passed to Database#<< or #[] or Dataset#with_sql
|
|
30
|
+
#
|
|
31
|
+
# To use this extension, load it into the database:
|
|
32
|
+
#
|
|
33
|
+
# DB.extension :lit_require_frozen
|
|
34
|
+
#
|
|
35
|
+
# It can also be loaded into individual datasets:
|
|
36
|
+
#
|
|
37
|
+
# ds = DB[:t].extension(:lit_require_frozen)
|
|
38
|
+
#
|
|
39
|
+
# Assuming you have good test coverage, it is recommended to only load
|
|
40
|
+
# this extension when testing.
|
|
41
|
+
#
|
|
42
|
+
# Related module: Sequel::LitRequireFrozen
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
module Sequel
|
|
46
|
+
class LiteralString
|
|
47
|
+
# The string used when creating the literal string (first argument to
|
|
48
|
+
# Sequel::LiteralString.new). This may be nil if no string was provided,
|
|
49
|
+
# or if the litral string was created before this extension was required.
|
|
50
|
+
attr_reader :source
|
|
51
|
+
|
|
52
|
+
def initialize(*a)
|
|
53
|
+
@source = a.first
|
|
54
|
+
super
|
|
55
|
+
end
|
|
56
|
+
# :nocov:
|
|
57
|
+
ruby2_keywords :initialize if respond_to?(:ruby2_keywords, true)
|
|
58
|
+
# :nocov:
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
module LitRequireFrozen
|
|
62
|
+
# Error class raised for using unfrozen literal string.
|
|
63
|
+
class Error < Sequel::Error
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module DatabaseMethods
|
|
67
|
+
def self.extended(db)
|
|
68
|
+
db.extend_datasets(DatasetMethods)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Check given SQL is frozen before running it.
|
|
72
|
+
def run(sql, opts=OPTS)
|
|
73
|
+
@default_dataset.with_sql(sql)
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
module DatasetMethods
|
|
79
|
+
# Check given SQL is not an unfrozen string.
|
|
80
|
+
def with_sql(sql, *args)
|
|
81
|
+
_check_unfrozen_literal_string(sql)
|
|
82
|
+
super
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Check that placeholder string is frozen (or all entries
|
|
86
|
+
# in placeholder array are frozen).
|
|
87
|
+
def placeholder_literal_string_sql_append(sql, pls)
|
|
88
|
+
str = pls.str
|
|
89
|
+
|
|
90
|
+
if str.is_a?(Array)
|
|
91
|
+
str.each do |s|
|
|
92
|
+
_check_unfrozen_literal_string(s)
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
_check_unfrozen_literal_string(str)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
super
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
# Base method that other methods used to check for whether a string should be allowed
|
|
104
|
+
# as literal SQL. Allows non-strings as well as frozen strings.
|
|
105
|
+
def _check_unfrozen_literal_string(str)
|
|
106
|
+
return if !str.is_a?(String) || str.frozen?
|
|
107
|
+
|
|
108
|
+
if str.is_a?(LiteralString)
|
|
109
|
+
_check_unfrozen_literal_string(str.source)
|
|
110
|
+
else
|
|
111
|
+
raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Check literal strings appended to SQL.
|
|
116
|
+
def literal_literal_string_append(sql, v)
|
|
117
|
+
_check_unfrozen_literal_string(v)
|
|
118
|
+
super
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Check static SQL is not frozen.
|
|
122
|
+
def static_sql(sql)
|
|
123
|
+
_check_unfrozen_literal_string(sql)
|
|
124
|
+
super
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
|
|
130
|
+
Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
|
|
131
|
+
end
|
|
@@ -37,18 +37,11 @@ module Sequel
|
|
|
37
37
|
value.to_s
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
else
|
|
47
|
-
# :nocov:
|
|
48
|
-
def _typecast_value_string_to_decimal(value)
|
|
49
|
-
BigDecimal(value)
|
|
50
|
-
end
|
|
51
|
-
# :nocov:
|
|
40
|
+
# Typecast invalid BigDecimal to 0.0.
|
|
41
|
+
def _typecast_value_string_to_decimal(value)
|
|
42
|
+
BigDecimal(value)
|
|
43
|
+
rescue
|
|
44
|
+
BigDecimal('0.0')
|
|
52
45
|
end
|
|
53
46
|
end
|
|
54
47
|
|
|
@@ -186,22 +186,19 @@ module Sequel
|
|
|
186
186
|
# and returns a new block that reverses the actions taken by
|
|
187
187
|
# the given block.
|
|
188
188
|
def reverse(&block)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
Proc.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
send(*a, &pr)
|
|
203
|
-
end
|
|
204
|
-
end
|
|
189
|
+
instance_exec(&block)
|
|
190
|
+
rescue NoMethodError => e
|
|
191
|
+
Proc.new{raise Sequel::Error, "irreversible migration method \"#{e.name}\" used in #{block.source_location.first}, you may need to write your own down method"}
|
|
192
|
+
rescue => e
|
|
193
|
+
Proc.new{raise Sequel::Error, "unable to reverse migration due to #{e.class} in #{block.source_location.first}, you may need to write your own down method"}
|
|
194
|
+
else
|
|
195
|
+
actions = @actions.reverse
|
|
196
|
+
Proc.new do
|
|
197
|
+
actions.each do |a|
|
|
198
|
+
pr = a.last.is_a?(Proc) ? a.pop : nil
|
|
199
|
+
# Allow calling private methods as the reversing methods are private
|
|
200
|
+
send(*a, &pr)
|
|
201
|
+
end
|
|
205
202
|
end
|
|
206
203
|
end
|
|
207
204
|
|
|
@@ -223,7 +220,7 @@ module Sequel
|
|
|
223
220
|
@actions << [:drop_join_table, *args]
|
|
224
221
|
end
|
|
225
222
|
|
|
226
|
-
def create_table(name, opts=OPTS)
|
|
223
|
+
def create_table(name, opts=OPTS, &_)
|
|
227
224
|
@actions << [:drop_table, name, opts]
|
|
228
225
|
end
|
|
229
226
|
|
|
@@ -270,7 +267,7 @@ module Sequel
|
|
|
270
267
|
end
|
|
271
268
|
|
|
272
269
|
def add_primary_key(*args)
|
|
273
|
-
|
|
270
|
+
super if args.first.is_a?(Array)
|
|
274
271
|
@actions << [:drop_column, args.first]
|
|
275
272
|
end
|
|
276
273
|
|
|
@@ -287,6 +284,10 @@ module Sequel
|
|
|
287
284
|
def set_column_allow_null(name, allow_null=true)
|
|
288
285
|
@actions << [:set_column_allow_null, name, !allow_null]
|
|
289
286
|
end
|
|
287
|
+
|
|
288
|
+
def set_column_not_null(name)
|
|
289
|
+
@actions << [:set_column_allow_null, name]
|
|
290
|
+
end
|
|
290
291
|
end
|
|
291
292
|
|
|
292
293
|
# The preferred method for writing Sequel migrations, using a DSL:
|
|
@@ -371,7 +372,7 @@ module Sequel
|
|
|
371
372
|
#
|
|
372
373
|
# Part of the +migration+ extension.
|
|
373
374
|
class Migrator
|
|
374
|
-
MIGRATION_FILE_PATTERN = /\A(\d+)_
|
|
375
|
+
MIGRATION_FILE_PATTERN = /\A(\d+)_(.+)\.rb\z/i.freeze
|
|
375
376
|
|
|
376
377
|
# Mutex used around migration file loading
|
|
377
378
|
MUTEX = Mutex.new
|
|
@@ -791,7 +792,23 @@ module Sequel
|
|
|
791
792
|
next unless MIGRATION_FILE_PATTERN.match(file)
|
|
792
793
|
files << File.join(directory, file)
|
|
793
794
|
end
|
|
794
|
-
files.
|
|
795
|
+
files.sort! do |a, b|
|
|
796
|
+
a_ver, a_name = split_migration_filename(a)
|
|
797
|
+
b_ver, b_name = split_migration_filename(b)
|
|
798
|
+
x = a_ver <=> b_ver
|
|
799
|
+
if x.zero?
|
|
800
|
+
x = a_name <=> b_name
|
|
801
|
+
end
|
|
802
|
+
x
|
|
803
|
+
end
|
|
804
|
+
files
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
# Return an integer and name (without extension) for the given path.
|
|
808
|
+
def split_migration_filename(path)
|
|
809
|
+
version, name = MIGRATION_FILE_PATTERN.match(File.basename(path)).captures
|
|
810
|
+
version = version.to_i
|
|
811
|
+
[version, name]
|
|
795
812
|
end
|
|
796
813
|
|
|
797
814
|
# Returns tuples of migration, filename, and direction
|
|
@@ -825,7 +842,7 @@ module Sequel
|
|
|
825
842
|
begin
|
|
826
843
|
db.create_table(table){String c, :primary_key=>true}
|
|
827
844
|
rescue Sequel::DatabaseError => e
|
|
828
|
-
if db.database_type == :mysql && e.message
|
|
845
|
+
if db.database_type == :mysql && e.message.include?('max key length')
|
|
829
846
|
# Handle case where MySQL is used with utf8mb4 charset default, which
|
|
830
847
|
# only allows a maximum length of about 190 characters for string
|
|
831
848
|
# primary keys due to InnoDB limitations.
|
|
@@ -63,12 +63,12 @@ module Sequel
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
# Return self without sending a database query, never yielding.
|
|
66
|
-
def each
|
|
66
|
+
def each(&_)
|
|
67
67
|
self
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# Return nil without sending a database query, never yielding.
|
|
71
|
-
def fetch_rows(sql)
|
|
71
|
+
def fetch_rows(sql, &_)
|
|
72
72
|
nil
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -56,6 +56,13 @@
|
|
|
56
56
|
# ia.join(':', ' ') # array_to_string(int_array_column, ':', ' ')
|
|
57
57
|
# ia.unnest # unnest(int_array_column)
|
|
58
58
|
# ia.unnest(:b) # unnest(int_array_column, b)
|
|
59
|
+
#
|
|
60
|
+
# On PostgreSQL 18+, the following are supported:
|
|
61
|
+
#
|
|
62
|
+
# ia.sort # array_sort(int_array_column)
|
|
63
|
+
# ia.sort(desc: true) # array_sort(int_array_column, true)
|
|
64
|
+
# ia.sort(nulls: :first) # array_sort(int_array_column, false, true)
|
|
65
|
+
# ia.reverse # array_reverse(int_array_column)
|
|
59
66
|
#
|
|
60
67
|
# See the PostgreSQL array function and operator documentation for more
|
|
61
68
|
# details on what these functions and operators do.
|
|
@@ -217,6 +224,40 @@ module Sequel
|
|
|
217
224
|
ArrayOp.new(function(:array_replace, element, replacement))
|
|
218
225
|
end
|
|
219
226
|
|
|
227
|
+
# Call the array_reverse method:
|
|
228
|
+
#
|
|
229
|
+
# array_op.reverse # array_reverse(array)
|
|
230
|
+
def reverse
|
|
231
|
+
function(:array_reverse)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Call the array_sort method. Options:
|
|
235
|
+
#
|
|
236
|
+
# :desc :: Sort in descending order instead of ascending order.
|
|
237
|
+
# :nulls :: If sorting in ascending order and value is :first, include NULL
|
|
238
|
+
# values before non-NULL values. If sorting in descending order and
|
|
239
|
+
# value is :last, include non-NULL values before NULL values.
|
|
240
|
+
#
|
|
241
|
+
# array_op.sort # array_sort(array)
|
|
242
|
+
# array_op.sort(desc: true) # array_sort(array, true)
|
|
243
|
+
# array_op.sort(nulls: :first) # array_sort(array, false, true)
|
|
244
|
+
# array_op.sort(desc: true, nulls: :last) # array_sort(array, true, false)
|
|
245
|
+
def sort(opts=OPTS)
|
|
246
|
+
desc = opts[:desc]
|
|
247
|
+
nulls = opts[:nulls]
|
|
248
|
+
if desc
|
|
249
|
+
if nulls == :last
|
|
250
|
+
function(:array_sort, true, false)
|
|
251
|
+
else
|
|
252
|
+
function(:array_sort, true)
|
|
253
|
+
end
|
|
254
|
+
elsif nulls == :first
|
|
255
|
+
function(:array_sort, false, true)
|
|
256
|
+
else
|
|
257
|
+
function(:array_sort)
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
220
261
|
# Call the array_to_string method:
|
|
221
262
|
#
|
|
222
263
|
# array_op.join # array_to_string(array, '')
|
|
@@ -348,6 +348,8 @@ module Sequel
|
|
|
348
348
|
# automatically parameterized.
|
|
349
349
|
def auto_param_type(v)
|
|
350
350
|
case v
|
|
351
|
+
when Symbol
|
|
352
|
+
false
|
|
351
353
|
when String
|
|
352
354
|
case v
|
|
353
355
|
when LiteralString
|
|
@@ -394,7 +396,7 @@ module Sequel
|
|
|
394
396
|
# there can be more than one parameter per column, so this doesn't prevent going
|
|
395
397
|
# over the limit, though it does make it less likely.
|
|
396
398
|
def default_import_slice
|
|
397
|
-
40
|
|
399
|
+
@opts[:no_auto_parameterize] ? super : 40
|
|
398
400
|
end
|
|
399
401
|
|
|
400
402
|
# Handle parameterization of multi_insert_sql
|
|
@@ -406,9 +408,9 @@ module Sequel
|
|
|
406
408
|
end
|
|
407
409
|
end
|
|
408
410
|
|
|
409
|
-
# Whether the given argument is an array of integers or NULL values, recursively.
|
|
411
|
+
# Whether the given argument is an array or set of integers or NULL values, recursively.
|
|
410
412
|
def _integer_array?(v)
|
|
411
|
-
Array === v && v.all?{|x| nil == x || Integer === x}
|
|
413
|
+
(Array === v || Set === v) && v.all?{|x| nil == x || Integer === x}
|
|
412
414
|
end
|
|
413
415
|
|
|
414
416
|
# Create the bound variable string that will be used for the IN (int, ...) to = ANY($)
|
|
@@ -463,6 +465,11 @@ module Sequel
|
|
|
463
465
|
@opts[:no_auto_parameterize] ? super : QueryString.new
|
|
464
466
|
end
|
|
465
467
|
|
|
468
|
+
# A mutable string used as the prefix when explaining a query.
|
|
469
|
+
def explain_sql_string_origin(opts)
|
|
470
|
+
@opts[:no_auto_parameterize] ? super : (QueryString.new << super)
|
|
471
|
+
end
|
|
472
|
+
|
|
466
473
|
# If subquery uses with_sql with a method name symbol, get the dataset
|
|
467
474
|
# with_sql was called on, and use that as the subquery, recording the
|
|
468
475
|
# arguments to with_sql that will be used to calculate the sql.
|