sequel 5.61.0 → 5.62.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/README.rdoc +20 -19
  4. data/doc/advanced_associations.rdoc +13 -13
  5. data/doc/association_basics.rdoc +21 -15
  6. data/doc/cheat_sheet.rdoc +3 -3
  7. data/doc/model_hooks.rdoc +1 -1
  8. data/doc/object_model.rdoc +8 -8
  9. data/doc/opening_databases.rdoc +4 -4
  10. data/doc/postgresql.rdoc +8 -8
  11. data/doc/querying.rdoc +1 -1
  12. data/doc/release_notes/5.62.0.txt +132 -0
  13. data/doc/schema_modification.rdoc +1 -1
  14. data/doc/security.rdoc +9 -9
  15. data/doc/sql.rdoc +13 -13
  16. data/doc/testing.rdoc +13 -11
  17. data/doc/transactions.rdoc +6 -6
  18. data/doc/virtual_rows.rdoc +1 -1
  19. data/lib/sequel/adapters/postgres.rb +4 -0
  20. data/lib/sequel/adapters/shared/access.rb +9 -1
  21. data/lib/sequel/adapters/shared/mssql.rb +9 -5
  22. data/lib/sequel/adapters/shared/mysql.rb +7 -0
  23. data/lib/sequel/adapters/shared/oracle.rb +7 -0
  24. data/lib/sequel/adapters/shared/postgres.rb +275 -152
  25. data/lib/sequel/adapters/shared/sqlanywhere.rb +7 -0
  26. data/lib/sequel/adapters/shared/sqlite.rb +5 -0
  27. data/lib/sequel/connection_pool.rb +42 -28
  28. data/lib/sequel/database/connecting.rb +24 -0
  29. data/lib/sequel/database/misc.rb +8 -2
  30. data/lib/sequel/database/query.rb +37 -0
  31. data/lib/sequel/dataset/actions.rb +31 -11
  32. data/lib/sequel/dataset/features.rb +5 -0
  33. data/lib/sequel/dataset/misc.rb +1 -1
  34. data/lib/sequel/dataset/query.rb +9 -9
  35. data/lib/sequel/dataset/sql.rb +5 -1
  36. data/lib/sequel/extensions/_model_pg_row.rb +0 -12
  37. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  38. data/lib/sequel/extensions/async_thread_pool.rb +11 -11
  39. data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
  40. data/lib/sequel/extensions/constraint_validations.rb +1 -1
  41. data/lib/sequel/extensions/date_arithmetic.rb +1 -1
  42. data/lib/sequel/extensions/migration.rb +1 -1
  43. data/lib/sequel/extensions/named_timezones.rb +17 -5
  44. data/lib/sequel/extensions/pg_array.rb +22 -3
  45. data/lib/sequel/extensions/pg_auto_parameterize.rb +478 -0
  46. data/lib/sequel/extensions/pg_extended_date_support.rb +12 -0
  47. data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
  48. data/lib/sequel/extensions/pg_hstore.rb +5 -0
  49. data/lib/sequel/extensions/pg_inet.rb +9 -10
  50. data/lib/sequel/extensions/pg_interval.rb +9 -10
  51. data/lib/sequel/extensions/pg_json.rb +10 -10
  52. data/lib/sequel/extensions/pg_multirange.rb +5 -10
  53. data/lib/sequel/extensions/pg_range.rb +5 -10
  54. data/lib/sequel/extensions/pg_row.rb +18 -13
  55. data/lib/sequel/model/associations.rb +7 -2
  56. data/lib/sequel/model/base.rb +6 -5
  57. data/lib/sequel/plugins/auto_validations.rb +53 -15
  58. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  59. data/lib/sequel/plugins/composition.rb +2 -2
  60. data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
  61. data/lib/sequel/plugins/dirty.rb +1 -1
  62. data/lib/sequel/plugins/finder.rb +3 -1
  63. data/lib/sequel/plugins/nested_attributes.rb +4 -4
  64. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +1 -1
  65. data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
  66. data/lib/sequel/plugins/sql_comments.rb +1 -1
  67. data/lib/sequel/plugins/validation_helpers.rb +20 -0
  68. data/lib/sequel/version.rb +1 -1
  69. 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], :name=>:albums_artists_pkey
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(:a => 'a') # "(\"a\" = 'a')"
131
- DB.literal(:a => Sequel.lit('a')) # "(\"a\" = a)"
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(:frame=>'SQL Here')}
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(:column => params[:value].to_s) # Safe
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(:id=>params[:id])
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(:id=>params[:id].to_i)
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(:name=>params[:name].to_s)
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(:id=>params[:ids].to_a.map(&:to_i))
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(:id=>params[:id])
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(:partition=>col2, :order=>col3)}
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(:partition=>[c3, c4], :order=>[c5, c6.desc])}
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(:partition=>c2, :order=>:c3, :frame=>:rows)}
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(:partition=>c2, :order=>:c3, :frame=>{:type=>:range, :start=>1, :end=>1})}
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(:partition=>c2, :order=>:c3, :frame=>{:type=>:groups, :start=>[2, :preceding], :end=>[1, :preceding]})}
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(:partition=>c2, :order=>:c3, :frame=>{:type=>:range, :start=>:preceding, :exclude=>:current})}
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, :nulls=>:first) # "column" ASC NULLS FIRST
555
- Sequel.desc(Sequel[:table][:column], :nulls=>:last) # "table"."column" DESC NULLS LAST
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(:name=>'RF') # INSERT INTO albums (name) VALUES ('RF')
633
- ds.update(:name=>'RF') # UPDATE albums SET name = 'RF'
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(:id=>1)
638
+ ds = DB[:albums].where(id: 1)
639
639
  ds.all # SELECT * FROM albums WHERE (id = 1)
640
- ds.insert(:name=>'RF') # INSERT INTO albums (name) VALUES ('RF')
641
- ds.update(:name=>'RF') # UPDATE albums SET name = 'RF' WHERE (id = 1)
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(:rollback=>:always, :auto_savepoint=>true){super}
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(:rollback=>:always, :auto_savepoint=>true){super}
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(:rollback=>:always, :auto_savepoint=>true){super}
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(:rollback=>:always, :auto_savepoint=>true){example.run}
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(:rollback=>:always)
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], :rollback=>:always)
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(:rollback=>:always, :savepoint=>true, :auto_savepoint=>true){super}
74
+ DB.transaction(rollback: :always, savepoint: true, auto_savepoint: true){super}
75
75
  end
76
76
 
77
77
  def around_all
78
- DB.transaction(:rollback=>:always){super}
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)
@@ -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(:savepoint=>true)</tt>
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(:savepoint=>true)
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(:savepoint=>true)
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(:savepoint=>integer)</tt>
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(:savepoint=>2)
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(:savepoint=>3)
159
+ DB.rollback_on_exit(savepoint: 3)
160
160
  end # ROLLBACK TO SAVEPOINT
161
161
  end # ROLLBACK TO SAVEPOINT
162
162
  end # ROLLBACK
@@ -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(:Type=>1, :Flags=>0).select_map(:Name).map(&:to_sym)
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
- statements = multi_insert_sql(columns, values)
804
- ds = naked
805
- @db.transaction(opts.merge(:server=>@opts[:server])) do
806
- statements.map{|st| ds.with_sql(st)}
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