sequel 5.60.1 → 5.62.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 +44 -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.61.0.txt +43 -0
- data/doc/release_notes/5.62.0.txt +132 -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.rb +42 -28
- data/lib/sequel/database/connecting.rb +24 -0
- data/lib/sequel/database/misc.rb +62 -12
- data/lib/sequel/database/query.rb +37 -0
- data/lib/sequel/dataset/actions.rb +31 -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/looser_typecasting.rb +3 -0
- data/lib/sequel/extensions/migration.rb +1 -1
- data/lib/sequel/extensions/named_timezones.rb +17 -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 +27 -24
- 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 +10 -11
- data/lib/sequel/extensions/pg_interval.rb +10 -11
- data/lib/sequel/extensions/pg_json.rb +10 -10
- data/lib/sequel/extensions/pg_json_ops.rb +0 -52
- data/lib/sequel/extensions/pg_multirange.rb +5 -10
- data/lib/sequel/extensions/pg_range.rb +6 -11
- data/lib/sequel/extensions/pg_row.rb +18 -13
- data/lib/sequel/model/associations.rb +7 -2
- 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/sql_comments.rb +1 -1
- data/lib/sequel/plugins/validation_helpers.rb +20 -0
- data/lib/sequel/version.rb +2 -2
- metadata +12 -5
@@ -0,0 +1,132 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* The pg_auto_parameterize extension for automatically using bound
|
4
|
+
variables when using postgres adapter with the pg driver has been
|
5
|
+
added back to Sequel. This extension was originally added in Sequel
|
6
|
+
3.34.0, but was removed in 4.0.0 due to the many corner cases it
|
7
|
+
had. Almost all of the corner cases have now been fixed, and
|
8
|
+
the extension is now recommended for production use. Compared
|
9
|
+
to the original version in Sequel 3, the reintroduced version
|
10
|
+
of the extension includes the following changes:
|
11
|
+
|
12
|
+
* Handles integers used in LIMIT/ORDER
|
13
|
+
* Respects explicit CASTs
|
14
|
+
* Tries to convert column IN (int, ...) into column = ANY($) with an
|
15
|
+
array parameter
|
16
|
+
* Uses the same parameter for the same object used more than once in
|
17
|
+
a query
|
18
|
+
* Uses parameters when inserting multiple rows via Dataset#import
|
19
|
+
* Supports automatically parameterizing all of the
|
20
|
+
PostgreSQL-specific types that Sequel ships support for in pg_*
|
21
|
+
extensions (though some values of those types may not support
|
22
|
+
automatic parameterization).
|
23
|
+
* Supports skipping auto parameterization for specific values.
|
24
|
+
|
25
|
+
Automatic parameterization is generally slower than Sequel's default
|
26
|
+
behavior, since some optimizations Sequel uses by default do not
|
27
|
+
currently support automatic parameterization.
|
28
|
+
|
29
|
+
Applications may need changes to work correctly with the
|
30
|
+
pg_auto_parameterize extension, such as the addition of explicit
|
31
|
+
casts. Please read the extension documentation for more details.
|
32
|
+
|
33
|
+
* Integer column schema entries now include :min_value and :max_value
|
34
|
+
entries on most databases, indicating the minimum and maximum values
|
35
|
+
supported for the column.
|
36
|
+
|
37
|
+
The validation_helpers plugin now has validates_max_value and
|
38
|
+
validates_min_value for testing the column value is not greater
|
39
|
+
than the given maximum value and not less than the given minimum
|
40
|
+
value, respectively.
|
41
|
+
|
42
|
+
The auto_validations plugin now automatically uses the :min_value
|
43
|
+
and :max_value column schema entries with the new validation_helpers
|
44
|
+
methods to validate that the column values for integer columns are
|
45
|
+
in the allowed range.
|
46
|
+
|
47
|
+
* A primary_key_lookup_check_values plugin has been added for
|
48
|
+
automatically typecasting and checking the primary key values are
|
49
|
+
in the allowed range (given by :min_value and :max_value column
|
50
|
+
schema entries) during lookup. If typecasting fails or the value
|
51
|
+
is outside the allowed range, the primary key lookup will return
|
52
|
+
nil without issuing a query (or will raise a NoMatchingRow error
|
53
|
+
if using with_pk!).
|
54
|
+
|
55
|
+
Note that this can change behavior in some cases if you are
|
56
|
+
passing filter conditions during lookup instead of passing primary
|
57
|
+
key values. The plugin tries to support most common filter
|
58
|
+
conditions, but there are still cases that will break.
|
59
|
+
|
60
|
+
* Sequel now supports shard-specific :after_connect and :connect_sqls
|
61
|
+
Database options, allowing you to customize behavior for specific
|
62
|
+
shards:
|
63
|
+
|
64
|
+
DB = Sequel.connect('url', servers: {
|
65
|
+
:shard1 => {host: '...', after_connect: proc{|conn|}},
|
66
|
+
:shard2 => {host: '...', connect_sqls: ['...']},
|
67
|
+
})
|
68
|
+
|
69
|
+
Note that these shard-specific options will not be respected if you
|
70
|
+
are calling after_connect= or connect_sqls= on the Database's
|
71
|
+
connection pool.
|
72
|
+
|
73
|
+
= Other Improvements
|
74
|
+
|
75
|
+
* A Sequel::Postgres::IntegerOutsideBigintRange exception will now be
|
76
|
+
raised if trying to literalize an integer outside PostgreSQL bigint
|
77
|
+
range, to avoid PostgreSQL treating the integer as a numeric type
|
78
|
+
and not respecting indexes on the related column.
|
79
|
+
|
80
|
+
A pg_extended_integer_support extension has been added for
|
81
|
+
customizing the behavior when literalizing an integer outside
|
82
|
+
PostgreSQL bigint range, either quoting it or getting the
|
83
|
+
historical behavior of using it directly in the query.
|
84
|
+
|
85
|
+
* Dataset#import and #multi_insert no longer use transactions when
|
86
|
+
they only run a single query.
|
87
|
+
|
88
|
+
* Fractional seconds in timestamps are now respected in the
|
89
|
+
named_timezones extension.
|
90
|
+
|
91
|
+
* Using hstore[] types as bound variables now works on PostgreSQL.
|
92
|
+
|
93
|
+
* Using BC dates and timestamps in bound variables now works on
|
94
|
+
PostgreSQL.
|
95
|
+
|
96
|
+
* A corner case has been fixed in eager loading where the window
|
97
|
+
function eager limit strategy would be used without removing the
|
98
|
+
row_number entries from the result.
|
99
|
+
|
100
|
+
* The shared postgres adapter now caches reflection datasets, speeding
|
101
|
+
up Database#indexes and similar methods.
|
102
|
+
|
103
|
+
* The mock postgres adapter now assumes PostgreSQL 15 instead of
|
104
|
+
PostgreSQL 14 by default.
|
105
|
+
|
106
|
+
= Backwards Compatibility
|
107
|
+
|
108
|
+
* If you are using Ruby integers outside PostgreSQL bigint range when
|
109
|
+
dealing with PostgreSQL numeric column values, this version may
|
110
|
+
not be compatible. It is recommended you explicitly convert the
|
111
|
+
Ruby integers to BigDecimal objects if you are using them for
|
112
|
+
numeric column values. You can also use the
|
113
|
+
pg_extended_integer_support extension introduced in this version.
|
114
|
+
|
115
|
+
= Workaround for Older Versions
|
116
|
+
|
117
|
+
* If you cannot upgrade to Sequel 5.62.0, but still want to avoid the
|
118
|
+
problems that come from using literal large integers on PostgreSQL,
|
119
|
+
you can use the following code, where DB is your Sequel::Database
|
120
|
+
object:
|
121
|
+
|
122
|
+
DB.extend_datasets do
|
123
|
+
def literal_integer(v)
|
124
|
+
if v > 9223372036854775807 || v < -9223372036854775808
|
125
|
+
raise Sequel::InvalidValue, "PostgreSQL int too large: #{v}"
|
126
|
+
end
|
127
|
+
super
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
This workaround should work all the way back to Sequel 3.29.0,
|
132
|
+
released in November 2011.
|
@@ -377,7 +377,7 @@ Sequel will not add a column, but will add a composite primary key constraint:
|
|
377
377
|
It is possible to specify a name for the primary key constraint: via the :name option:
|
378
378
|
|
379
379
|
alter_table(:albums_artists) do
|
380
|
-
add_primary_key [:album_id, :artist_id], :
|
380
|
+
add_primary_key [:album_id, :artist_id], name: :albums_artists_pkey
|
381
381
|
end
|
382
382
|
|
383
383
|
If you just want to take an existing single column and make it a primary key, call
|
data/doc/security.rdoc
CHANGED
@@ -127,8 +127,8 @@ a ruby string as raw SQL. For example:
|
|
127
127
|
DB.literal(Date.today) # "'2013-03-22'"
|
128
128
|
DB.literal('a') # "'a'"
|
129
129
|
DB.literal(Sequel.lit('a')) # "a"
|
130
|
-
DB.literal(:
|
131
|
-
DB.literal(:
|
130
|
+
DB.literal(a: 'a') # "(\"a\" = 'a')"
|
131
|
+
DB.literal(a: Sequel.lit('a')) # "(\"a\" = a)"
|
132
132
|
|
133
133
|
==== SQL Filter Fragments
|
134
134
|
|
@@ -178,7 +178,7 @@ user input for function names.
|
|
178
178
|
For backwards compatibility, Sequel supports regular strings in the
|
179
179
|
window function :frame option, which will be treated as a literal string:
|
180
180
|
|
181
|
-
DB[:table].select{fun(arg).over(:
|
181
|
+
DB[:table].select{fun(arg).over(frame: 'SQL Here')}
|
182
182
|
|
183
183
|
You should make sure the frame argument is not derived from user input,
|
184
184
|
or switch to using a hash as the :frame option value.
|
@@ -237,7 +237,7 @@ or:
|
|
237
237
|
|
238
238
|
Instead, you should do:
|
239
239
|
|
240
|
-
DB[:table].update(:
|
240
|
+
DB[:table].update(column: params[:value].to_s) # Safe
|
241
241
|
|
242
242
|
Because using the auto_literal_strings extension makes SQL injection
|
243
243
|
so much eaiser, it is recommended to not use it, and instead
|
@@ -402,29 +402,29 @@ This issue isn't necessarily specific to Sequel, but it is a good general practi
|
|
402
402
|
If you are using values derived from user input, it is best to be explicit about
|
403
403
|
their type. For example:
|
404
404
|
|
405
|
-
Album.where(:
|
405
|
+
Album.where(id: params[:id])
|
406
406
|
|
407
407
|
is probably a bad idea. Assuming you are using a web framework, <tt>params[:id]</tt> could
|
408
408
|
be a string, an array, a hash, nil, or potentially something else.
|
409
409
|
|
410
410
|
Assuming that +id+ is an integer field, you probably want to do:
|
411
411
|
|
412
|
-
Album.where(:
|
412
|
+
Album.where(id: params[:id].to_i)
|
413
413
|
|
414
414
|
If you are looking something up by name, you should try to enforce the value to be
|
415
415
|
a string:
|
416
416
|
|
417
|
-
Album.where(:
|
417
|
+
Album.where(name: params[:name].to_s)
|
418
418
|
|
419
419
|
If you are trying to use an IN clause with a list of id values based on input provided
|
420
420
|
on a web form:
|
421
421
|
|
422
|
-
Album.where(:
|
422
|
+
Album.where(id: params[:ids].to_a.map(&:to_i))
|
423
423
|
|
424
424
|
Basically, be as explicit as possible. While there aren't any known security issues
|
425
425
|
in Sequel when you do:
|
426
426
|
|
427
|
-
Album.where(:
|
427
|
+
Album.where(id: params[:id])
|
428
428
|
|
429
429
|
It allows the attacker to choose to do any of the following queries:
|
430
430
|
|
data/doc/sql.rdoc
CHANGED
@@ -223,22 +223,22 @@ If the database supports window functions, Sequel can handle them by calling the
|
|
223
223
|
DB[:albums].select{count.function.*.over}
|
224
224
|
# SELECT count(*) OVER () FROM albums
|
225
225
|
|
226
|
-
DB[:albums].select{function(:col1).over(:
|
226
|
+
DB[:albums].select{function(:col1).over(partition: col2, order: col3)}
|
227
227
|
# SELECT function(col1) OVER (PARTITION BY col2 ORDER BY col3) FROM albums
|
228
228
|
|
229
|
-
DB[:albums].select{function(c1, c2).over(:
|
229
|
+
DB[:albums].select{function(c1, c2).over(partition: [c3, c4], order: [c5, c6.desc])}
|
230
230
|
# SELECT function(c1, c2) OVER (PARTITION BY c3, c4 ORDER BY c5, c6 DESC) FROM albums
|
231
231
|
|
232
|
-
DB[:albums].select{function(c1).over(:
|
232
|
+
DB[:albums].select{function(c1).over(partition: c2, order: :c3, frame: :rows)}
|
233
233
|
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM albums
|
234
234
|
|
235
|
-
DB[:albums].select{function(c1).over(:
|
235
|
+
DB[:albums].select{function(c1).over(partition: c2, order: :c3, frame: {type: :range, start: 1, end: 1})}
|
236
236
|
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING) FROM albums
|
237
237
|
|
238
|
-
DB[:albums].select{function(c1).over(:
|
238
|
+
DB[:albums].select{function(c1).over(partition: c2, order: :c3, frame: {type: :groups, start: [2, :preceding], end: [1, :preceding]})}
|
239
239
|
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 GROUPS BETWEEN 2 PRECEDING AND 1 PRECEDING) FROM albums
|
240
240
|
|
241
|
-
DB[:albums].select{function(c1).over(:
|
241
|
+
DB[:albums].select{function(c1).over(partition: c2, order: :c3, frame: {type: :range, start: :preceding, exclude: :current})}
|
242
242
|
# SELECT function(c1) OVER (PARTITION BY c2 ORDER BY c3 RANGE UNBOUNDED PRECEDING EXCLUDE CURRENT ROW) FROM albums
|
243
243
|
|
244
244
|
=== Schema Qualified Functions
|
@@ -551,8 +551,8 @@ You can also use the <tt>Sequel.asc</tt> and <tt>Sequel.desc</tt> methods:
|
|
551
551
|
|
552
552
|
On some databases, you can specify null ordering:
|
553
553
|
|
554
|
-
Sequel.asc(:column, :
|
555
|
-
Sequel.desc(Sequel[:table][:column], :
|
554
|
+
Sequel.asc(:column, nulls: :first) # "column" ASC NULLS FIRST
|
555
|
+
Sequel.desc(Sequel[:table][:column], nulls: :last) # "table"."column" DESC NULLS LAST
|
556
556
|
|
557
557
|
=== All Columns (.*)
|
558
558
|
|
@@ -629,16 +629,16 @@ Also note that while the SELECT clause is displayed when you look at a dataset,
|
|
629
629
|
|
630
630
|
ds = DB[:albums]
|
631
631
|
ds.all # SELECT * FROM albums
|
632
|
-
ds.insert(:
|
633
|
-
ds.update(:
|
632
|
+
ds.insert(name: 'RF') # INSERT INTO albums (name) VALUES ('RF')
|
633
|
+
ds.update(name: 'RF') # UPDATE albums SET name = 'RF'
|
634
634
|
ds.delete # DELETE FROM albums
|
635
635
|
|
636
636
|
In general, the +insert+, +update+, and +delete+ methods use the appropriate clauses you defined on the dataset:
|
637
637
|
|
638
|
-
ds = DB[:albums].where(:
|
638
|
+
ds = DB[:albums].where(id: 1)
|
639
639
|
ds.all # SELECT * FROM albums WHERE (id = 1)
|
640
|
-
ds.insert(:
|
641
|
-
ds.update(:
|
640
|
+
ds.insert(name: 'RF') # INSERT INTO albums (name) VALUES ('RF')
|
641
|
+
ds.update(name: 'RF') # UPDATE albums SET name = 'RF' WHERE (id = 1)
|
642
642
|
ds.delete # DELETE FROM albums WHERE (id = 1)
|
643
643
|
|
644
644
|
Note how +update+ and +delete+ used the +where+ argument, but +insert+ did not, because INSERT doesn't use a WHERE clause.
|
data/doc/testing.rdoc
CHANGED
@@ -15,7 +15,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
15
15
|
|
16
16
|
class Minitest::HooksSpec
|
17
17
|
def around
|
18
|
-
DB.transaction(:
|
18
|
+
DB.transaction(rollback: :always, auto_savepoint: true){super}
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -24,7 +24,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
24
24
|
|
25
25
|
class Minitest::Spec
|
26
26
|
def run(*args, &block)
|
27
|
-
DB.transaction(:
|
27
|
+
DB.transaction(rollback: :always, auto_savepoint: true){super}
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -34,7 +34,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
34
34
|
# Use this class as the base class for your tests
|
35
35
|
class SequelTestCase < Minitest::Test
|
36
36
|
def run(*args, &block)
|
37
|
-
DB.transaction(:
|
37
|
+
DB.transaction(rollback: :always, auto_savepoint: true){super}
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -43,7 +43,7 @@ These run each test in its own transaction, the recommended way to test.
|
|
43
43
|
|
44
44
|
RSpec.configure do |c|
|
45
45
|
c.around(:each) do |example|
|
46
|
-
DB.transaction(:
|
46
|
+
DB.transaction(rollback: :always, auto_savepoint: true){example.run}
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -51,11 +51,11 @@ These run each test in its own transaction, the recommended way to test.
|
|
51
51
|
|
52
52
|
You can use the Sequel.transaction method to run a transaction on multiple databases, rolling all of them back. Instead of:
|
53
53
|
|
54
|
-
DB.transaction(:
|
54
|
+
DB.transaction(rollback: :always)
|
55
55
|
|
56
56
|
Use Sequel.transaction with an array of databases:
|
57
57
|
|
58
|
-
Sequel.transaction([DB1, DB2, DB3], :
|
58
|
+
Sequel.transaction([DB1, DB2, DB3], rollback: :always)
|
59
59
|
|
60
60
|
== Transactional testing with savepoints
|
61
61
|
|
@@ -71,11 +71,11 @@ Example:
|
|
71
71
|
require 'minitest/hooks/default'
|
72
72
|
class Minitest::HooksSpec
|
73
73
|
def around
|
74
|
-
DB.transaction(:
|
74
|
+
DB.transaction(rollback: :always, savepoint: true, auto_savepoint: true){super}
|
75
75
|
end
|
76
76
|
|
77
77
|
def around_all
|
78
|
-
DB.transaction(:
|
78
|
+
DB.transaction(rollback: :always){super}
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -161,22 +161,24 @@ The SEQUEL_INTEGRATION_URL environment variable specifies the Database connectio
|
|
161
161
|
|
162
162
|
SEQUEL_ASYNC_THREAD_POOL :: Use the async_thread_pool extension when running the specs
|
163
163
|
SEQUEL_ASYNC_THREAD_POOL_PREEMPT :: Use the async_thread_pool extension when running the specs, with the :preempt_async_thread option
|
164
|
+
SEQUEL_CHECK_PENDING :: Try running all specs (note, can cause lockups for some adapters), and raise errors for skipped specs that don't fail
|
164
165
|
SEQUEL_COLUMNS_INTROSPECTION :: Use the columns_introspection extension when running the specs
|
166
|
+
SEQUEL_CONCURRENT_EAGER_LOADING :: Use the async_thread_pool extension and concurrent_eager_loading plugin when running the specs
|
165
167
|
SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when running the specs
|
166
168
|
SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
|
167
|
-
SEQUEL_CONCURRENT_EAGER_LOADING :: Use the async_thread_pool extension and concurrent_eager_loading plugin when running the specs
|
168
169
|
SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
|
169
|
-
SEQUEL_INDEX_CACHING :: Use the index_caching extension when running the specs
|
170
170
|
SEQUEL_FIBER_CONCURRENCY :: Use the fiber_concurrency extension when running the adapter and integration specs
|
171
171
|
SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
|
172
172
|
SEQUEL_IDENTIFIER_MANGLING :: Use the identifier_mangling extension when running the specs
|
173
|
+
SEQUEL_INDEX_CACHING :: Use the index_caching extension when running the specs
|
173
174
|
SEQUEL_INTEGER64 :: Use the integer64 extension when running the adapter or integration specs
|
174
175
|
SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements plugin when running the specs
|
175
176
|
SEQUEL_MODEL_THROW_FAILURES :: Use the throw_failures plugin when running the specs
|
176
177
|
SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
|
177
|
-
SEQUEL_CHECK_PENDING :: Try running all specs (note, can cause lockups for some adapters), and raise errors for skipped specs that don't fail
|
178
178
|
SEQUEL_NO_PENDING :: Don't skip any specs, try running all specs (note, can cause lockups for some adapters)
|
179
|
+
SEQUEL_PG_AUTO_PARAMETERIZE :: Use the pg_auto_parameterize extension when running the postgres specs
|
179
180
|
SEQUEL_PG_TIMESTAMPTZ :: Use the pg_timestamptz extension when running the postgres specs
|
181
|
+
SEQUEL_PRIMARY_KEY_LOOKUP_CHECK_VALUES :: Use the primary_key_lookup_check_values extension when running the adapter or integration specs
|
180
182
|
SEQUEL_QUERY_PER_ASSOCIATION_DB_0_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
|
181
183
|
SEQUEL_QUERY_PER_ASSOCIATION_DB_1_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
|
182
184
|
SEQUEL_QUERY_PER_ASSOCIATION_DB_2_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
|
data/doc/transactions.rdoc
CHANGED
@@ -127,28 +127,28 @@ Other exceptions, unless rescued inside the outer transaction block, will rollba
|
|
127
127
|
end # ROLLBACK
|
128
128
|
# ArgumentError raised
|
129
129
|
|
130
|
-
If you want the current savepoint to be rolled back when the savepoint block exits instead of being committed (even if an exception is not raised), use <tt>Database#rollback_on_exit(:
|
130
|
+
If you want the current savepoint to be rolled back when the savepoint block exits instead of being committed (even if an exception is not raised), use <tt>Database#rollback_on_exit(savepoint: true)</tt>
|
131
131
|
|
132
132
|
DB.transaction do # BEGIN
|
133
133
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
134
|
-
DB.rollback_on_exit(:
|
134
|
+
DB.rollback_on_exit(savepoint: true)
|
135
135
|
end # ROLLBACK TO SAVEPOINT
|
136
136
|
end # COMMIT
|
137
137
|
|
138
138
|
DB.transaction do # BEGIN
|
139
139
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
140
140
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
141
|
-
DB.rollback_on_exit(:
|
141
|
+
DB.rollback_on_exit(savepoint: true)
|
142
142
|
end # ROLLBACK TO SAVEPOINT
|
143
143
|
end # RELEASE SAVEPOINT
|
144
144
|
end # COMMIT
|
145
145
|
|
146
|
-
If you want the current savepoint and potentially enclosing savepoints to be rolled back when the savepoint blocks exit (even if an exception is not raised), use <tt>Database#rollback_on_exit(:
|
146
|
+
If you want the current savepoint and potentially enclosing savepoints to be rolled back when the savepoint blocks exit (even if an exception is not raised), use <tt>Database#rollback_on_exit(savepoint: integer)</tt>
|
147
147
|
|
148
148
|
DB.transaction do # BEGIN
|
149
149
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
150
150
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
151
|
-
DB.rollback_on_exit(:
|
151
|
+
DB.rollback_on_exit(savepoint: 2)
|
152
152
|
end # ROLLBACK TO SAVEPOINT
|
153
153
|
end # ROLLBACK TO SAVEPOINT
|
154
154
|
end # COMMIT
|
@@ -156,7 +156,7 @@ If you want the current savepoint and potentially enclosing savepoints to be rol
|
|
156
156
|
DB.transaction do # BEGIN
|
157
157
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
158
158
|
DB.transaction(savepoint: true) do # SAVEPOINT
|
159
|
-
DB.rollback_on_exit(:
|
159
|
+
DB.rollback_on_exit(savepoint: 3)
|
160
160
|
end # ROLLBACK TO SAVEPOINT
|
161
161
|
end # ROLLBACK TO SAVEPOINT
|
162
162
|
end # ROLLBACK
|
data/doc/virtual_rows.rdoc
CHANGED
@@ -23,7 +23,7 @@ With virtual rows, you can use the less verbose:
|
|
23
23
|
Virtual row blocks behave differently depending on whether the block accepts
|
24
24
|
an argument. If the block accepts an argument, it is called with an instance
|
25
25
|
of Sequel::SQL::VirtualRow. If it does not accept an argument, it is
|
26
|
-
evaluated in the context of an instance of Sequel::SQL::VirtualRow.
|
26
|
+
evaluated in the <em> context of an instance </em> of Sequel::SQL::VirtualRow.
|
27
27
|
|
28
28
|
ds = DB[:items]
|
29
29
|
# Regular block
|
@@ -185,8 +185,12 @@ module Sequel
|
|
185
185
|
case arg
|
186
186
|
when Sequel::SQL::Blob
|
187
187
|
{:value=>arg, :type=>17, :format=>1}
|
188
|
+
# :nocov:
|
189
|
+
# Not covered by tests as tests use pg_extended_date_support
|
190
|
+
# extension, which has basically the same code.
|
188
191
|
when DateTime, Time
|
189
192
|
literal(arg)
|
193
|
+
# :nocov:
|
190
194
|
else
|
191
195
|
arg
|
192
196
|
end
|
@@ -17,7 +17,7 @@ module Sequel
|
|
17
17
|
|
18
18
|
# Doesn't work, due to security restrictions on MSysObjects
|
19
19
|
#def tables
|
20
|
-
# from(:MSysObjects).where(:
|
20
|
+
# from(:MSysObjects).where(Type: 1, Flags: 0).select_map(:Name).map(&:to_sym)
|
21
21
|
#end
|
22
22
|
|
23
23
|
# Access doesn't support renaming tables from an SQL query,
|
@@ -57,6 +57,14 @@ module Sequel
|
|
57
57
|
DATABASE_ERROR_REGEXPS
|
58
58
|
end
|
59
59
|
|
60
|
+
# Access's Byte type will accept much larger values,
|
61
|
+
# even though it only stores 0-255. Do not set min/max
|
62
|
+
# values for the Byte type.
|
63
|
+
def column_schema_integer_min_max_values(db_type)
|
64
|
+
return if /byte/i =~ db_type
|
65
|
+
super
|
66
|
+
end
|
67
|
+
|
60
68
|
def drop_index_sql(table, op)
|
61
69
|
"DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))} ON #{quote_schema_table(table)}"
|
62
70
|
end
|
@@ -325,6 +325,11 @@ module Sequel
|
|
325
325
|
false
|
326
326
|
end
|
327
327
|
|
328
|
+
# MSSQL tinyint types are unsigned.
|
329
|
+
def column_schema_tinyint_type_is_unsigned?
|
330
|
+
true
|
331
|
+
end
|
332
|
+
|
328
333
|
# Handle MSSQL specific default format.
|
329
334
|
def column_schema_normalize_default(default, type)
|
330
335
|
if m = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/.match(default)
|
@@ -800,11 +805,10 @@ module Sequel
|
|
800
805
|
if opts[:return] == :primary_key && !@opts[:output]
|
801
806
|
output(nil, [SQL::QualifiedIdentifier.new(:inserted, first_primary_key)])._import(columns, values, opts)
|
802
807
|
elsif @opts[:output]
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
end.first.map{|v| v.length == 1 ? v.values.first : v}
|
808
|
+
# no transaction: our multi_insert_sql_strategy should guarantee
|
809
|
+
# that there's only ever a single statement.
|
810
|
+
sql = multi_insert_sql(columns, values)[0]
|
811
|
+
naked.with_sql(sql).map{|v| v.length == 1 ? v.values.first : v}
|
808
812
|
else
|
809
813
|
super
|
810
814
|
end
|
@@ -550,6 +550,13 @@ module Sequel
|
|
550
550
|
end
|
551
551
|
end
|
552
552
|
|
553
|
+
# Return nil if CHECK constraints are not supported, because
|
554
|
+
# versions that don't support check constraints don't raise
|
555
|
+
# errors for values outside of range.
|
556
|
+
def column_schema_integer_min_max_values(db_type)
|
557
|
+
super if supports_check_constraints?
|
558
|
+
end
|
559
|
+
|
553
560
|
# Split DROP INDEX ops on MySQL 5.6+, as dropping them in the same
|
554
561
|
# statement as dropping a related foreign key causes an error.
|
555
562
|
def split_alter_table_op?(op)
|
@@ -178,6 +178,13 @@ module Sequel
|
|
178
178
|
''
|
179
179
|
end
|
180
180
|
|
181
|
+
# Do not support min/max integer values on Oracle, since
|
182
|
+
# Oracle uses a number type, and integer just adds a
|
183
|
+
# constaint on the number type.
|
184
|
+
def column_schema_integer_min_max_values(db_type)
|
185
|
+
nil
|
186
|
+
end
|
187
|
+
|
181
188
|
def create_sequence_sql(name, opts=OPTS)
|
182
189
|
"CREATE SEQUENCE #{quote_identifier(name)} start with #{opts [:start_with]||1} increment by #{opts[:increment_by]||1} nomaxvalue"
|
183
190
|
end
|