sequel 5.61.0 → 5.62.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +32 -0
- data/README.rdoc +20 -19
- data/doc/advanced_associations.rdoc +13 -13
- data/doc/association_basics.rdoc +21 -15
- data/doc/cheat_sheet.rdoc +3 -3
- data/doc/model_hooks.rdoc +1 -1
- data/doc/object_model.rdoc +8 -8
- data/doc/opening_databases.rdoc +4 -4
- data/doc/postgresql.rdoc +8 -8
- data/doc/querying.rdoc +1 -1
- data/doc/release_notes/5.62.0.txt +132 -0
- data/doc/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 +8 -2
- 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/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 +12 -0
- data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
- data/lib/sequel/extensions/pg_hstore.rb +5 -0
- data/lib/sequel/extensions/pg_inet.rb +9 -10
- data/lib/sequel/extensions/pg_interval.rb +9 -10
- data/lib/sequel/extensions/pg_json.rb +10 -10
- data/lib/sequel/extensions/pg_multirange.rb +5 -10
- data/lib/sequel/extensions/pg_range.rb +5 -10
- data/lib/sequel/extensions/pg_row.rb +18 -13
- data/lib/sequel/model/associations.rb +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 +1 -1
- metadata +10 -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
|