sequel 5.59.0 → 5.60.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 +10 -0
- data/README.rdoc +1 -1
- data/bin/sequel +11 -3
- data/doc/release_notes/5.60.0.txt +22 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
- data/lib/sequel/adapters/jdbc.rb +5 -5
- data/lib/sequel/adapters/mock.rb +1 -1
- data/lib/sequel/adapters/mysql.rb +3 -3
- data/lib/sequel/adapters/oracle.rb +1 -1
- data/lib/sequel/adapters/postgres.rb +46 -11
- data/lib/sequel/adapters/shared/mssql.rb +1 -1
- data/lib/sequel/adapters/shared/oracle.rb +1 -1
- data/lib/sequel/adapters/shared/postgres.rb +26 -14
- data/lib/sequel/adapters/shared/sqlite.rb +1 -1
- data/lib/sequel/adapters/sqlite.rb +1 -1
- data/lib/sequel/ast_transformer.rb +1 -1
- data/lib/sequel/database/misc.rb +2 -2
- data/lib/sequel/dataset/sql.rb +2 -2
- data/lib/sequel/extensions/date_arithmetic.rb +35 -7
- data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
- data/lib/sequel/extensions/is_distinct_from.rb +3 -1
- data/lib/sequel/extensions/pg_array.rb +2 -2
- data/lib/sequel/extensions/pg_array_ops.rb +1 -1
- data/lib/sequel/extensions/pg_enum.rb +1 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +3 -3
- data/lib/sequel/extensions/pg_inet.rb +2 -2
- data/lib/sequel/extensions/pg_interval.rb +1 -1
- data/lib/sequel/extensions/pg_json.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +3 -3
- data/lib/sequel/extensions/pg_multirange.rb +2 -2
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
- data/lib/sequel/extensions/symbol_aref.rb +2 -0
- data/lib/sequel/model/associations.rb +6 -6
- data/lib/sequel/model/base.rb +3 -3
- data/lib/sequel/model/exceptions.rb +1 -1
- data/lib/sequel/model/inflections.rb +6 -6
- data/lib/sequel/plugins/auto_validations.rb +1 -1
- data/lib/sequel/plugins/defaults_setter.rb +1 -1
- data/lib/sequel/plugins/dirty.rb +1 -1
- data/lib/sequel/plugins/insert_conflict.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +1 -1
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +1 -1
- data/lib/sequel/plugins/sql_comments.rb +4 -4
- data/lib/sequel/plugins/subclasses.rb +1 -1
- data/lib/sequel/plugins/validation_class_methods.rb +3 -3
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/sql.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1bd9076a491b881827f095bbb1177974861448054cd73376ee76a42ed0f72ee5
|
|
4
|
+
data.tar.gz: e2e23f283d2d9f5b29df1510f5f39c8335cc47c37d0f92c848763cd437d4e668
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 309b37a25a51bc38c30c20276b7df1df4d21b6b14502b129fc363a0ac9bfc4897be03c21ec1d5b4b333eb6c1944491e4383406bb3f2cb96ba8dd1e98b513de42
|
|
7
|
+
data.tar.gz: 58adf4e309a3bd1d921f95d168a79830cce4526767b8ee9379ce69463327b10f0db4ded44a4a8e474cd0dd31036546b120f3e38a07c3057a5290933cffd3b77a
|
data/CHANGELOG
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
=== 5.60.0 (2022-09-01)
|
|
2
|
+
|
|
3
|
+
* Support arbitrary expressions for date_arithmetic interval values on PostgreSQL 9.4+ (jeremyevans)
|
|
4
|
+
|
|
5
|
+
* Support native IS DISTINCT FROM on SQLite 3.39+ instead of emulating support in the is_distinct_from extension (jeremyevans)
|
|
6
|
+
|
|
7
|
+
* Support HAVING without GROUP BY on SQLite 3.39+ (jeremyevans)
|
|
8
|
+
|
|
9
|
+
* Convert most respond_to? calls to equivalent defined? for better performance (jeremyevans)
|
|
10
|
+
|
|
1
11
|
=== 5.59.0 (2022-08-01)
|
|
2
12
|
|
|
3
13
|
* Set :allow_eager association option to false for instance specific associations without eager loaders (jeremyevans)
|
data/README.rdoc
CHANGED
|
@@ -416,7 +416,7 @@ As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
|
|
|
416
416
|
|
|
417
417
|
=== Merging records
|
|
418
418
|
|
|
419
|
-
Merging records using the SQL MERGE
|
|
419
|
+
Merging records using the SQL MERGE statement is done using <tt>merge*</tt> methods.
|
|
420
420
|
You use +merge_using+ to specify the merge source and join conditions.
|
|
421
421
|
You can use +merge_insert+, +merge_delete+, and/or +merge_update+ to set the
|
|
422
422
|
INSERT, DELETE, and UPDATE clauses for the merge. +merge_insert+ takes the same
|
data/bin/sequel
CHANGED
|
@@ -194,7 +194,11 @@ begin
|
|
|
194
194
|
TO_DB = connect_proc[db2]
|
|
195
195
|
same_db = DB.database_type==TO_DB.database_type
|
|
196
196
|
index_opts = {:same_db=>same_db}
|
|
197
|
+
|
|
198
|
+
# :nocov:
|
|
197
199
|
index_opts[:index_names] = :namespace if !DB.global_index_namespace? && TO_DB.global_index_namespace?
|
|
200
|
+
# :nocov:
|
|
201
|
+
|
|
198
202
|
if DB.database_type == :sqlite && !same_db
|
|
199
203
|
# SQLite integer types allows 64-bit integers
|
|
200
204
|
TO_DB.extension :integer64
|
|
@@ -212,18 +216,20 @@ begin
|
|
|
212
216
|
puts "Begin copying data"
|
|
213
217
|
DB.transaction do
|
|
214
218
|
TO_DB.transaction do
|
|
219
|
+
all_status_lines = ENV['SEQUEL_BIN_STATUS_ALL_LINES']
|
|
220
|
+
|
|
215
221
|
DB.tables.each do |table|
|
|
216
222
|
puts "Begin copying records for table: #{table}"
|
|
217
223
|
time = Time.now
|
|
218
224
|
to_ds = TO_DB.from(table)
|
|
219
225
|
j = 0
|
|
220
226
|
DB.from(table).each do |record|
|
|
221
|
-
|
|
227
|
+
to_ds.insert(record)
|
|
228
|
+
j += 1
|
|
229
|
+
if Time.now - time > 5 || all_status_lines
|
|
222
230
|
puts "Status: #{j} records copied"
|
|
223
231
|
time = Time.now
|
|
224
232
|
end
|
|
225
|
-
to_ds.insert(record)
|
|
226
|
-
j += 1
|
|
227
233
|
end
|
|
228
234
|
puts "Finished copying #{j} records for table: #{table}"
|
|
229
235
|
end
|
|
@@ -260,8 +266,10 @@ if !ARGV.empty?
|
|
|
260
266
|
ARGV.each{|v| load(v)}
|
|
261
267
|
elsif !$stdin.isatty
|
|
262
268
|
eval($stdin.read)
|
|
269
|
+
# :nocov:
|
|
263
270
|
else
|
|
264
271
|
require 'irb'
|
|
265
272
|
puts "Your database is stored in DB..."
|
|
266
273
|
IRB.start
|
|
267
274
|
end
|
|
275
|
+
# :nocov:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
= New Features
|
|
2
|
+
|
|
3
|
+
* The date_arithmetic extension now supports arbitrary expressions
|
|
4
|
+
as interval values on PostgreSQL 9.4+. Previously, only integers
|
|
5
|
+
were supported for the interval values.
|
|
6
|
+
|
|
7
|
+
= Other Improvements
|
|
8
|
+
|
|
9
|
+
* Most Kernel#respond_to? calls have been converted to equivalent
|
|
10
|
+
defined? calls for better performance. defined? is a keyword
|
|
11
|
+
and is about 50% faster for the same behavior.
|
|
12
|
+
|
|
13
|
+
* The is_distinct_from extension now supports the IS DISTINCT FROM
|
|
14
|
+
syntax natively on SQLite 3.39+, instead of emulating it.
|
|
15
|
+
|
|
16
|
+
* HAVING without GROUP BY is now supported on SQLite 3.39+.
|
|
17
|
+
|
|
18
|
+
* Coverage testing has been significantly expanded. Previously,
|
|
19
|
+
the core, model, plugin, and extension code had 100% line/branch
|
|
20
|
+
coverage. 100% line/branch coverage has been added for the
|
|
21
|
+
core extensions, bin/sequel, and the postgres adapter with the
|
|
22
|
+
pg driver.
|
|
@@ -125,7 +125,7 @@ module Sequel
|
|
|
125
125
|
|
|
126
126
|
# The result code for the exception, if the jdbc driver supports result codes for exceptions.
|
|
127
127
|
def sqlite_error_code(exception)
|
|
128
|
-
exception.resultCode.code if exception.
|
|
128
|
+
exception.resultCode.code if defined?(exception.resultCode)
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
end
|
data/lib/sequel/adapters/jdbc.rb
CHANGED
|
@@ -38,7 +38,7 @@ module Sequel
|
|
|
38
38
|
else
|
|
39
39
|
if defined?(::Jdbc) && ( ::Jdbc.const_defined?(name) rescue nil )
|
|
40
40
|
jdbc_module = ::Jdbc.const_get(name) # e.g. Jdbc::SQLite3
|
|
41
|
-
jdbc_module.load_driver if jdbc_module.
|
|
41
|
+
jdbc_module.load_driver if defined?(jdbc_module.load_driver)
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -396,9 +396,9 @@ module Sequel
|
|
|
396
396
|
|
|
397
397
|
def database_exception_sqlstate(exception, opts)
|
|
398
398
|
if database_exception_use_sqlstates?
|
|
399
|
-
while exception.
|
|
399
|
+
while defined?(exception.cause)
|
|
400
400
|
exception = exception.cause
|
|
401
|
-
return exception.getSQLState if exception.
|
|
401
|
+
return exception.getSQLState if defined?(exception.getSQLState)
|
|
402
402
|
end
|
|
403
403
|
end
|
|
404
404
|
nil
|
|
@@ -415,8 +415,8 @@ module Sequel
|
|
|
415
415
|
|
|
416
416
|
# Raise a disconnect error if the SQL state of the cause of the exception indicates so.
|
|
417
417
|
def disconnect_error?(exception, opts)
|
|
418
|
-
cause = exception.
|
|
419
|
-
super || (cause.
|
|
418
|
+
cause = defined?(exception.cause) ? exception.cause : exception
|
|
419
|
+
super || (defined?(cause.getSQLState) && cause.getSQLState =~ /^08/)
|
|
420
420
|
end
|
|
421
421
|
|
|
422
422
|
# Execute the prepared statement. If the provided name is a
|
data/lib/sequel/adapters/mock.rb
CHANGED
|
@@ -72,7 +72,7 @@ module Sequel
|
|
|
72
72
|
def connect(server)
|
|
73
73
|
opts = server_opts(server)
|
|
74
74
|
|
|
75
|
-
if Mysql.
|
|
75
|
+
if defined?(Mysql.init)
|
|
76
76
|
conn = Mysql.init
|
|
77
77
|
conn.options(Mysql::READ_DEFAULT_GROUP, opts[:config_default_group] || "client")
|
|
78
78
|
conn.options(Mysql::OPT_LOCAL_INFILE, opts[:config_local_infile]) if opts.has_key?(:config_local_infile)
|
|
@@ -186,7 +186,7 @@ module Sequel
|
|
|
186
186
|
elsif defined?(yield)
|
|
187
187
|
yield conn
|
|
188
188
|
end
|
|
189
|
-
if conn.
|
|
189
|
+
if defined?(conn.more_results?)
|
|
190
190
|
while conn.more_results? do
|
|
191
191
|
if r
|
|
192
192
|
r.free
|
|
@@ -207,7 +207,7 @@ module Sequel
|
|
|
207
207
|
ensure
|
|
208
208
|
r.free if r
|
|
209
209
|
# Use up all results to avoid a commands out of sync message.
|
|
210
|
-
if conn.
|
|
210
|
+
if defined?(conn.more_results?)
|
|
211
211
|
while conn.more_results? do
|
|
212
212
|
begin
|
|
213
213
|
conn.next_result
|
|
@@ -149,7 +149,7 @@ module Sequel
|
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
def database_specific_error_class(exception, opts)
|
|
152
|
-
return super unless exception.
|
|
152
|
+
return super unless defined?(exception.code)
|
|
153
153
|
case exception.code
|
|
154
154
|
when 1400, 1407
|
|
155
155
|
NotNullConstraintViolation
|
|
@@ -5,6 +5,7 @@ require_relative 'shared/postgres'
|
|
|
5
5
|
begin
|
|
6
6
|
require 'pg'
|
|
7
7
|
|
|
8
|
+
# :nocov:
|
|
8
9
|
Sequel::Postgres::PGError = PG::Error if defined?(PG::Error)
|
|
9
10
|
Sequel::Postgres::PGconn = PG::Connection if defined?(PG::Connection)
|
|
10
11
|
Sequel::Postgres::PGresult = PG::Result if defined?(PG::Result)
|
|
@@ -14,14 +15,17 @@ begin
|
|
|
14
15
|
raise LoadError unless defined?(PGconn::CONNECTION_OK)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
Sequel::Postgres::USES_PG = true
|
|
18
18
|
if defined?(PG::TypeMapByClass)
|
|
19
|
+
# :nocov:
|
|
19
20
|
type_map = Sequel::Postgres::PG_QUERY_TYPE_MAP = PG::TypeMapByClass.new
|
|
20
21
|
type_map[Integer] = PG::TextEncoder::Integer.new
|
|
21
22
|
type_map[FalseClass] = type_map[TrueClass] = PG::TextEncoder::Boolean.new
|
|
22
23
|
type_map[Float] = PG::TextEncoder::Float.new
|
|
23
24
|
end
|
|
25
|
+
|
|
26
|
+
Sequel::Postgres::USES_PG = true
|
|
24
27
|
rescue LoadError => e
|
|
28
|
+
# :nocov:
|
|
25
29
|
begin
|
|
26
30
|
require 'sequel/postgres-pr'
|
|
27
31
|
rescue LoadError
|
|
@@ -32,16 +36,19 @@ rescue LoadError => e
|
|
|
32
36
|
end
|
|
33
37
|
end
|
|
34
38
|
Sequel::Postgres::USES_PG = false
|
|
39
|
+
# :nocov:
|
|
35
40
|
end
|
|
36
41
|
|
|
37
42
|
module Sequel
|
|
38
43
|
module Postgres
|
|
44
|
+
# :nocov:
|
|
39
45
|
if USES_PG
|
|
40
46
|
# Whether the given sequel_pg version integer is supported.
|
|
41
47
|
def self.sequel_pg_version_supported?(version)
|
|
42
48
|
version >= 10617
|
|
43
49
|
end
|
|
44
50
|
end
|
|
51
|
+
# :nocov:
|
|
45
52
|
|
|
46
53
|
# PGconn subclass for connection specific methods used with the
|
|
47
54
|
# pg or postgres-pr driver.
|
|
@@ -49,7 +56,9 @@ module Sequel
|
|
|
49
56
|
# The underlying exception classes to reraise as disconnect errors
|
|
50
57
|
# instead of regular database errors.
|
|
51
58
|
DISCONNECT_ERROR_CLASSES = [IOError, Errno::EPIPE, Errno::ECONNRESET]
|
|
59
|
+
# :nocov:
|
|
52
60
|
if defined?(::PG::ConnectionBad)
|
|
61
|
+
# :nocov:
|
|
53
62
|
DISCONNECT_ERROR_CLASSES << ::PG::ConnectionBad
|
|
54
63
|
end
|
|
55
64
|
DISCONNECT_ERROR_CLASSES.freeze
|
|
@@ -75,6 +84,7 @@ module Sequel
|
|
|
75
84
|
# are SQL strings.
|
|
76
85
|
attr_reader :prepared_statements
|
|
77
86
|
|
|
87
|
+
# :nocov:
|
|
78
88
|
unless public_method_defined?(:async_exec_params)
|
|
79
89
|
alias async_exec_params async_exec
|
|
80
90
|
end
|
|
@@ -117,6 +127,7 @@ module Sequel
|
|
|
117
127
|
alias cmd_tuples cmdtuples
|
|
118
128
|
end
|
|
119
129
|
end
|
|
130
|
+
# :nocov:
|
|
120
131
|
|
|
121
132
|
# Raise a Sequel::DatabaseDisconnectError if a one of the disconnect
|
|
122
133
|
# error classes is raised, or a PGError is raised and the connection
|
|
@@ -149,7 +160,7 @@ module Sequel
|
|
|
149
160
|
begin
|
|
150
161
|
defined?(yield) ? yield(q) : q.cmd_tuples
|
|
151
162
|
ensure
|
|
152
|
-
q.clear if q && q.
|
|
163
|
+
q.clear if q && defined?(q.clear)
|
|
153
164
|
end
|
|
154
165
|
end
|
|
155
166
|
|
|
@@ -210,7 +221,9 @@ module Sequel
|
|
|
210
221
|
:sslmode => opts[:sslmode],
|
|
211
222
|
:sslrootcert => opts[:sslrootcert]
|
|
212
223
|
}.delete_if { |key, value| blank_object?(value) }
|
|
224
|
+
# :nocov:
|
|
213
225
|
connection_params.merge!(opts[:driver_options]) if opts[:driver_options]
|
|
226
|
+
# :nocov:
|
|
214
227
|
conn = Adapter.connect(opts[:conn_str] || connection_params)
|
|
215
228
|
|
|
216
229
|
conn.instance_variable_set(:@prepared_statements, {})
|
|
@@ -218,6 +231,13 @@ module Sequel
|
|
|
218
231
|
if receiver = opts[:notice_receiver]
|
|
219
232
|
conn.set_notice_receiver(&receiver)
|
|
220
233
|
end
|
|
234
|
+
|
|
235
|
+
# :nocov:
|
|
236
|
+
if conn.respond_to?(:type_map_for_queries=) && defined?(PG_QUERY_TYPE_MAP)
|
|
237
|
+
# :nocov:
|
|
238
|
+
conn.type_map_for_queries = PG_QUERY_TYPE_MAP
|
|
239
|
+
end
|
|
240
|
+
# :nocov:
|
|
221
241
|
else
|
|
222
242
|
unless typecast_value_boolean(@opts.fetch(:force_standard_strings, true))
|
|
223
243
|
raise Error, "Cannot create connection using postgres-pr unless force_standard_strings is set"
|
|
@@ -232,19 +252,19 @@ module Sequel
|
|
|
232
252
|
opts[:password]
|
|
233
253
|
)
|
|
234
254
|
end
|
|
255
|
+
# :nocov:
|
|
235
256
|
|
|
236
257
|
conn.instance_variable_set(:@db, self)
|
|
237
|
-
if USES_PG && conn.respond_to?(:type_map_for_queries=) && defined?(PG_QUERY_TYPE_MAP)
|
|
238
|
-
conn.type_map_for_queries = PG_QUERY_TYPE_MAP
|
|
239
|
-
end
|
|
240
258
|
|
|
259
|
+
# :nocov:
|
|
241
260
|
if encoding = opts[:encoding] || opts[:charset]
|
|
242
|
-
if conn.
|
|
261
|
+
if defined?(conn.set_client_encoding)
|
|
243
262
|
conn.set_client_encoding(encoding)
|
|
244
263
|
else
|
|
245
264
|
conn.async_exec("set client_encoding to '#{encoding}'")
|
|
246
265
|
end
|
|
247
266
|
end
|
|
267
|
+
# :nocov:
|
|
248
268
|
|
|
249
269
|
connection_configuration_sqls(opts).each{|sql| conn.execute(sql)}
|
|
250
270
|
conn
|
|
@@ -271,7 +291,9 @@ module Sequel
|
|
|
271
291
|
nil
|
|
272
292
|
end
|
|
273
293
|
|
|
294
|
+
# :nocov:
|
|
274
295
|
if USES_PG && Object.const_defined?(:PG) && ::PG.const_defined?(:Constants) && ::PG::Constants.const_defined?(:PG_DIAG_SCHEMA_NAME)
|
|
296
|
+
# :nocov:
|
|
275
297
|
# Return a hash of information about the related PGError (or Sequel::DatabaseError that
|
|
276
298
|
# wraps a PGError), with the following entries (any of which may be +nil+):
|
|
277
299
|
#
|
|
@@ -322,7 +344,9 @@ module Sequel
|
|
|
322
344
|
synchronize(opts[:server]){|conn| check_database_errors{_execute(conn, sql, opts, &block)}}
|
|
323
345
|
end
|
|
324
346
|
|
|
347
|
+
# :nocov:
|
|
325
348
|
if USES_PG
|
|
349
|
+
# :nocov:
|
|
326
350
|
# +copy_table+ uses PostgreSQL's +COPY TO STDOUT+ SQL statement to return formatted
|
|
327
351
|
# results directly to the caller. This method is only supported if pg is the
|
|
328
352
|
# underlying ruby driver. This method should only be called if you want
|
|
@@ -468,12 +492,12 @@ module Sequel
|
|
|
468
492
|
opts[:after_listen].call(conn) if opts[:after_listen]
|
|
469
493
|
timeout = opts[:timeout]
|
|
470
494
|
if timeout
|
|
471
|
-
timeout_block = timeout.
|
|
495
|
+
timeout_block = defined?(timeout.call) ? timeout : proc{timeout}
|
|
472
496
|
end
|
|
473
497
|
|
|
474
498
|
if l = opts[:loop]
|
|
475
499
|
raise Error, 'calling #listen with :loop requires a block' unless block
|
|
476
|
-
loop_call = l.
|
|
500
|
+
loop_call = defined?(l.call)
|
|
477
501
|
catch(:stop) do
|
|
478
502
|
while true
|
|
479
503
|
t = timeout_block ? [timeout_block.call] : []
|
|
@@ -515,8 +539,10 @@ module Sequel
|
|
|
515
539
|
def adapter_initialize
|
|
516
540
|
@use_iso_date_format = typecast_value_boolean(@opts.fetch(:use_iso_date_format, true))
|
|
517
541
|
initialize_postgres_adapter
|
|
542
|
+
# :nocov:
|
|
518
543
|
add_conversion_proc(17, method(:unescape_bytea)) if USES_PG
|
|
519
544
|
add_conversion_proc(1082, TYPE_TRANSLATOR_DATE) if @use_iso_date_format
|
|
545
|
+
# :nocov:
|
|
520
546
|
self.convert_infinite_timestamps = @opts[:convert_infinite_timestamps]
|
|
521
547
|
end
|
|
522
548
|
|
|
@@ -526,19 +552,22 @@ module Sequel
|
|
|
526
552
|
rescue => e
|
|
527
553
|
raise_error(e, :classes=>database_error_classes)
|
|
528
554
|
end
|
|
529
|
-
|
|
530
555
|
# Set the DateStyle to ISO if configured, for faster date parsing.
|
|
531
556
|
def connection_configuration_sqls(opts=@opts)
|
|
532
557
|
sqls = super
|
|
558
|
+
# :nocov:
|
|
533
559
|
sqls << "SET DateStyle = 'ISO'" if @use_iso_date_format
|
|
560
|
+
# :nocov:
|
|
534
561
|
sqls
|
|
535
562
|
end
|
|
536
563
|
|
|
564
|
+
# :nocov:
|
|
537
565
|
if USES_PG
|
|
538
566
|
def unescape_bytea(s)
|
|
539
567
|
::Sequel::SQL::Blob.new(Adapter.unescape_bytea(s))
|
|
540
568
|
end
|
|
541
569
|
end
|
|
570
|
+
# :nocov:
|
|
542
571
|
|
|
543
572
|
DATABASE_ERROR_CLASSES = [PGError].freeze
|
|
544
573
|
def database_error_classes
|
|
@@ -552,7 +581,9 @@ module Sequel
|
|
|
552
581
|
end
|
|
553
582
|
|
|
554
583
|
def database_exception_sqlstate(exception, opts)
|
|
555
|
-
|
|
584
|
+
# :nocov:
|
|
585
|
+
if defined?(exception.result) && (result = exception.result)
|
|
586
|
+
# :nocov:
|
|
556
587
|
result.error_field(PGresult::PG_DIAG_SQLSTATE)
|
|
557
588
|
end
|
|
558
589
|
end
|
|
@@ -594,7 +625,7 @@ module Sequel
|
|
|
594
625
|
begin
|
|
595
626
|
defined?(yield) ? yield(q) : q.cmd_tuples
|
|
596
627
|
ensure
|
|
597
|
-
q.clear if q && q.
|
|
628
|
+
q.clear if q && defined?(q.clear)
|
|
598
629
|
end
|
|
599
630
|
end
|
|
600
631
|
|
|
@@ -662,7 +693,9 @@ module Sequel
|
|
|
662
693
|
clone(:where=>Sequel.lit(['CURRENT OF '], Sequel.identifier(cursor_name)))
|
|
663
694
|
end
|
|
664
695
|
|
|
696
|
+
# :nocov:
|
|
665
697
|
if USES_PG
|
|
698
|
+
# :nocov:
|
|
666
699
|
PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
|
|
667
700
|
|
|
668
701
|
# PostgreSQL specific argument mapper used for mapping the named
|
|
@@ -809,6 +842,7 @@ module Sequel
|
|
|
809
842
|
end
|
|
810
843
|
end
|
|
811
844
|
|
|
845
|
+
# :nocov:
|
|
812
846
|
if Sequel::Postgres::USES_PG && !ENV['NO_SEQUEL_PG']
|
|
813
847
|
begin
|
|
814
848
|
require 'sequel_pg'
|
|
@@ -820,3 +854,4 @@ if Sequel::Postgres::USES_PG && !ENV['NO_SEQUEL_PG']
|
|
|
820
854
|
rescue LoadError
|
|
821
855
|
end
|
|
822
856
|
end
|
|
857
|
+
# :nocov:
|
|
@@ -205,7 +205,7 @@ module Sequel
|
|
|
205
205
|
return @server_version = Integer(@opts[:server_version])
|
|
206
206
|
end
|
|
207
207
|
@server_version = synchronize(server) do |conn|
|
|
208
|
-
(conn.server_version rescue nil) if conn.
|
|
208
|
+
(conn.server_version rescue nil) if defined?(conn.server_version)
|
|
209
209
|
end
|
|
210
210
|
unless @server_version
|
|
211
211
|
m = /^(\d+)\.(\d+)\.(\d+)/.match(fetch("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)").single_value.to_s)
|
|
@@ -121,7 +121,7 @@ module Sequel
|
|
|
121
121
|
def server_version(server=nil)
|
|
122
122
|
return @server_version if @server_version
|
|
123
123
|
@server_version = synchronize(server) do |conn|
|
|
124
|
-
(conn.server_version rescue nil) if conn.
|
|
124
|
+
(conn.server_version rescue nil) if defined?(conn.server_version)
|
|
125
125
|
end
|
|
126
126
|
unless @server_version
|
|
127
127
|
@server_version = if m = /(\d+)\.(\d+)\.?(\d+)?\.?(\d+)?/.match(fetch("select version from PRODUCT_COMPONENT_VERSION where lower(product) like 'oracle%'").single_value)
|
|
@@ -230,7 +230,6 @@ module Sequel
|
|
|
230
230
|
module DatabaseMethods
|
|
231
231
|
include UnmodifiedIdentifiers::DatabaseMethods
|
|
232
232
|
|
|
233
|
-
PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
|
|
234
233
|
FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'=>:no_action, 'r'=>:restrict, 'c'=>:cascade, 'n'=>:set_null, 'd'=>:set_default}.freeze
|
|
235
234
|
ON_COMMIT = {:drop => 'DROP', :delete_rows => 'DELETE ROWS', :preserve_rows => 'PRESERVE ROWS'}.freeze
|
|
236
235
|
ON_COMMIT.each_value(&:freeze)
|
|
@@ -365,9 +364,10 @@ module Sequel
|
|
|
365
364
|
|
|
366
365
|
table_oid = regclass_oid(table)
|
|
367
366
|
im = input_identifier_meth
|
|
368
|
-
unless column =
|
|
367
|
+
unless column = (opts[:column] || ((sch = schema(table).find{|_, sc| sc[:primary_key] && sc[:auto_increment]}) && sch[0]))
|
|
369
368
|
raise Error, "could not determine column to convert from serial to identity automatically"
|
|
370
369
|
end
|
|
370
|
+
column = im.call(column)
|
|
371
371
|
|
|
372
372
|
column_num = ds.from(:pg_attribute).
|
|
373
373
|
where(:attrelid=>table_oid, :attname=>column).
|
|
@@ -569,10 +569,12 @@ module Sequel
|
|
|
569
569
|
if server_version >= 90500
|
|
570
570
|
cpos = Sequel.expr{array_position(co[:conkey], ctable[:attnum])}
|
|
571
571
|
rpos = Sequel.expr{array_position(co[:confkey], rtable[:attnum])}
|
|
572
|
+
# :nocov:
|
|
572
573
|
else
|
|
573
574
|
range = 0...32
|
|
574
575
|
cpos = Sequel.expr{SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(co[:conkey], [x]), x]}, 32, ctable[:attnum])}
|
|
575
576
|
rpos = Sequel.expr{SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(co[:confkey], [x]), x]}, 32, rtable[:attnum])}
|
|
577
|
+
# :nocov:
|
|
576
578
|
end
|
|
577
579
|
|
|
578
580
|
ds = metadata_dataset.
|
|
@@ -653,9 +655,11 @@ module Sequel
|
|
|
653
655
|
|
|
654
656
|
if server_version >= 90500
|
|
655
657
|
order = [Sequel[:indc][:relname], Sequel.function(:array_position, Sequel[:ind][:indkey], Sequel[:att][:attnum])]
|
|
658
|
+
# :nocov:
|
|
656
659
|
else
|
|
657
660
|
range = 0...32
|
|
658
661
|
order = [Sequel[:indc][:relname], SQL::CaseExpression.new(range.map{|x| [SQL::Subscript.new(Sequel[:ind][:indkey], [x]), x]}, 32, Sequel[:att][:attnum])]
|
|
662
|
+
# :nocov:
|
|
659
663
|
end
|
|
660
664
|
|
|
661
665
|
attnums = SQL::Function.new(:ANY, Sequel[:ind][:indkey])
|
|
@@ -676,8 +680,10 @@ module Sequel
|
|
|
676
680
|
select{[indc[:relname].as(:name), ind[:indisunique].as(:unique), att[:attname].as(:column), con[:condeferrable].as(:deferrable)]}
|
|
677
681
|
|
|
678
682
|
ds = ds.where(:indpred=>nil) unless opts[:include_partial]
|
|
683
|
+
# :nocov:
|
|
679
684
|
ds = ds.where(:indisready=>true) if server_version >= 80300
|
|
680
685
|
ds = ds.where(:indislive=>true) if server_version >= 90300
|
|
686
|
+
# :nocov:
|
|
681
687
|
|
|
682
688
|
indexes = {}
|
|
683
689
|
ds.each do |r|
|
|
@@ -758,10 +764,12 @@ module Sequel
|
|
|
758
764
|
seq_ds = metadata_dataset.from(:pg_sequence).where(:seqrelid=>regclass_oid(LiteralString.new(seq)))
|
|
759
765
|
increment_by = :seqincrement
|
|
760
766
|
min_value = :seqmin
|
|
767
|
+
# :nocov:
|
|
761
768
|
else
|
|
762
769
|
seq_ds = metadata_dataset.from(LiteralString.new(seq))
|
|
763
770
|
increment_by = :increment_by
|
|
764
771
|
min_value = :min_value
|
|
772
|
+
# :nocov:
|
|
765
773
|
end
|
|
766
774
|
|
|
767
775
|
get{setval(seq, db[table].select(coalesce(max(pk)+seq_ds.select(increment_by), seq_ds.select(min_value))), false)}
|
|
@@ -774,7 +782,9 @@ module Sequel
|
|
|
774
782
|
# PostgreSQL uses SERIAL psuedo-type instead of AUTOINCREMENT for
|
|
775
783
|
# managing incrementing primary keys.
|
|
776
784
|
def serial_primary_key_options
|
|
785
|
+
# :nocov:
|
|
777
786
|
auto_increment_key = server_version >= 100002 ? :identity : :serial
|
|
787
|
+
# :nocov:
|
|
778
788
|
{:primary_key => true, auto_increment_key => true, :type=>Integer}
|
|
779
789
|
end
|
|
780
790
|
|
|
@@ -1152,7 +1162,7 @@ module Sequel
|
|
|
1152
1162
|
when :hash
|
|
1153
1163
|
mod, remainder = generator.hash_values
|
|
1154
1164
|
sql << " FOR VALUES WITH (MODULUS #{literal(mod)}, REMAINDER #{literal(remainder)})"
|
|
1155
|
-
when :default
|
|
1165
|
+
else # when :default
|
|
1156
1166
|
sql << " DEFAULT"
|
|
1157
1167
|
end
|
|
1158
1168
|
|
|
@@ -1356,11 +1366,6 @@ module Sequel
|
|
|
1356
1366
|
end
|
|
1357
1367
|
end
|
|
1358
1368
|
|
|
1359
|
-
# Use a dollar sign instead of question mark for the argument placeholder.
|
|
1360
|
-
def prepared_arg_placeholder
|
|
1361
|
-
PREPARED_ARG_PLACEHOLDER
|
|
1362
|
-
end
|
|
1363
|
-
|
|
1364
1369
|
# Return an expression the oid for the table expr. Used by the metadata parsing
|
|
1365
1370
|
# code to disambiguate unqualified tables.
|
|
1366
1371
|
def regclass_oid(expr, opts=OPTS)
|
|
@@ -1434,10 +1439,14 @@ module Sequel
|
|
|
1434
1439
|
where{{pg_class[:oid]=>oid}}.
|
|
1435
1440
|
order{pg_attribute[:attnum]}
|
|
1436
1441
|
|
|
1442
|
+
# :nocov:
|
|
1437
1443
|
if server_version > 100000
|
|
1444
|
+
# :nocov:
|
|
1438
1445
|
ds = ds.select_append{pg_attribute[:attidentity]}
|
|
1439
1446
|
|
|
1447
|
+
# :nocov:
|
|
1440
1448
|
if server_version > 120000
|
|
1449
|
+
# :nocov:
|
|
1441
1450
|
ds = ds.select_append{Sequel.~(pg_attribute[:attgenerated]=>'').as(:generated)}
|
|
1442
1451
|
end
|
|
1443
1452
|
end
|
|
@@ -1525,7 +1534,9 @@ module Sequel
|
|
|
1525
1534
|
|
|
1526
1535
|
# PostgreSQL 9.4+ supports views with check option.
|
|
1527
1536
|
def view_with_check_option_support
|
|
1537
|
+
# :nocov:
|
|
1528
1538
|
:local if server_version >= 90400
|
|
1539
|
+
# :nocov:
|
|
1529
1540
|
end
|
|
1530
1541
|
end
|
|
1531
1542
|
|
|
@@ -1921,6 +1932,8 @@ module Sequel
|
|
|
1921
1932
|
server_version >= 90000
|
|
1922
1933
|
when :groups, :exclude
|
|
1923
1934
|
server_version >= 110000
|
|
1935
|
+
else
|
|
1936
|
+
false
|
|
1924
1937
|
end
|
|
1925
1938
|
end
|
|
1926
1939
|
|
|
@@ -2067,12 +2080,11 @@ module Sequel
|
|
|
2067
2080
|
|
|
2068
2081
|
# Return the primary key to use for RETURNING in an INSERT statement
|
|
2069
2082
|
def insert_pk
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
end
|
|
2083
|
+
(f = opts[:from]) && !f.empty? && (t = f.first)
|
|
2084
|
+
case t
|
|
2085
|
+
when Symbol, String, SQL::Identifier, SQL::QualifiedIdentifier
|
|
2086
|
+
if pk = db.primary_key(t)
|
|
2087
|
+
Sequel::SQL::Identifier.new(pk)
|
|
2076
2088
|
end
|
|
2077
2089
|
end
|
|
2078
2090
|
end
|
|
@@ -663,7 +663,7 @@ module Sequel
|
|
|
663
663
|
|
|
664
664
|
# HAVING requires GROUP BY on SQLite
|
|
665
665
|
def having(*cond)
|
|
666
|
-
raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset")
|
|
666
|
+
raise(InvalidOperation, "Can only specify a HAVING clause on a grouped dataset") if !@opts[:group] && db.sqlite_version < 33900
|
|
667
667
|
super
|
|
668
668
|
end
|
|
669
669
|
|
|
@@ -305,7 +305,7 @@ module Sequel
|
|
|
305
305
|
if USE_EXTENDED_RESULT_CODES
|
|
306
306
|
# Support SQLite exception codes if ruby-sqlite3 supports them.
|
|
307
307
|
def sqlite_error_code(exception)
|
|
308
|
-
exception.code if exception.
|
|
308
|
+
exception.code if defined?(exception.code)
|
|
309
309
|
end
|
|
310
310
|
end
|
|
311
311
|
end
|
data/lib/sequel/database/misc.rb
CHANGED
|
@@ -350,7 +350,7 @@ module Sequel
|
|
|
350
350
|
# strings with all whitespace, and ones that respond
|
|
351
351
|
# true to empty?
|
|
352
352
|
def blank_object?(obj)
|
|
353
|
-
return obj.blank? if obj.
|
|
353
|
+
return obj.blank? if defined?(obj.blank?)
|
|
354
354
|
case obj
|
|
355
355
|
when NilClass, FalseClass
|
|
356
356
|
true
|
|
@@ -359,7 +359,7 @@ module Sequel
|
|
|
359
359
|
when String
|
|
360
360
|
obj.strip.empty?
|
|
361
361
|
else
|
|
362
|
-
obj.
|
|
362
|
+
defined?(obj.empty?) ? obj.empty? : false
|
|
363
363
|
end
|
|
364
364
|
end
|
|
365
365
|
|
data/lib/sequel/dataset/sql.rb
CHANGED
|
@@ -1398,9 +1398,9 @@ module Sequel
|
|
|
1398
1398
|
# don't cache SQL for a dataset that uses this.
|
|
1399
1399
|
disable_sql_caching!
|
|
1400
1400
|
|
|
1401
|
-
if v.
|
|
1401
|
+
if defined?(v.sql_literal_append)
|
|
1402
1402
|
v.sql_literal_append(self, sql)
|
|
1403
|
-
elsif v.
|
|
1403
|
+
elsif defined?(v.sql_literal)
|
|
1404
1404
|
sql << v.sql_literal(self)
|
|
1405
1405
|
else
|
|
1406
1406
|
raise Error, "can't express #{v.inspect} as a SQL literal"
|