sequel 5.56.0 → 5.59.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 +32 -0
- data/README.rdoc +25 -0
- data/doc/cheat_sheet.rdoc +8 -0
- data/doc/opening_databases.rdoc +10 -6
- data/doc/release_notes/5.57.0.txt +23 -0
- data/doc/release_notes/5.58.0.txt +31 -0
- data/doc/release_notes/5.59.0.txt +73 -0
- data/doc/testing.rdoc +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +5 -0
- data/lib/sequel/adapters/jdbc/h2.rb +5 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +6 -0
- data/lib/sequel/adapters/postgres.rb +12 -6
- data/lib/sequel/adapters/shared/db2.rb +28 -0
- data/lib/sequel/adapters/shared/mssql.rb +34 -0
- data/lib/sequel/adapters/shared/mysql.rb +12 -0
- data/lib/sequel/adapters/shared/oracle.rb +69 -0
- data/lib/sequel/adapters/shared/postgres.rb +70 -4
- data/lib/sequel/database/schema_generator.rb +4 -0
- data/lib/sequel/database/schema_methods.rb +3 -0
- data/lib/sequel/dataset/actions.rb +49 -0
- data/lib/sequel/dataset/features.rb +5 -0
- data/lib/sequel/dataset/query.rb +62 -0
- data/lib/sequel/dataset/sql.rb +112 -25
- data/lib/sequel/extensions/is_distinct_from.rb +139 -0
- data/lib/sequel/extensions/pg_hstore.rb +1 -1
- data/lib/sequel/extensions/pg_json_ops.rb +52 -0
- data/lib/sequel/model/associations.rb +12 -0
- data/lib/sequel/model/base.rb +14 -4
- data/lib/sequel/plugins/insert_conflict.rb +4 -0
- data/lib/sequel/plugins/list.rb +3 -1
- data/lib/sequel/plugins/require_valid_schema.rb +67 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -0
- data/lib/sequel/version.rb +1 -1
- metadata +10 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47d7144911d61be13cc600fc3153c8e30eb384476ea7fb94ce61bd0f2f627c36
|
4
|
+
data.tar.gz: fa763e2f24d5b6b26feecb405b5a43d8bbf30d2b727590e8fd98031640dfef2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3855f6fbb47f26bfd0e9570ed8b7e908815bc7de3752751b92708c3e88948719f62dafe26cc1ea83b598c73e1ee84e4dbf12f01437dd1b087eed68ca4281b33d
|
7
|
+
data.tar.gz: 932fa5c97bc8dcf077a50961b2da7ecd59ae0c077409c2b0c3111d875fe468d5fbb4030f155faf17d3ba3ed0392e264d8e5ebaa11ad04db3ab98c209e2199440
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
=== 5.59.0 (2022-08-01)
|
2
|
+
|
3
|
+
* Set :allow_eager association option to false for instance specific associations without eager loaders (jeremyevans)
|
4
|
+
|
5
|
+
* Add require_valid_schema plugin for checking that model classes have schema parsed as expected (jeremyevans)
|
6
|
+
|
7
|
+
* Model classes created from aliased expressions and literal strings no longer use the simple table optimization (jeremyevans)
|
8
|
+
|
9
|
+
* Model code that does not swallow connection errors will now also not swallow disconnect errors (jeremyevans) (#1892)
|
10
|
+
|
11
|
+
* Add is_json and is_not_json methods to the pg_json_ops extension, for the PostgreSQL 15+ IS [NOT] JSON operator (jeremyevans)
|
12
|
+
|
13
|
+
* Support :security_invoker view option on PostgreSQL 15+, for views where access uses permissions of user instead of owner (jeremyevans)
|
14
|
+
|
15
|
+
* Support :nulls_distinct index option on PostgreSQL 15+, for NULLS [NOT] DISTINCT (jeremyevans)
|
16
|
+
|
17
|
+
* Support sequel-postgres-pr driver in the postgres adapter (jeremyevans)
|
18
|
+
|
19
|
+
=== 5.58.0 (2022-07-01)
|
20
|
+
|
21
|
+
* Support :disable_split_materialized Database option on MySQL to work around optimizer bug in MariaDB 10.5+ affecting association tests (jeremyevans)
|
22
|
+
|
23
|
+
* Add Dataset#merge* methods to support MERGE statement on PostgreSQL 15+, MSSQL, Oracle, DB2, H2, HSQLDB, and Derby (jeremyevans)
|
24
|
+
|
25
|
+
=== 5.57.0 (2022-06-01)
|
26
|
+
|
27
|
+
* Make Database#create_function on PostgreSQL accept :parallel option (bananarne) (#1870)
|
28
|
+
|
29
|
+
* Add support for :on_update_current_timestamp column option on MySQL (jeremyevans)
|
30
|
+
|
31
|
+
* Add is_distinct_from extension with support for the IS DISTINCT FROM operator (jeremyevans)
|
32
|
+
|
1
33
|
=== 5.56.0 (2022-05-01)
|
2
34
|
|
3
35
|
* Make alter_table add_column/add_foreign_key methods support :index option to create an index on the column (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -414,6 +414,31 @@ As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
|
|
414
414
|
# NOT THIS:
|
415
415
|
posts.update(:state => 'archived').where(Sequel[:stamp] < Date.today - 7)
|
416
416
|
|
417
|
+
=== Merging records
|
418
|
+
|
419
|
+
Merging records using the SQL MERGE statment is done using <tt>merge*</tt> methods.
|
420
|
+
You use +merge_using+ to specify the merge source and join conditions.
|
421
|
+
You can use +merge_insert+, +merge_delete+, and/or +merge_update+ to set the
|
422
|
+
INSERT, DELETE, and UPDATE clauses for the merge. +merge_insert+ takes the same
|
423
|
+
arguments as +insert+, and +merge_update+ takes the same arguments as +update+.
|
424
|
+
+merge_insert+, +merge_delete+, and +merge_update+ can all be called with blocks,
|
425
|
+
to set the conditions for the related INSERT, DELETE, or UPDATE.
|
426
|
+
|
427
|
+
Finally, after calling all of the other <tt>merge_*</tt> methods, you call +merge+
|
428
|
+
to run the MERGE statement on the database.
|
429
|
+
|
430
|
+
ds = DB[:m1]
|
431
|
+
merge_using(:m2, i1: :i2).
|
432
|
+
merge_insert(i1: :i2, a: Sequel[:b]+11).
|
433
|
+
merge_delete{a > 30}.
|
434
|
+
merge_update(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20)
|
435
|
+
|
436
|
+
ds.merge
|
437
|
+
# MERGE INTO m1 USING m2 ON (i1 = i2)
|
438
|
+
# WHEN NOT MATCHED THEN INSERT (i1, a) VALUES (i2, (b + 11))
|
439
|
+
# WHEN MATCHED AND (a > 30) THEN DELETE
|
440
|
+
# WHEN MATCHED THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
441
|
+
|
417
442
|
=== Transactions
|
418
443
|
|
419
444
|
You can wrap a block of code in a database transaction using the <tt>Database#transaction</tt> method:
|
data/doc/cheat_sheet.rdoc
CHANGED
@@ -57,6 +57,14 @@ Without a filename argument, the sqlite adapter will setup a new sqlite database
|
|
57
57
|
dataset.where{price < 100}.update(:active => true)
|
58
58
|
dataset.where(:active).update(:price => Sequel[:price] * 0.90)
|
59
59
|
|
60
|
+
= Merge rows
|
61
|
+
|
62
|
+
dataset.
|
63
|
+
merge_using(:table, col1: :col2).
|
64
|
+
merge_insert(col3: :col4).
|
65
|
+
merge_delete{col5 > 30}.
|
66
|
+
merge_update(col3: Sequel[:col3] + :col4)
|
67
|
+
|
60
68
|
== Datasets are Enumerable
|
61
69
|
|
62
70
|
dataset.map{|r| r[:name]}
|
data/doc/opening_databases.rdoc
CHANGED
@@ -102,6 +102,7 @@ The following options can be specified and are passed to the database's internal
|
|
102
102
|
:after_connect :: A callable object called after each new connection is made, with the
|
103
103
|
connection object (and server argument if the callable accepts 2 arguments),
|
104
104
|
useful for customizations that you want to apply to all connections (nil by default).
|
105
|
+
:connect_sqls :: An array of sql strings to execute on each new connection, after :after_connect runs.
|
105
106
|
:max_connections :: The maximum size of the connection pool (4 connections by default on most databases)
|
106
107
|
:pool_timeout :: The number of seconds to wait if a connection cannot be acquired before raising an error (5 seconds by default)
|
107
108
|
:single_threaded :: Whether to use a single-threaded (non-thread safe) connection pool
|
@@ -258,6 +259,8 @@ The following additional options are supported:
|
|
258
259
|
:compress :: Whether to compress data sent/received via the socket connection.
|
259
260
|
:config_default_group :: The default group to read from the in the MySQL config file, defaults to "client")
|
260
261
|
:config_local_infile :: If provided, sets the Mysql::OPT_LOCAL_INFILE option on the connection with the given value.
|
262
|
+
:disable_split_materialized :: Set split_materialized=off in the optimizer settings. Necessary to pass the associations
|
263
|
+
integration tests in MariaDB 10.5+, due to a unfixed bug in the optimizer.
|
261
264
|
:encoding :: Specify the encoding/character set to use for the connection.
|
262
265
|
:fractional_seconds :: On MySQL 5.6.5+, this option is recognized and will include fractional seconds in
|
263
266
|
time/timestamp values, as well as have the schema method create columns that can contain
|
@@ -278,7 +281,9 @@ if either the :sslca or :sslkey option is given.
|
|
278
281
|
|
279
282
|
This is a newer MySQL adapter that does typecasting in C, so it is often faster than the
|
280
283
|
mysql adapter. The options given are passed to Mysql2::Client.new, see the mysql2 documentation
|
281
|
-
for details on what options are supported.
|
284
|
+
for details on what options are supported. The :timeout, :auto_is_null, :sql_mode, and :disable_split_materialized
|
285
|
+
options supported by the mysql adapter are also supported for mysql2 adapter (and any other adapters connecting to
|
286
|
+
mysql, such as the jdbc/mysql adapter).
|
282
287
|
|
283
288
|
=== odbc
|
284
289
|
|
@@ -307,15 +312,14 @@ The following additional options are supported:
|
|
307
312
|
|
308
313
|
=== postgres
|
309
314
|
|
310
|
-
Requires: pg (or postgres-pr/postgres-compat if pg is not available)
|
315
|
+
Requires: pg (or sequel/postgres-pr or postgres-pr/postgres-compat if pg is not available)
|
311
316
|
|
312
|
-
The Sequel postgres adapter works with the pg and postgres-pr ruby libraries.
|
317
|
+
The Sequel postgres adapter works with the pg, sequel-postgres-pr, jeremyevans-postgres-pr, and postgres-pr ruby libraries.
|
313
318
|
The pg library is the best supported, as it supports real bound variables and prepared statements.
|
314
319
|
If the pg library is being used, Sequel will also attempt to load the sequel_pg library, which is
|
315
320
|
a C extension that optimizes performance when Sequel is used with pg. All users of Sequel who
|
316
|
-
use pg are encouraged to install sequel_pg. For users who want to use postgres-pr
|
317
|
-
with C extensions, it is recommended to use
|
318
|
-
the upstream postgres-pr gem, and is regularly tested with Sequel.
|
321
|
+
use pg are encouraged to install sequel_pg. For users who want to use one of the postgres-pr
|
322
|
+
libraries to avoid issues with C extensions, it is recommended to use sequel-postgres-pr.
|
319
323
|
|
320
324
|
The following additional options are supported:
|
321
325
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An is_distinct_from extension has been added with support for the
|
4
|
+
SQL IS DISTINCT FROM operator. This operator is similar to the
|
5
|
+
not equals operator, except in terms of NULL handling. It returns
|
6
|
+
true if only one side is NULL, and false if both sides are NULL.
|
7
|
+
You can call is_distinct_from on Sequel itself or on Sequel objects:
|
8
|
+
|
9
|
+
Sequel.is_distinct_from(:column_a, :column_b)
|
10
|
+
Sequel[:column_a].is_distinct_from(:column_b)
|
11
|
+
# (column_a IS DISTINCT FROM column_b)
|
12
|
+
|
13
|
+
On databases not supporting IS DISTINCT FROM, support is emulated
|
14
|
+
using a CASE statement.
|
15
|
+
|
16
|
+
* Column definitions on MySQL can use the :on_update_current_timestamp
|
17
|
+
option for ON UPDATE CURRENT_TIMESTAMP, which creates a column that
|
18
|
+
will automatically have its value set to CURRENT_TIMESTAMP on every
|
19
|
+
update.
|
20
|
+
|
21
|
+
* Database#create_function on PostgreSQL now supports a :parallel
|
22
|
+
option to set the thread safety of the funciton. The value should
|
23
|
+
be :safe, :unsafe, or :restricted.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* Dataset#merge and related #merge_* methods have been added for the
|
4
|
+
MERGE statement. MERGE is supported on PostgreSQL 15+, Oracle,
|
5
|
+
Microsoft SQL Server, DB2, H2, HSQLDB, and Derby. You can use MERGE
|
6
|
+
to insert, update, and/or delete in a single query. You call
|
7
|
+
the #merge_* methods to setup the MERGE statement, and #merge to
|
8
|
+
execute it on the database:
|
9
|
+
|
10
|
+
ds = DB[:m1]
|
11
|
+
merge_using(:m2, i1: :i2).
|
12
|
+
merge_insert(i1: :i2, a: Sequel[:b]+11).
|
13
|
+
merge_delete{a > 30}.
|
14
|
+
merge_update(i1: Sequel[:i1]+:i2+10, a: Sequel[:a]+:b+20)
|
15
|
+
|
16
|
+
ds.merge
|
17
|
+
# MERGE INTO m1 USING m2 ON (i1 = i2)
|
18
|
+
# WHEN NOT MATCHED THEN INSERT (i1, a) VALUES (i2, (b + 11))
|
19
|
+
# WHEN MATCHED AND (a > 30) THEN DELETE
|
20
|
+
# WHEN MATCHED THEN UPDATE SET i1 = (i1 + i2 + 10), a = (a + b + 20)
|
21
|
+
|
22
|
+
On PostgreSQL, the following additional MERGE related methods are
|
23
|
+
available:
|
24
|
+
|
25
|
+
* #merge_do_nothing_when_matched
|
26
|
+
* #merge_do_nothing_when_not_matched
|
27
|
+
|
28
|
+
* A :disable_split_materialized Database option is now supported on
|
29
|
+
MySQL. This disables split_materialized support in the optimizer,
|
30
|
+
working around a bug in MariaDB 10.5+ that causes failures in
|
31
|
+
Sequel's association tests.
|
@@ -0,0 +1,73 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A require_valid_schema plugin has been added, for checking that
|
4
|
+
model classes have schema parsed as expected. By default, model
|
5
|
+
classes are not required to have valid schema, because it is
|
6
|
+
allowed to have model classes based on arbitrary datasets (such
|
7
|
+
as those using joins or set-returning functions), and it is not
|
8
|
+
possible to determine the schema for arbitary datasets.
|
9
|
+
|
10
|
+
Sequel swallows non-connection errors when trying to parse schema
|
11
|
+
for a model's dataset, but if schema parsing fails when you would
|
12
|
+
expect it to succeed, it results in a model where typecasting does
|
13
|
+
not work as expected.
|
14
|
+
|
15
|
+
The require_valid_schema plugin will raise an error when setting
|
16
|
+
the dataset for a model if schema parsing fails and the dataset
|
17
|
+
uses a simple table where you would expect schema parsing to
|
18
|
+
succeed. You can also provide an argument of :warn when loading
|
19
|
+
the plugin, to warn instead of raising an error.
|
20
|
+
|
21
|
+
This plugin may not work correctly in all cases for all adapters,
|
22
|
+
especially external adapters. Adapters are not required to support
|
23
|
+
schema parsing. Even if supported, adapters may not support
|
24
|
+
parsing schema for qualified tables, or parsing schema for views.
|
25
|
+
You should consider this plugin as a possible safety net. Users
|
26
|
+
are encouraged to try using it and report any unexpected breakage,
|
27
|
+
as that may help improve schema parsing in adapters that Sequel
|
28
|
+
ships.
|
29
|
+
|
30
|
+
* is_json and is_not_json methods have been added to the pg_json_ops
|
31
|
+
extension, for the IS [NOT] JSON operator supported in PostgreSQL
|
32
|
+
15+.
|
33
|
+
|
34
|
+
* Index creation methods on PostgreSQL 15+ now support a
|
35
|
+
:nulls_distinct option, for NULLS [NOT] DISTINCT. This allows you
|
36
|
+
to create unique indexes where NULL values are not considered
|
37
|
+
distinct.
|
38
|
+
|
39
|
+
* View creation methods on PostgreSQL 15+ now support a
|
40
|
+
:security_invoker option to create a view where access is
|
41
|
+
determined by the permissions of the role that is accessing the
|
42
|
+
view, instead of the role that created the view.
|
43
|
+
|
44
|
+
= Other Improvements
|
45
|
+
|
46
|
+
* The :allow_eager association option is now set to false by default
|
47
|
+
for associations explicitly marked as :instance_specific, if the
|
48
|
+
:eager_loader association is not given.
|
49
|
+
|
50
|
+
* The postgres adapter now supports the sequel-postgres-pr driver.
|
51
|
+
The sequel-postgres-pr driver is a slimmed down fork of the
|
52
|
+
postgres-pr driver designed specifically for use by Sequel.
|
53
|
+
|
54
|
+
* Model code that explicitly does not swallow connection errors
|
55
|
+
will also now not swallow disconnect errors. This can fix issues
|
56
|
+
where model classes are being loaded at runtime, and the query to
|
57
|
+
get the columns/schema for the model uses a connection that has
|
58
|
+
been disconnected.
|
59
|
+
|
60
|
+
* Model classes created from aliased expressions and literal
|
61
|
+
strings no longer use the simple_table optimization, as there
|
62
|
+
are cases where doing so is not safe.
|
63
|
+
|
64
|
+
= Backwards Compatibility
|
65
|
+
|
66
|
+
* The change to not swallow disconnect errors when not swallowing
|
67
|
+
connection errors can result in exceptions being raised which
|
68
|
+
weren't raised previously. In most cases, this will alert you
|
69
|
+
to issues in your application that should be fixed, but it
|
70
|
+
potentially it can result in regressions if you were OK with
|
71
|
+
the errors being swallowed. If this does result in regressions
|
72
|
+
in your application, please file an issue and we can probably
|
73
|
+
add a setting controlling this feature.
|
data/doc/testing.rdoc
CHANGED
@@ -113,7 +113,7 @@ The order in which you delete/truncate the tables is important if you are using
|
|
113
113
|
|
114
114
|
= Testing Sequel Itself
|
115
115
|
|
116
|
-
Sequel has multiple separate test suites. All test suites use minitest/spec, with the minitest-hooks
|
116
|
+
Sequel has multiple separate test suites. All test suites use minitest/spec, with the minitest-hooks and minitest-global_expectations extensions. To install the dependencies necessary to test Sequel, run <tt>gem install --development sequel</tt>.
|
117
117
|
|
118
118
|
== rake
|
119
119
|
|
@@ -179,6 +179,12 @@ module Sequel
|
|
179
179
|
true
|
180
180
|
end
|
181
181
|
|
182
|
+
# HSQLDB 2.3.4+ supports MERGE. Older versions also support MERGE, but not all
|
183
|
+
# features that are in Sequel's tests.
|
184
|
+
def supports_merge?
|
185
|
+
db.db_version >= 20304
|
186
|
+
end
|
187
|
+
|
182
188
|
private
|
183
189
|
|
184
190
|
def empty_from_sql
|
@@ -23,16 +23,20 @@ begin
|
|
23
23
|
end
|
24
24
|
rescue LoadError => e
|
25
25
|
begin
|
26
|
-
require 'postgres-pr
|
27
|
-
Sequel::Postgres::USES_PG = false
|
26
|
+
require 'sequel/postgres-pr'
|
28
27
|
rescue LoadError
|
29
|
-
|
28
|
+
begin
|
29
|
+
require 'postgres-pr/postgres-compat'
|
30
|
+
rescue LoadError
|
31
|
+
raise e
|
32
|
+
end
|
30
33
|
end
|
34
|
+
Sequel::Postgres::USES_PG = false
|
31
35
|
end
|
32
36
|
|
33
37
|
module Sequel
|
34
38
|
module Postgres
|
35
|
-
if
|
39
|
+
if USES_PG
|
36
40
|
# Whether the given sequel_pg version integer is supported.
|
37
41
|
def self.sequel_pg_version_supported?(version)
|
38
42
|
version >= 10617
|
@@ -74,8 +78,10 @@ module Sequel
|
|
74
78
|
unless public_method_defined?(:async_exec_params)
|
75
79
|
alias async_exec_params async_exec
|
76
80
|
end
|
77
|
-
|
78
|
-
#
|
81
|
+
elsif !const_defined?(:CONNECTION_OK)
|
82
|
+
# Handle old postgres-pr
|
83
|
+
# sequel-postgres-pr already implements this API
|
84
|
+
|
79
85
|
CONNECTION_OK = -1
|
80
86
|
|
81
87
|
# Escape bytea values. Uses historical format instead of hex
|
@@ -338,6 +338,11 @@ module Sequel
|
|
338
338
|
true
|
339
339
|
end
|
340
340
|
|
341
|
+
# DB2 supports MERGE
|
342
|
+
def supports_merge?
|
343
|
+
true
|
344
|
+
end
|
345
|
+
|
341
346
|
# DB2 does not support multiple columns in IN.
|
342
347
|
def supports_multiple_column_in?
|
343
348
|
false
|
@@ -360,6 +365,29 @@ module Sequel
|
|
360
365
|
|
361
366
|
private
|
362
367
|
|
368
|
+
# Normalize conditions for MERGE WHEN.
|
369
|
+
def _merge_when_conditions_sql(sql, data)
|
370
|
+
if data.has_key?(:conditions)
|
371
|
+
sql << " AND "
|
372
|
+
literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
|
377
|
+
# type error.
|
378
|
+
def _normalize_merge_when_conditions(conditions)
|
379
|
+
case conditions
|
380
|
+
when nil, false
|
381
|
+
{1=>0}
|
382
|
+
when true
|
383
|
+
{1=>1}
|
384
|
+
when Sequel::SQL::DelayedEvaluation
|
385
|
+
Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
|
386
|
+
else
|
387
|
+
conditions
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
363
391
|
def empty_from_sql
|
364
392
|
' FROM "SYSIBM"."SYSDUMMY1"'
|
365
393
|
end
|
@@ -734,6 +734,11 @@ module Sequel
|
|
734
734
|
false
|
735
735
|
end
|
736
736
|
|
737
|
+
# MSSQL 2008+ supports MERGE
|
738
|
+
def supports_merge?
|
739
|
+
is_2008_or_later?
|
740
|
+
end
|
741
|
+
|
737
742
|
# MSSQL 2005+ supports modifying joined datasets
|
738
743
|
def supports_modifying_joins?
|
739
744
|
is_2005_or_later?
|
@@ -824,6 +829,35 @@ module Sequel
|
|
824
829
|
|
825
830
|
private
|
826
831
|
|
832
|
+
# Normalize conditions for MERGE WHEN.
|
833
|
+
def _merge_when_conditions_sql(sql, data)
|
834
|
+
if data.has_key?(:conditions)
|
835
|
+
sql << " AND "
|
836
|
+
literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
|
837
|
+
end
|
838
|
+
end
|
839
|
+
|
840
|
+
# Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
|
841
|
+
# type error.
|
842
|
+
def _normalize_merge_when_conditions(conditions)
|
843
|
+
case conditions
|
844
|
+
when nil, false
|
845
|
+
{1=>0}
|
846
|
+
when true
|
847
|
+
{1=>1}
|
848
|
+
when Sequel::SQL::DelayedEvaluation
|
849
|
+
Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
|
850
|
+
else
|
851
|
+
conditions
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
# MSSQL requires a semicolon at the end of MERGE.
|
856
|
+
def _merge_when_sql(sql)
|
857
|
+
super
|
858
|
+
sql << ';'
|
859
|
+
end
|
860
|
+
|
827
861
|
# MSSQL does not allow ordering in sub-clauses unless TOP (limit) is specified
|
828
862
|
def aggregate_dataset
|
829
863
|
(options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
|
@@ -333,6 +333,12 @@ module Sequel
|
|
333
333
|
sqls << "SET sql_mode = '#{sql_mode}'"
|
334
334
|
end
|
335
335
|
|
336
|
+
# Disable the use of split_materialized in the optimizer. This is
|
337
|
+
# needed to pass association tests on MariaDB 10.5+.
|
338
|
+
if opts[:disable_split_materialized] && typecast_value_boolean(opts[:disable_split_materialized])
|
339
|
+
sqls << "SET SESSION optimizer_switch='split_materialized=off'"
|
340
|
+
end
|
341
|
+
|
336
342
|
sqls
|
337
343
|
end
|
338
344
|
|
@@ -356,6 +362,12 @@ module Sequel
|
|
356
362
|
end
|
357
363
|
end
|
358
364
|
|
365
|
+
# Support :on_update_current_timestamp option.
|
366
|
+
def column_definition_default_sql(sql, column)
|
367
|
+
super
|
368
|
+
sql << " ON UPDATE CURRENT_TIMESTAMP" if column[:on_update_current_timestamp]
|
369
|
+
end
|
370
|
+
|
359
371
|
# Add generation clause SQL fragment to column creation SQL.
|
360
372
|
def column_definition_generated_sql(sql, column)
|
361
373
|
if (generated_expression = column[:generated_always_as])
|
@@ -478,6 +478,11 @@ module Sequel
|
|
478
478
|
false
|
479
479
|
end
|
480
480
|
|
481
|
+
# Oracle supports MERGE
|
482
|
+
def supports_merge?
|
483
|
+
true
|
484
|
+
end
|
485
|
+
|
481
486
|
# Oracle supports NOWAIT.
|
482
487
|
def supports_nowait?
|
483
488
|
true
|
@@ -525,6 +530,70 @@ module Sequel
|
|
525
530
|
|
526
531
|
private
|
527
532
|
|
533
|
+
# Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
|
534
|
+
# type error.
|
535
|
+
def _normalize_merge_when_conditions(conditions)
|
536
|
+
case conditions
|
537
|
+
when nil, false
|
538
|
+
{1=>0}
|
539
|
+
when true
|
540
|
+
{1=>1}
|
541
|
+
when Sequel::SQL::DelayedEvaluation
|
542
|
+
Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
|
543
|
+
else
|
544
|
+
conditions
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
# Handle Oracle's non standard MERGE syntax
|
549
|
+
def _merge_when_sql(sql)
|
550
|
+
raise Error, "no WHEN [NOT] MATCHED clauses provided for MERGE" unless merge_when = @opts[:merge_when]
|
551
|
+
insert = update = delete = nil
|
552
|
+
types = merge_when.map{|d| d[:type]}
|
553
|
+
raise Error, "Oracle does not support multiple INSERT, UPDATE, or DELETE clauses in MERGE" if types != types.uniq
|
554
|
+
|
555
|
+
merge_when.each do |data|
|
556
|
+
case data[:type]
|
557
|
+
when :insert
|
558
|
+
insert = data
|
559
|
+
when :update
|
560
|
+
update = data
|
561
|
+
else # when :delete
|
562
|
+
delete = data
|
563
|
+
end
|
564
|
+
end
|
565
|
+
|
566
|
+
if delete
|
567
|
+
raise Error, "Oracle does not support DELETE without UPDATE clause in MERGE" unless update
|
568
|
+
raise Error, "Oracle does not support DELETE without conditions clause in MERGE" unless delete.has_key?(:conditions)
|
569
|
+
end
|
570
|
+
|
571
|
+
if update
|
572
|
+
sql << " WHEN MATCHED"
|
573
|
+
_merge_update_sql(sql, update)
|
574
|
+
_merge_when_conditions_sql(sql, update)
|
575
|
+
|
576
|
+
if delete
|
577
|
+
sql << " DELETE"
|
578
|
+
_merge_when_conditions_sql(sql, delete)
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
if insert
|
583
|
+
sql << " WHEN NOT MATCHED"
|
584
|
+
_merge_insert_sql(sql, insert)
|
585
|
+
_merge_when_conditions_sql(sql, insert)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
# Handle Oracle's non-standard MERGE WHEN condition syntax.
|
590
|
+
def _merge_when_conditions_sql(sql, data)
|
591
|
+
if data.has_key?(:conditions)
|
592
|
+
sql << " WHERE "
|
593
|
+
literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
|
594
|
+
end
|
595
|
+
end
|
596
|
+
|
528
597
|
# Allow preparing prepared statements, since determining the prepared sql to use for
|
529
598
|
# a prepared statement requires calling prepare on that statement.
|
530
599
|
def allow_preparing_prepared_statements?
|