sequel 5.93.0 → 5.95.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/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 +191 -22
- 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/sharded_timed_queue.rb +6 -0
- data/lib/sequel/connection_pool/timed_queue.rb +6 -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 +66 -10
- data/lib/sequel/database/schema_methods.rb +79 -28
- data/lib/sequel/dataset/query.rb +10 -2
- data/lib/sequel/dataset/sql.rb +1 -1
- 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_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/class_table_inheritance_constraint_validations.rb +82 -0
- data/lib/sequel/plugins/constraint_validations.rb +15 -10
- 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/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a008ffa4ce90081d7259c785ca68f6f3e3209d789ce6016da8040ea89acca49
|
4
|
+
data.tar.gz: a9f7af4d4214ca4dd82d4909e8aa2c79c96821245f39cc34278df788ae319cb6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9aa9d1fb1cb8a0a323331b2cdccc48b51b5b9f38289be280f693e0b998747d6c7a5e204c29c13cb89bd50caeb5bde604527eb8966249edfe3ab0866bb039bdf2
|
7
|
+
data.tar.gz: 894997717d624f602d9dbfaa554ac03270a50a69f5da6982fd687101af95e94c02a3c82b0fbe9e5ec8a5c4d39265fb4e18d9b9f706be216fccc7c45cd72a00ce
|
@@ -281,7 +281,7 @@ module Sequel
|
|
281
281
|
fetch_ado_schema(:columns, [nil,nil,table_name.to_s,nil]) do |row|
|
282
282
|
rows << AdoSchema::Column.new(row)
|
283
283
|
end
|
284
|
-
rows.
|
284
|
+
rows.sort_by! { |a| a["ORDINAL_POSITION"] }
|
285
285
|
end
|
286
286
|
|
287
287
|
def ado_schema_foreign_keys(table_name)
|
@@ -289,7 +289,7 @@ module Sequel
|
|
289
289
|
fetch_ado_schema(:foreign_keys, [nil,nil,nil,nil,nil,table_name.to_s]) do |row|
|
290
290
|
rows << row
|
291
291
|
end
|
292
|
-
rows.
|
292
|
+
rows.sort_by! { |a| a["ORDINAL"] }
|
293
293
|
end
|
294
294
|
|
295
295
|
def fetch_ado_schema(type, criteria=[])
|
data/lib/sequel/adapters/ado.rb
CHANGED
@@ -234,7 +234,7 @@ module Sequel
|
|
234
234
|
end
|
235
235
|
|
236
236
|
def disconnect_error?(e, opts)
|
237
|
-
super || (e.is_a?(::WIN32OLERuntimeError) && e.message
|
237
|
+
super || (e.is_a?(::WIN32OLERuntimeError) && e.message.include?('Communication link failure'))
|
238
238
|
end
|
239
239
|
|
240
240
|
def rollback_transaction(conn, opts=OPTS)
|
@@ -26,7 +26,7 @@ module Sequel
|
|
26
26
|
|
27
27
|
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
28
28
|
def disconnect_error?(exception, opts)
|
29
|
-
exception.message
|
29
|
+
exception.message.start_with?("Communications link failure") || super
|
30
30
|
end
|
31
31
|
|
32
32
|
# Get the last inserted id using LAST_INSERT_ID().
|
@@ -64,7 +64,7 @@ module Sequel
|
|
64
64
|
|
65
65
|
# Convert tinyint(1) type to boolean
|
66
66
|
def schema_column_type(db_type)
|
67
|
-
db_type
|
67
|
+
db_type.start_with?("tinyint(1)") ? :boolean : super
|
68
68
|
end
|
69
69
|
|
70
70
|
# Run the default connection setting SQL statements.
|
@@ -55,7 +55,7 @@ module Sequel
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def disconnect_error?(exception, opts)
|
58
|
-
super || exception.message
|
58
|
+
super || exception.message.start_with?("Closed Connection")
|
59
59
|
end
|
60
60
|
|
61
61
|
# Default the fetch size for statements to 100, similar to the oci8-based oracle adapter.
|
@@ -98,7 +98,7 @@ module Sequel
|
|
98
98
|
|
99
99
|
# Whether the given exception is due to a foreign key error.
|
100
100
|
def foreign_key_error?(exception)
|
101
|
-
exception.message
|
101
|
+
exception.message.include?('query does not return ResultSet')
|
102
102
|
end
|
103
103
|
|
104
104
|
# Use getLong instead of getInt for converting integers on SQLite, since SQLite does not enforce a limit of 2**32.
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
@@ -305,17 +305,31 @@ module Sequel
|
|
305
305
|
m = output_identifier_meth
|
306
306
|
schema, table = metadata_schema_and_table(table, opts)
|
307
307
|
foreign_keys = {}
|
308
|
+
|
308
309
|
metadata(:getImportedKeys, nil, schema, table) do |r|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
310
|
+
next unless fk_name = r[:fk_name]
|
311
|
+
|
312
|
+
key_seq = r[:key_seq]
|
313
|
+
columns = [key_seq, m.call(r[:fkcolumn_name])]
|
314
|
+
key = [key_seq, m.call(r[:pkcolumn_name])]
|
315
|
+
|
316
|
+
if fk = foreign_keys[fk_name]
|
317
|
+
fk[:columns] << columns
|
318
|
+
fk[:key] << key
|
319
|
+
else
|
320
|
+
foreign_keys[fk_name] = {
|
321
|
+
:name=>m.call(fk_name),
|
322
|
+
:columns=>[columns],
|
323
|
+
:table=>m.call(r[:pktable_name]),
|
324
|
+
:key=>[key]
|
325
|
+
}
|
314
326
|
end
|
315
327
|
end
|
328
|
+
|
329
|
+
fk_keys = [:columns, :key]
|
316
330
|
foreign_keys.values.each do |fk|
|
317
|
-
|
318
|
-
fk[k]
|
331
|
+
fk_keys.each do |k|
|
332
|
+
fk[k].sort!.map!{|_, v| v}
|
319
333
|
end
|
320
334
|
end
|
321
335
|
end
|
@@ -290,7 +290,7 @@ module Sequel
|
|
290
290
|
|
291
291
|
# Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
|
292
292
|
def schema_column_type(db_type)
|
293
|
-
convert_tinyint_to_bool && db_type
|
293
|
+
convert_tinyint_to_bool && db_type.start_with?("tinyint(1)") ? :boolean : super
|
294
294
|
end
|
295
295
|
end
|
296
296
|
|
@@ -221,13 +221,13 @@ module Sequel
|
|
221
221
|
super ||
|
222
222
|
((conn = opts[:conn]) && !conn.ping) ||
|
223
223
|
(e.is_a?(::Mysql2::Error) &&
|
224
|
-
(e.sql_state
|
224
|
+
((e.sql_state && e.sql_state.start_with?("08")) ||
|
225
225
|
MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message)))
|
226
226
|
end
|
227
227
|
|
228
228
|
# Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
|
229
229
|
def schema_column_type(db_type)
|
230
|
-
convert_tinyint_to_bool && db_type
|
230
|
+
convert_tinyint_to_bool && db_type.start_with?("tinyint(1)") ? :boolean : super
|
231
231
|
end
|
232
232
|
end
|
233
233
|
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -108,7 +108,7 @@ module Sequel
|
|
108
108
|
from(name).first
|
109
109
|
true
|
110
110
|
rescue DatabaseError => e
|
111
|
-
if e.to_s
|
111
|
+
if e.to_s.include?('Operation not allowed for reason code "7" on table') && v == false
|
112
112
|
# table probably needs reorg
|
113
113
|
reorg(name)
|
114
114
|
v = true
|
@@ -175,8 +175,13 @@ module Sequel
|
|
175
175
|
# Supply columns with NOT NULL if they are part of a composite
|
176
176
|
# primary key or unique constraint
|
177
177
|
def column_list_sql(g)
|
178
|
-
ks =
|
179
|
-
g.constraints.each
|
178
|
+
ks = {}
|
179
|
+
g.constraints.each do |c|
|
180
|
+
case c[:type]
|
181
|
+
when :primary_key, :unique
|
182
|
+
c[:columns].each{|c| ks[c] = true}
|
183
|
+
end
|
184
|
+
end
|
180
185
|
g.columns.each{|c| c[:null] = false if ks.include?(c[:name]) }
|
181
186
|
super
|
182
187
|
end
|
@@ -705,7 +705,7 @@ module Sequel
|
|
705
705
|
|
706
706
|
# Allows you to do a dirty read of uncommitted data using WITH (NOLOCK).
|
707
707
|
def nolock
|
708
|
-
|
708
|
+
cached_lock_style_dataset(:_nolock_ds, :dirty)
|
709
709
|
end
|
710
710
|
|
711
711
|
# Uses OUTER APPLY to join the given table into the current dataset.
|
@@ -456,7 +456,7 @@ module Sequel
|
|
456
456
|
[pk]
|
457
457
|
elsif !(pkc = generator.constraints.select{|con| con[:type] == :primary_key}).empty?
|
458
458
|
pkc.first[:columns]
|
459
|
-
elsif !(pkc = generator.columns.select{|con| con[:primary_key]
|
459
|
+
elsif !(pkc = generator.columns.select{|con| con[:primary_key]}).empty?
|
460
460
|
pkc.map{|c| c[:name]}
|
461
461
|
end
|
462
462
|
else
|
@@ -787,7 +787,7 @@ module Sequel
|
|
787
787
|
|
788
788
|
# Return a cloned dataset which will use LOCK IN SHARE MODE to lock returned rows.
|
789
789
|
def for_share
|
790
|
-
|
790
|
+
cached_lock_style_dataset(:_for_share_ds, :share)
|
791
791
|
end
|
792
792
|
|
793
793
|
# Adds full text filter
|
@@ -48,7 +48,7 @@ module Sequel
|
|
48
48
|
TYPE_TRANSLATOR_DATE = date.freeze
|
49
49
|
bytea = Object.new
|
50
50
|
def bytea.call(str)
|
51
|
-
str = if str
|
51
|
+
str = if str.start_with?('\\x')
|
52
52
|
# PostgreSQL 9.0+ bytea hex format
|
53
53
|
str[2..-1].gsub(/(..)/){|s| s.to_i(16).chr}
|
54
54
|
else
|
@@ -124,6 +124,8 @@ module Sequel
|
|
124
124
|
#
|
125
125
|
# Options supported:
|
126
126
|
#
|
127
|
+
# :include :: Include additional columns in the underlying index, to
|
128
|
+
# allow for index-only scans in more cases (PostgreSQL 11+).
|
127
129
|
# :name :: Name the constraint with the given name (useful if you may
|
128
130
|
# need to drop the constraint later)
|
129
131
|
# :using :: Override the index_method for the exclusion constraint (defaults to gist).
|
@@ -141,6 +143,17 @@ module Sequel
|
|
141
143
|
@operations << {:op => :add_constraint, :type => :exclude, :elements => elements}.merge!(opts)
|
142
144
|
end
|
143
145
|
|
146
|
+
# Alter an existing constraint. Options:
|
147
|
+
# :deferrable :: Modify deferrable setting for constraint (PostgreSQL 9.4+):
|
148
|
+
# true :: DEFERRABLE INITIALLY DEFERRED
|
149
|
+
# false :: NOT DEFERRABLE
|
150
|
+
# :immediate :: DEFERRABLE INITIALLY IMMEDIATE
|
151
|
+
# :enforced :: Set true to use ENFORCED, or false to use NOT ENFORCED (PostgreSQL 18+)
|
152
|
+
# :inherit :: Set true to use INHERIT, or false to use NO INHERIT (PostgreSQL 18+)
|
153
|
+
def alter_constraint(name, opts=OPTS)
|
154
|
+
@operations << {:op => :alter_constraint, :name => name}.merge!(opts)
|
155
|
+
end
|
156
|
+
|
144
157
|
# Validate the constraint with the given name, which should have
|
145
158
|
# been added previously with NOT VALID.
|
146
159
|
def validate_constraint(name)
|
@@ -335,7 +348,7 @@ module Sequel
|
|
335
348
|
hash = {}
|
336
349
|
_check_constraints_ds.where_each(:conrelid=>regclass_oid(table)) do |row|
|
337
350
|
constraint = m.call(row[:constraint])
|
338
|
-
entry = hash[constraint] ||= {:definition=>row[:definition], :columns=>[]}
|
351
|
+
entry = hash[constraint] ||= {:definition=>row[:definition], :columns=>[], :validated=>row[:validated], :enforced=>row[:enforced]}
|
339
352
|
entry[:columns] << m.call(row[:column]) if row[:column]
|
340
353
|
end
|
341
354
|
|
@@ -601,6 +614,8 @@ module Sequel
|
|
601
614
|
:on_update=>fklod_map[row[:on_update]],
|
602
615
|
:on_delete=>fklod_map[row[:on_delete]],
|
603
616
|
:deferrable=>row[:deferrable],
|
617
|
+
:validated=>row[:validated],
|
618
|
+
:enforced=>row[:enforced],
|
604
619
|
:table=>schema ? SQL::QualifiedIdentifier.new(m.call(row[:schema]), m.call(row[:table])) : m.call(row[:table]),
|
605
620
|
}
|
606
621
|
|
@@ -898,11 +913,15 @@ module Sequel
|
|
898
913
|
|
899
914
|
# Dataset used to retrieve CHECK constraint information
|
900
915
|
def _check_constraints_ds
|
901
|
-
@_check_constraints_ds ||=
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
916
|
+
@_check_constraints_ds ||= begin
|
917
|
+
ds = metadata_dataset.
|
918
|
+
from{pg_constraint.as(:co)}.
|
919
|
+
left_join(Sequel[:pg_attribute].as(:att), :attrelid=>:conrelid, :attnum=>SQL::Function.new(:ANY, Sequel[:co][:conkey])).
|
920
|
+
where(:contype=>'c').
|
921
|
+
select{[co[:conname].as(:constraint), att[:attname].as(:column), pg_get_constraintdef(co[:oid]).as(:definition)]}
|
922
|
+
|
923
|
+
_add_validated_enforced_constraint_columns(ds)
|
924
|
+
end
|
906
925
|
end
|
907
926
|
|
908
927
|
# Dataset used to retrieve foreign keys referenced by a table
|
@@ -968,6 +987,28 @@ module Sequel
|
|
968
987
|
ds = ds.order_append(Sequel[:nsp][:nspname], Sequel[:cl2][:relname])
|
969
988
|
end
|
970
989
|
|
990
|
+
_add_validated_enforced_constraint_columns(ds)
|
991
|
+
end
|
992
|
+
|
993
|
+
def _add_validated_enforced_constraint_columns(ds)
|
994
|
+
validated_cond = if server_version >= 90100
|
995
|
+
Sequel[:convalidated]
|
996
|
+
# :nocov:
|
997
|
+
else
|
998
|
+
Sequel.cast(true, TrueClass)
|
999
|
+
# :nocov:
|
1000
|
+
end
|
1001
|
+
ds = ds.select_append(validated_cond.as(:validated))
|
1002
|
+
|
1003
|
+
enforced_cond = if server_version >= 180000
|
1004
|
+
Sequel[:conenforced]
|
1005
|
+
# :nocov:
|
1006
|
+
else
|
1007
|
+
Sequel.cast(true, TrueClass)
|
1008
|
+
# :nocov:
|
1009
|
+
end
|
1010
|
+
ds = ds.select_append(enforced_cond.as(:enforced))
|
1011
|
+
|
971
1012
|
ds
|
972
1013
|
end
|
973
1014
|
|
@@ -1140,6 +1181,31 @@ module Sequel
|
|
1140
1181
|
"ADD COLUMN#{' IF NOT EXISTS' if op[:if_not_exists]} #{column_definition_sql(op)}"
|
1141
1182
|
end
|
1142
1183
|
|
1184
|
+
def alter_table_alter_constraint_sql(table, op)
|
1185
|
+
sql = String.new
|
1186
|
+
sql << "ALTER CONSTRAINT #{quote_identifier(op[:name])}"
|
1187
|
+
|
1188
|
+
constraint_deferrable_sql_append(sql, op[:deferrable])
|
1189
|
+
|
1190
|
+
case op[:enforced]
|
1191
|
+
when nil
|
1192
|
+
when false
|
1193
|
+
sql << " NOT ENFORCED"
|
1194
|
+
else
|
1195
|
+
sql << " ENFORCED"
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
case op[:inherit]
|
1199
|
+
when nil
|
1200
|
+
when false
|
1201
|
+
sql << " NO INHERIT"
|
1202
|
+
else
|
1203
|
+
sql << " INHERIT"
|
1204
|
+
end
|
1205
|
+
|
1206
|
+
sql
|
1207
|
+
end
|
1208
|
+
|
1143
1209
|
def alter_table_generator_class
|
1144
1210
|
Postgres::AlterTableGenerator
|
1145
1211
|
end
|
@@ -1190,6 +1256,22 @@ module Sequel
|
|
1190
1256
|
end
|
1191
1257
|
end
|
1192
1258
|
|
1259
|
+
def column_definition_append_include_sql(sql, constraint)
|
1260
|
+
if include_cols = constraint[:include]
|
1261
|
+
sql << " INCLUDE " << literal(Array(include_cols))
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
def column_definition_append_primary_key_sql(sql, constraint)
|
1266
|
+
super
|
1267
|
+
column_definition_append_include_sql(sql, constraint)
|
1268
|
+
end
|
1269
|
+
|
1270
|
+
def column_definition_append_unique_sql(sql, constraint)
|
1271
|
+
super
|
1272
|
+
column_definition_append_include_sql(sql, constraint)
|
1273
|
+
end
|
1274
|
+
|
1193
1275
|
# Literalize non-String collate options. This is because unquoted collatations
|
1194
1276
|
# are folded to lowercase, and PostgreSQL used mixed case or capitalized collations.
|
1195
1277
|
def column_definition_collate_sql(sql, column)
|
@@ -1233,9 +1315,9 @@ module Sequel
|
|
1233
1315
|
end
|
1234
1316
|
|
1235
1317
|
# PostgreSQL can't combine rename_column operations, and it can combine
|
1236
|
-
#
|
1318
|
+
# validate_constraint and alter_constraint operations.
|
1237
1319
|
def combinable_alter_table_op?(op)
|
1238
|
-
(super || op[:op] == :validate_constraint) && op[:op] != :rename_column
|
1320
|
+
(super || op[:op] == :validate_constraint || op[:op] == :alter_constraint) && op[:op] != :rename_column
|
1239
1321
|
end
|
1240
1322
|
|
1241
1323
|
VALID_CLIENT_MIN_MESSAGES = %w'DEBUG5 DEBUG4 DEBUG3 DEBUG2 DEBUG1 LOG NOTICE WARNING ERROR FATAL PANIC'.freeze.each(&:freeze)
|
@@ -1269,30 +1351,49 @@ module Sequel
|
|
1269
1351
|
sqls
|
1270
1352
|
end
|
1271
1353
|
|
1272
|
-
# Handle
|
1354
|
+
# Handle PostgreSQL-specific constraint features.
|
1273
1355
|
def constraint_definition_sql(constraint)
|
1274
1356
|
case type = constraint[:type]
|
1275
1357
|
when :exclude
|
1276
1358
|
elements = constraint[:elements].map{|c, op| "#{literal(c)} WITH #{op}"}.join(', ')
|
1277
1359
|
sql = String.new
|
1278
|
-
sql << "
|
1360
|
+
sql << "CONSTRAINT #{quote_identifier(constraint[:name])} " if constraint[:name]
|
1361
|
+
sql << "EXCLUDE USING #{constraint[:using]||'gist'} (#{elements})"
|
1362
|
+
column_definition_append_include_sql(sql, constraint)
|
1363
|
+
sql << " WHERE #{filter_expr(constraint[:where])}" if constraint[:where]
|
1279
1364
|
constraint_deferrable_sql_append(sql, constraint[:deferrable])
|
1280
1365
|
sql
|
1281
1366
|
when :primary_key, :unique
|
1367
|
+
sql = String.new
|
1368
|
+
sql << "CONSTRAINT #{quote_identifier(constraint[:name])} " if constraint[:name]
|
1369
|
+
|
1370
|
+
if type == :primary_key
|
1371
|
+
sql << primary_key_constraint_sql_fragment(constraint)
|
1372
|
+
else
|
1373
|
+
sql << unique_constraint_sql_fragment(constraint)
|
1374
|
+
end
|
1375
|
+
|
1282
1376
|
if using_index = constraint[:using_index]
|
1283
|
-
sql = String.new
|
1284
|
-
sql << "CONSTRAINT #{quote_identifier(constraint[:name])} " if constraint[:name]
|
1285
|
-
if type == :primary_key
|
1286
|
-
sql << primary_key_constraint_sql_fragment(constraint)
|
1287
|
-
else
|
1288
|
-
sql << unique_constraint_sql_fragment(constraint)
|
1289
|
-
end
|
1290
1377
|
sql << " USING INDEX " << quote_identifier(using_index)
|
1291
1378
|
else
|
1292
|
-
|
1379
|
+
cols = literal(constraint[:columns])
|
1380
|
+
cols.insert(-2, " WITHOUT OVERLAPS") if constraint[:without_overlaps]
|
1381
|
+
sql << " " << cols
|
1382
|
+
|
1383
|
+
if include_cols = constraint[:include]
|
1384
|
+
sql << " INCLUDE " << literal(Array(include_cols))
|
1385
|
+
end
|
1293
1386
|
end
|
1387
|
+
|
1388
|
+
sql
|
1294
1389
|
else # when :foreign_key, :check
|
1295
1390
|
sql = super
|
1391
|
+
if constraint[:no_inherit]
|
1392
|
+
sql << " NO INHERIT"
|
1393
|
+
end
|
1394
|
+
if constraint[:not_enforced]
|
1395
|
+
sql << " NOT ENFORCED"
|
1396
|
+
end
|
1296
1397
|
if constraint[:not_valid]
|
1297
1398
|
sql << " NOT VALID"
|
1298
1399
|
end
|
@@ -1300,6 +1401,46 @@ module Sequel
|
|
1300
1401
|
end
|
1301
1402
|
end
|
1302
1403
|
|
1404
|
+
def column_definition_add_references_sql(sql, column)
|
1405
|
+
super
|
1406
|
+
if column[:not_enforced]
|
1407
|
+
sql << " NOT ENFORCED"
|
1408
|
+
end
|
1409
|
+
end
|
1410
|
+
|
1411
|
+
def column_definition_null_sql(sql, column)
|
1412
|
+
constraint = column[:not_null]
|
1413
|
+
constraint = nil unless constraint.is_a?(Hash)
|
1414
|
+
if constraint && (name = constraint[:name])
|
1415
|
+
sql << " CONSTRAINT #{quote_identifier(name)}"
|
1416
|
+
end
|
1417
|
+
super
|
1418
|
+
if constraint && constraint[:no_inherit]
|
1419
|
+
sql << " NO INHERIT"
|
1420
|
+
end
|
1421
|
+
end
|
1422
|
+
|
1423
|
+
# Handle :period option
|
1424
|
+
def column_references_table_constraint_sql(constraint)
|
1425
|
+
sql = String.new
|
1426
|
+
sql << "FOREIGN KEY "
|
1427
|
+
cols = constraint[:columns]
|
1428
|
+
cols = column_references_add_period(cols) if constraint[:period]
|
1429
|
+
sql << literal(cols) << column_references_sql(constraint)
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
def column_references_append_key_sql(sql, column)
|
1433
|
+
cols = Array(column[:key])
|
1434
|
+
cols = column_references_add_period(cols) if column[:period]
|
1435
|
+
sql << "(#{cols.map{|x| quote_identifier(x)}.join(', ')})"
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
def column_references_add_period(cols)
|
1439
|
+
cols= cols.dup
|
1440
|
+
cols[-1] = Sequel.lit("PERIOD #{quote_identifier(cols[-1])}")
|
1441
|
+
cols
|
1442
|
+
end
|
1443
|
+
|
1303
1444
|
def database_specific_error_class_from_sqlstate(sqlstate)
|
1304
1445
|
if sqlstate == '23P01'
|
1305
1446
|
ExclusionConstraintViolation
|
@@ -1369,7 +1510,8 @@ module Sequel
|
|
1369
1510
|
# SQL statement to create database function.
|
1370
1511
|
def create_function_sql(name, definition, opts=OPTS)
|
1371
1512
|
args = opts[:args]
|
1372
|
-
|
1513
|
+
in_out = %w'OUT INOUT'
|
1514
|
+
if (!opts[:args].is_a?(Array) || !opts[:args].any?{|a| Array(a).length == 3 && in_out.include?(a[2].to_s)})
|
1373
1515
|
returns = opts[:returns] || 'void'
|
1374
1516
|
end
|
1375
1517
|
language = opts[:language] || 'SQL'
|
@@ -1816,6 +1958,15 @@ module Sequel
|
|
1816
1958
|
end
|
1817
1959
|
end
|
1818
1960
|
|
1961
|
+
# Support :nulls_not_distinct option.
|
1962
|
+
def unique_constraint_sql_fragment(constraint)
|
1963
|
+
if constraint[:nulls_not_distinct]
|
1964
|
+
'UNIQUE NULLS NOT DISTINCT'
|
1965
|
+
else
|
1966
|
+
'UNIQUE'
|
1967
|
+
end
|
1968
|
+
end
|
1969
|
+
|
1819
1970
|
# PostgreSQL 9.4+ supports views with check option.
|
1820
1971
|
def view_with_check_option_support
|
1821
1972
|
# :nocov:
|
@@ -1932,9 +2083,22 @@ module Sequel
|
|
1932
2083
|
end
|
1933
2084
|
end
|
1934
2085
|
|
2086
|
+
# Return a cloned dataset which will use FOR KEY SHARE to lock returned rows.
|
2087
|
+
# Supported on PostgreSQL 9.3+.
|
2088
|
+
def for_key_share
|
2089
|
+
cached_lock_style_dataset(:_for_key_share_ds, :key_share)
|
2090
|
+
end
|
2091
|
+
|
2092
|
+
# Return a cloned dataset which will use FOR NO KEY UPDATE to lock returned rows.
|
2093
|
+
# This is generally a better choice than using for_update on PostgreSQL, unless
|
2094
|
+
# you will be deleting the row or modifying a key column. Supported on PostgreSQL 9.3+.
|
2095
|
+
def for_no_key_update
|
2096
|
+
cached_lock_style_dataset(:_for_no_key_update_ds, :no_key_update)
|
2097
|
+
end
|
2098
|
+
|
1935
2099
|
# Return a cloned dataset which will use FOR SHARE to lock returned rows.
|
1936
2100
|
def for_share
|
1937
|
-
|
2101
|
+
cached_lock_style_dataset(:_for_share_ds, :share)
|
1938
2102
|
end
|
1939
2103
|
|
1940
2104
|
# Run a full text search on PostgreSQL. By default, searching for the inclusion
|
@@ -2710,8 +2874,13 @@ module Sequel
|
|
2710
2874
|
# Use SKIP LOCKED if skipping locked rows.
|
2711
2875
|
def select_lock_sql(sql)
|
2712
2876
|
lock = @opts[:lock]
|
2713
|
-
|
2877
|
+
case lock
|
2878
|
+
when :share
|
2714
2879
|
sql << ' FOR SHARE'
|
2880
|
+
when :no_key_update
|
2881
|
+
sql << ' FOR NO KEY UPDATE'
|
2882
|
+
when :key_share
|
2883
|
+
sql << ' FOR KEY SHARE'
|
2715
2884
|
else
|
2716
2885
|
super
|
2717
2886
|
end
|
@@ -95,14 +95,14 @@ module Sequel
|
|
95
95
|
metadata_dataset.with_sql("PRAGMA index_list(?)", im.call(table)).each do |r|
|
96
96
|
if opts[:only_autocreated]
|
97
97
|
# If specifically asked for only autocreated indexes, then return those an only those
|
98
|
-
next unless r[:name]
|
98
|
+
next unless r[:name].start_with?('sqlite_autoindex_')
|
99
99
|
elsif r.has_key?(:origin)
|
100
100
|
# If origin is set, then only exclude primary key indexes and partial indexes
|
101
101
|
next if r[:origin] == 'pk'
|
102
102
|
next if r[:partial].to_i == 1
|
103
103
|
else
|
104
104
|
# When :origin key not present, assume any autoindex could be a primary key one and exclude it
|
105
|
-
next if r[:name]
|
105
|
+
next if r[:name].start_with?('sqlite_autoindex_')
|
106
106
|
end
|
107
107
|
|
108
108
|
indexes[m.call(r[:name])] = {:unique=>r[:unique].to_i==1}
|
@@ -302,7 +302,7 @@ module Sequel
|
|
302
302
|
|
303
303
|
# A name to use for the backup table
|
304
304
|
def backup_table_name(table, opts=OPTS)
|
305
|
-
table = table.
|
305
|
+
table = table.delete('`')
|
306
306
|
(opts[:times]||1000).times do |i|
|
307
307
|
table_name = "#{table}_backup#{i}"
|
308
308
|
return table_name unless table_exists?(table_name)
|
@@ -140,6 +140,12 @@ class Sequel::ShardedTimedQueueConnectionPool < Sequel::ConnectionPool
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
+
# The number of threads waiting to check out a connection for the given
|
144
|
+
# server.
|
145
|
+
def num_waiting(server=:default)
|
146
|
+
@queues[pick_server(server)].num_waiting
|
147
|
+
end
|
148
|
+
|
143
149
|
# The total number of connections in the pool. Using a non-existant server will return nil.
|
144
150
|
def size(server=:default)
|
145
151
|
sync{@sizes[server]}
|
@@ -102,6 +102,11 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
+
# The number of threads waiting to check out a connection.
|
106
|
+
def num_waiting(_server=:default)
|
107
|
+
@queue.num_waiting
|
108
|
+
end
|
109
|
+
|
105
110
|
def pool_type
|
106
111
|
:timed_queue
|
107
112
|
end
|
@@ -236,7 +241,7 @@ class Sequel::TimedQueueConnectionPool < Sequel::ConnectionPool
|
|
236
241
|
def preconnect(concurrent = false)
|
237
242
|
if concurrent
|
238
243
|
if times = sync{@max_size > (size = @size[0]) ? @max_size - size : false}
|
239
|
-
|
244
|
+
Array.new(times){Thread.new{if conn = try_make_new; @queue.push(conn) end}}.map(&:value)
|
240
245
|
end
|
241
246
|
else
|
242
247
|
while conn = try_make_new
|