sequel 5.61.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 +46 -0
- data/README.rdoc +20 -19
- data/doc/advanced_associations.rdoc +13 -13
- data/doc/association_basics.rdoc +21 -15
- data/doc/cheat_sheet.rdoc +3 -3
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +4 -4
- data/doc/postgresql.rdoc +8 -8
- data/doc/querying.rdoc +1 -1
- 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 +13 -13
- data/doc/testing.rdoc +13 -11
- data/doc/transactions.rdoc +6 -6
- data/doc/virtual_rows.rdoc +1 -1
- data/lib/sequel/adapters/postgres.rb +4 -0
- data/lib/sequel/adapters/shared/access.rb +9 -1
- data/lib/sequel/adapters/shared/mssql.rb +9 -5
- data/lib/sequel/adapters/shared/mysql.rb +7 -0
- data/lib/sequel/adapters/shared/oracle.rb +7 -0
- data/lib/sequel/adapters/shared/postgres.rb +275 -152
- data/lib/sequel/adapters/shared/sqlanywhere.rb +7 -0
- data/lib/sequel/adapters/shared/sqlite.rb +5 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -1
- 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/database/connecting.rb +24 -0
- data/lib/sequel/database/misc.rb +8 -2
- data/lib/sequel/database/query.rb +37 -0
- data/lib/sequel/dataset/actions.rb +56 -11
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/misc.rb +1 -1
- data/lib/sequel/dataset/query.rb +9 -9
- data/lib/sequel/dataset/sql.rb +5 -1
- data/lib/sequel/extensions/_model_pg_row.rb +0 -12
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/async_thread_pool.rb +11 -11
- data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
- data/lib/sequel/extensions/constraint_validations.rb +1 -1
- data/lib/sequel/extensions/date_arithmetic.rb +1 -1
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/named_timezones.rb +21 -5
- data/lib/sequel/extensions/pg_array.rb +22 -3
- data/lib/sequel/extensions/pg_auto_parameterize.rb +478 -0
- data/lib/sequel/extensions/pg_extended_date_support.rb +12 -0
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +5 -0
- data/lib/sequel/extensions/pg_inet.rb +9 -10
- data/lib/sequel/extensions/pg_interval.rb +9 -10
- data/lib/sequel/extensions/pg_json.rb +10 -10
- data/lib/sequel/extensions/pg_multirange.rb +5 -10
- data/lib/sequel/extensions/pg_range.rb +5 -10
- data/lib/sequel/extensions/pg_row.rb +18 -13
- data/lib/sequel/model/associations.rb +9 -4
- data/lib/sequel/model/base.rb +6 -5
- data/lib/sequel/plugins/auto_validations.rb +53 -15
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +2 -2
- data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/finder.rb +3 -1
- data/lib/sequel/plugins/nested_attributes.rb +4 -4
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
- data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +8 -0
- data/lib/sequel/plugins/sql_comments.rb +1 -1
- data/lib/sequel/plugins/tactical_eager_loading.rb +14 -14
- data/lib/sequel/plugins/validate_associated.rb +22 -12
- data/lib/sequel/plugins/validation_helpers.rb +20 -0
- data/lib/sequel/version.rb +1 -1
- metadata +14 -6
data/lib/sequel/dataset/query.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Sequel
|
|
|
65
65
|
Sequel.synchronize{EXTENSIONS[ext] = block}
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
# On Ruby 2.4+, use clone(:
|
|
68
|
+
# On Ruby 2.4+, use clone(freeze: false) to create clones, because
|
|
69
69
|
# we use true freezing in that case, and we need to modify the opts
|
|
70
70
|
# in the frozen copy.
|
|
71
71
|
#
|
|
@@ -116,7 +116,7 @@ module Sequel
|
|
|
116
116
|
# DB[:items].order(:id).distinct(:id) # SQL: SELECT DISTINCT ON (id) * FROM items ORDER BY id
|
|
117
117
|
# DB[:items].order(:id).distinct{func(:id)} # SQL: SELECT DISTINCT ON (func(id)) * FROM items ORDER BY id
|
|
118
118
|
#
|
|
119
|
-
# There is support for
|
|
119
|
+
# There is support for emulating the DISTINCT ON support in MySQL, but it
|
|
120
120
|
# does not support the ORDER of the dataset, and also doesn't work in many
|
|
121
121
|
# cases if the ONLY_FULL_GROUP_BY sql_mode is used, which is the default on
|
|
122
122
|
# MySQL 5.7.5+.
|
|
@@ -787,7 +787,7 @@ module Sequel
|
|
|
787
787
|
# DB[:items].order(Sequel.lit('a + b')) # SELECT * FROM items ORDER BY a + b
|
|
788
788
|
# DB[:items].order(Sequel[:a] + :b) # SELECT * FROM items ORDER BY (a + b)
|
|
789
789
|
# DB[:items].order(Sequel.desc(:name)) # SELECT * FROM items ORDER BY name DESC
|
|
790
|
-
# DB[:items].order(Sequel.asc(:name, :
|
|
790
|
+
# DB[:items].order(Sequel.asc(:name, nulls: :last)) # SELECT * FROM items ORDER BY name ASC NULLS LAST
|
|
791
791
|
# DB[:items].order{sum(name).desc} # SELECT * FROM items ORDER BY sum(name) DESC
|
|
792
792
|
# DB[:items].order(nil) # SELECT * FROM items
|
|
793
793
|
def order(*columns, &block)
|
|
@@ -857,13 +857,13 @@ module Sequel
|
|
|
857
857
|
# DB[:items].returning(nil) # RETURNING NULL
|
|
858
858
|
# DB[:items].returning(:id, :name) # RETURNING id, name
|
|
859
859
|
#
|
|
860
|
-
# DB[:items].returning.insert(:
|
|
860
|
+
# DB[:items].returning.insert(a: 1) do |hash|
|
|
861
861
|
# # hash for each row inserted, with values for all columns
|
|
862
862
|
# end
|
|
863
|
-
# DB[:items].returning.update(:
|
|
863
|
+
# DB[:items].returning.update(a: 1) do |hash|
|
|
864
864
|
# # hash for each row updated, with values for all columns
|
|
865
865
|
# end
|
|
866
|
-
# DB[:items].returning.delete(:
|
|
866
|
+
# DB[:items].returning.delete(a: 1) do |hash|
|
|
867
867
|
# # hash for each row deleted, with values for all columns
|
|
868
868
|
# end
|
|
869
869
|
def returning(*values)
|
|
@@ -1102,7 +1102,7 @@ module Sequel
|
|
|
1102
1102
|
# referenced in window functions. See Sequel::SQL::Window for a list of
|
|
1103
1103
|
# options that can be passed in. Example:
|
|
1104
1104
|
#
|
|
1105
|
-
# DB[:items].window(:w, :
|
|
1105
|
+
# DB[:items].window(:w, partition: :c1, order: :c2)
|
|
1106
1106
|
# # SELECT * FROM items WINDOW w AS (PARTITION BY c1 ORDER BY c2)
|
|
1107
1107
|
def window(name, opts)
|
|
1108
1108
|
clone(:window=>((@opts[:window]||EMPTY_ARRAY) + [[name, SQL::Window.new(opts)].freeze]).freeze)
|
|
@@ -1163,7 +1163,7 @@ module Sequel
|
|
|
1163
1163
|
# DB[:t].with_recursive(:t,
|
|
1164
1164
|
# DB[:i1].select(:id, :parent_id).where(parent_id: nil),
|
|
1165
1165
|
# DB[:i1].join(:t, id: :parent_id).select(Sequel[:i1][:id], Sequel[:i1][:parent_id]),
|
|
1166
|
-
# :
|
|
1166
|
+
# args: [:id, :parent_id])
|
|
1167
1167
|
#
|
|
1168
1168
|
# # WITH RECURSIVE t(id, parent_id) AS (
|
|
1169
1169
|
# # SELECT id, parent_id FROM i1 WHERE (parent_id IS NULL)
|
|
@@ -1241,7 +1241,7 @@ module Sequel
|
|
|
1241
1241
|
#
|
|
1242
1242
|
# You can also provide a method name and arguments to call to get the SQL:
|
|
1243
1243
|
#
|
|
1244
|
-
# DB[:items].with_sql(:insert_sql, :
|
|
1244
|
+
# DB[:items].with_sql(:insert_sql, b: 1) # INSERT INTO items (b) VALUES (1)
|
|
1245
1245
|
#
|
|
1246
1246
|
# Note that datasets that specify custom SQL using this method will generally
|
|
1247
1247
|
# ignore future dataset methods that modify the SQL used, as specifying custom SQL
|
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -1725,7 +1725,7 @@ module Sequel
|
|
|
1725
1725
|
# Append literalization of the subselect to SQL string.
|
|
1726
1726
|
def subselect_sql_append(sql, ds)
|
|
1727
1727
|
sds = subselect_sql_dataset(sql, ds)
|
|
1728
|
-
sds
|
|
1728
|
+
subselect_sql_append_sql(sql, sds)
|
|
1729
1729
|
unless sds.send(:cache_sql?)
|
|
1730
1730
|
# If subquery dataset does not allow caching SQL,
|
|
1731
1731
|
# then this dataset should not allow caching SQL.
|
|
@@ -1737,6 +1737,10 @@ module Sequel
|
|
|
1737
1737
|
ds.clone(:append_sql=>sql)
|
|
1738
1738
|
end
|
|
1739
1739
|
|
|
1740
|
+
def subselect_sql_append_sql(sql, ds)
|
|
1741
|
+
ds.sql
|
|
1742
|
+
end
|
|
1743
|
+
|
|
1740
1744
|
# The number of decimal digits of precision to use in timestamps.
|
|
1741
1745
|
def timestamp_precision
|
|
1742
1746
|
supports_timestamp_usecs? ? 6 : 0
|
|
@@ -23,18 +23,6 @@ module Sequel
|
|
|
23
23
|
super
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
# Handle Sequel::Model instances in bound variable arrays.
|
|
30
|
-
def bound_variable_array(arg)
|
|
31
|
-
case arg
|
|
32
|
-
when Sequel::Model
|
|
33
|
-
"\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
|
|
34
|
-
else
|
|
35
|
-
super
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
26
|
end
|
|
39
27
|
end
|
|
40
28
|
end
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
# code
|
|
6
6
|
#
|
|
7
7
|
# DB.extension :async_thread_pool
|
|
8
|
-
# foos = DB[:foos].async.where
|
|
8
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
9
9
|
# bar_names = DB[:bar].async.select_order_map(:name)
|
|
10
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
10
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
11
11
|
#
|
|
12
12
|
# All 3 queries will be run in separate threads. +foos+, +bar_names+
|
|
13
13
|
# and +baz_1+ will be proxy objects. Calling a method on the proxy
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
# of calling that method on the result of the query method. For example,
|
|
16
16
|
# if you run:
|
|
17
17
|
#
|
|
18
|
-
# foos = DB[:foos].async.where
|
|
18
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
19
19
|
# bar_names = DB[:bars].async.select_order_map(:name)
|
|
20
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
20
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
21
21
|
# sleep(1)
|
|
22
22
|
# foos.size
|
|
23
23
|
# bar_names.first
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
# These three queries will generally be run concurrently in separate
|
|
27
27
|
# threads. If you instead run:
|
|
28
28
|
#
|
|
29
|
-
# DB[:foos].async.where
|
|
29
|
+
# DB[:foos].async.where(name: 'A'..'M').all.size
|
|
30
30
|
# DB[:bars].async.select_order_map(:name).first
|
|
31
|
-
# DB[:bazes].async.first(:
|
|
31
|
+
# DB[:bazes].async.first(id: 1).name
|
|
32
32
|
#
|
|
33
33
|
# Then will run each query sequentially, since you need the result of
|
|
34
34
|
# one query before running the next query. The queries will still be
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
# What is run in the separate thread is the entire method call that
|
|
38
38
|
# returns results. So with the original example:
|
|
39
39
|
#
|
|
40
|
-
# foos = DB[:foos].async.where
|
|
40
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
41
41
|
# bar_names = DB[:bars].async.select_order_map(:name)
|
|
42
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
42
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
43
43
|
#
|
|
44
|
-
# The +all+, <tt>select_order_map(:name)</tt>, and <tt>first(:
|
|
44
|
+
# The +all+, <tt>select_order_map(:name)</tt>, and <tt>first(id: 1)</tt>
|
|
45
45
|
# calls are run in separate threads. If a block is passed to a method
|
|
46
46
|
# such as +all+ or +each+, the block is also run in that thread. If you
|
|
47
47
|
# have code such as:
|
|
@@ -156,10 +156,10 @@
|
|
|
156
156
|
# so that the query will run in the current thread instead of waiting
|
|
157
157
|
# for an async thread to become available. With the following code:
|
|
158
158
|
#
|
|
159
|
-
# foos = DB[:foos].async.where
|
|
159
|
+
# foos = DB[:foos].async.where(name: 'A'..'M').all
|
|
160
160
|
# bar_names = DB[:bar].async.select_order_map(:name)
|
|
161
161
|
# if foos.length > 4
|
|
162
|
-
# baz_1 = DB[:bazes].async.first(:
|
|
162
|
+
# baz_1 = DB[:bazes].async.first(id: 1)
|
|
163
163
|
# end
|
|
164
164
|
#
|
|
165
165
|
# Whether you need the +baz_1+ variable depends on the value of foos.
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
#
|
|
23
23
|
# Named placeholders can also be used with a hash:
|
|
24
24
|
#
|
|
25
|
-
# ds.where("name > :a", :
|
|
25
|
+
# ds.where("name > :a", a: "A")
|
|
26
26
|
# # SELECT * FROM table WHERE (name > 'A')
|
|
27
27
|
#
|
|
28
28
|
# This extension also allows the use of a plain string passed to Dataset#update:
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
# be emulated by dropping the table and recreating it with the constraints.
|
|
127
127
|
# If you want to use this plugin on SQLite with an alter_table block,
|
|
128
128
|
# you should drop all constraint validation metadata using
|
|
129
|
-
# <tt>drop_constraint_validations_for(:
|
|
129
|
+
# <tt>drop_constraint_validations_for(table: 'table')</tt>, and then
|
|
130
130
|
# readd all constraints you want to use inside the alter table block,
|
|
131
131
|
# making no other changes inside the alter_table block.
|
|
132
132
|
#
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
# By default, values are casted to the generic timestamp type for the
|
|
26
26
|
# database. You can override the cast type using the :cast option:
|
|
27
27
|
#
|
|
28
|
-
# add = Sequel.date_add(:date_column, {years: 1, months: 2, days: 3}, :
|
|
28
|
+
# add = Sequel.date_add(:date_column, {years: 1, months: 2, days: 3}, cast: :timestamptz)
|
|
29
29
|
#
|
|
30
30
|
# These expressions can be used in your datasets, or anywhere else that
|
|
31
31
|
# Sequel expressions are allowed:
|
|
@@ -377,7 +377,7 @@ module Sequel
|
|
|
377
377
|
# Raise a NotCurrentError unless the migrator is current, takes the same
|
|
378
378
|
# arguments as #run.
|
|
379
379
|
def self.check_current(*args)
|
|
380
|
-
raise(NotCurrentError, '
|
|
380
|
+
raise(NotCurrentError, 'current migration version does not match latest available version') unless is_current?(*args)
|
|
381
381
|
end
|
|
382
382
|
|
|
383
383
|
# Return whether the migrator is current (i.e. it does not need to make
|
|
@@ -68,6 +68,10 @@ module Sequel
|
|
|
68
68
|
private
|
|
69
69
|
|
|
70
70
|
if RUBY_VERSION >= '2.6'
|
|
71
|
+
# Whether Time.at with :nsec and :in is broken. True on JRuby < 9.3.9.0.
|
|
72
|
+
BROKEN_TIME_AT_WITH_NSEC = defined?(JRUBY_VERSION) && (JRUBY_VERSION < '9.3' || (JRUBY_VERSION < '9.4' && JRUBY_VERSION.split('.')[2].to_i < 9))
|
|
73
|
+
private_constant :BROKEN_TIME_AT_WITH_NSEC
|
|
74
|
+
|
|
71
75
|
# Convert the given input Time (which must be in UTC) to the given input timezone,
|
|
72
76
|
# which should be a TZInfo::Timezone instance.
|
|
73
77
|
def convert_input_time_other(v, input_timezone)
|
|
@@ -76,33 +80,45 @@ module Sequel
|
|
|
76
80
|
raise unless disamb = tzinfo_disambiguator_for(v)
|
|
77
81
|
period = input_timezone.period_for_local(v, &disamb)
|
|
78
82
|
offset = period.utc_total_offset
|
|
79
|
-
|
|
83
|
+
# :nocov:
|
|
84
|
+
if BROKEN_TIME_AT_WITH_NSEC
|
|
85
|
+
Time.at(v.to_i - offset, :in => input_timezone) + v.nsec/1000000000.0
|
|
86
|
+
# :nocov:
|
|
87
|
+
else
|
|
88
|
+
Time.at(v.to_i - offset, v.nsec, :nsec, :in => input_timezone)
|
|
89
|
+
end
|
|
80
90
|
end
|
|
81
91
|
|
|
82
92
|
# Convert the given input Time to the given output timezone,
|
|
83
93
|
# which should be a TZInfo::Timezone instance.
|
|
84
94
|
def convert_output_time_other(v, output_timezone)
|
|
85
|
-
|
|
95
|
+
# :nocov:
|
|
96
|
+
if BROKEN_TIME_AT_WITH_NSEC
|
|
97
|
+
Time.at(v.to_i, :in => output_timezone) + v.nsec/1000000000.0
|
|
98
|
+
# :nocov:
|
|
99
|
+
else
|
|
100
|
+
Time.at(v.to_i, v.nsec, :nsec, :in => output_timezone)
|
|
101
|
+
end
|
|
86
102
|
end
|
|
87
103
|
# :nodoc:
|
|
88
104
|
# :nocov:
|
|
89
105
|
else
|
|
90
106
|
def convert_input_time_other(v, input_timezone)
|
|
91
107
|
local_offset = input_timezone.period_for_local(v, &tzinfo_disambiguator_for(v)).utc_total_offset
|
|
92
|
-
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i
|
|
108
|
+
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i + v.nsec/1000000000.0
|
|
93
109
|
end
|
|
94
110
|
|
|
95
111
|
if defined?(TZInfo::VERSION) && TZInfo::VERSION > '2'
|
|
96
112
|
def convert_output_time_other(v, output_timezone)
|
|
97
113
|
v = output_timezone.utc_to_local(v.getutc)
|
|
98
114
|
local_offset = output_timezone.period_for_local(v, &tzinfo_disambiguator_for(v)).utc_total_offset
|
|
99
|
-
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i + local_offset
|
|
115
|
+
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i + v.nsec/1000000000.0 + local_offset
|
|
100
116
|
end
|
|
101
117
|
else
|
|
102
118
|
def convert_output_time_other(v, output_timezone)
|
|
103
119
|
v = output_timezone.utc_to_local(v.getutc)
|
|
104
120
|
local_offset = output_timezone.period_for_local(v, &tzinfo_disambiguator_for(v)).utc_total_offset
|
|
105
|
-
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i
|
|
121
|
+
Time.new(1970, 1, 1, 0, 0, 0, local_offset) + v.to_i + v.nsec/1000000000.0
|
|
106
122
|
end
|
|
107
123
|
end
|
|
108
124
|
# :nodoc:
|
|
@@ -228,16 +228,27 @@ module Sequel
|
|
|
228
228
|
when Array
|
|
229
229
|
"{#{a.map{|i| bound_variable_array(i)}.join(',')}}"
|
|
230
230
|
when Sequel::SQL::Blob
|
|
231
|
-
|
|
231
|
+
bound_variable_array_string(literal(a)[BLOB_RANGE].gsub("''", "'"))
|
|
232
232
|
when Sequel::LiteralString
|
|
233
233
|
a
|
|
234
234
|
when String
|
|
235
|
-
|
|
235
|
+
bound_variable_array_string(a)
|
|
236
236
|
else
|
|
237
|
-
|
|
237
|
+
if (s = bound_variable_arg(a, nil)).is_a?(String)
|
|
238
|
+
bound_variable_array_string(s)
|
|
239
|
+
else
|
|
240
|
+
literal(a)
|
|
241
|
+
end
|
|
238
242
|
end
|
|
239
243
|
end
|
|
240
244
|
|
|
245
|
+
# Escape strings used as array members in bound variables. Most complex
|
|
246
|
+
# will create a regular string with bound_variable_arg, and then use this
|
|
247
|
+
# escaping to format it as an array member.
|
|
248
|
+
def bound_variable_array_string(s)
|
|
249
|
+
"\"#{s.gsub(/("|\\)/, '\\\\\1')}\""
|
|
250
|
+
end
|
|
251
|
+
|
|
241
252
|
# Look into both the current database's array schema types and the global
|
|
242
253
|
# array schema types to get the type symbol for the given database type
|
|
243
254
|
# string.
|
|
@@ -457,6 +468,14 @@ module Sequel
|
|
|
457
468
|
end
|
|
458
469
|
end
|
|
459
470
|
|
|
471
|
+
# Allow automatic parameterization of the receiver if all elements can be
|
|
472
|
+
# can be automatically parameterized.
|
|
473
|
+
def sequel_auto_param_type(ds)
|
|
474
|
+
if array_type && all?{|x| nil == x || ds.send(:auto_param_type, x)}
|
|
475
|
+
"::#{array_type}[]"
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
460
479
|
private
|
|
461
480
|
|
|
462
481
|
# Recursive method that handles multi-dimensional
|