sequel 5.58.0 → 5.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +288 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +24 -23
  5. data/bin/sequel +11 -3
  6. data/doc/advanced_associations.rdoc +16 -14
  7. data/doc/association_basics.rdoc +53 -17
  8. data/doc/cheat_sheet.rdoc +3 -3
  9. data/doc/mass_assignment.rdoc +1 -1
  10. data/doc/migration.rdoc +15 -0
  11. data/doc/model_hooks.rdoc +1 -1
  12. data/doc/object_model.rdoc +8 -8
  13. data/doc/opening_databases.rdoc +20 -12
  14. data/doc/postgresql.rdoc +8 -8
  15. data/doc/querying.rdoc +1 -1
  16. data/doc/release_notes/5.59.0.txt +73 -0
  17. data/doc/release_notes/5.60.0.txt +22 -0
  18. data/doc/release_notes/5.61.0.txt +43 -0
  19. data/doc/release_notes/5.62.0.txt +132 -0
  20. data/doc/release_notes/5.63.0.txt +33 -0
  21. data/doc/release_notes/5.64.0.txt +50 -0
  22. data/doc/release_notes/5.65.0.txt +21 -0
  23. data/doc/release_notes/5.66.0.txt +24 -0
  24. data/doc/release_notes/5.67.0.txt +32 -0
  25. data/doc/release_notes/5.68.0.txt +61 -0
  26. data/doc/release_notes/5.69.0.txt +26 -0
  27. data/doc/release_notes/5.70.0.txt +35 -0
  28. data/doc/release_notes/5.71.0.txt +21 -0
  29. data/doc/release_notes/5.72.0.txt +33 -0
  30. data/doc/release_notes/5.73.0.txt +66 -0
  31. data/doc/release_notes/5.74.0.txt +45 -0
  32. data/doc/release_notes/5.75.0.txt +35 -0
  33. data/doc/release_notes/5.76.0.txt +86 -0
  34. data/doc/release_notes/5.77.0.txt +63 -0
  35. data/doc/release_notes/5.78.0.txt +67 -0
  36. data/doc/schema_modification.rdoc +3 -3
  37. data/doc/security.rdoc +9 -9
  38. data/doc/sharding.rdoc +3 -1
  39. data/doc/sql.rdoc +14 -14
  40. data/doc/testing.rdoc +16 -12
  41. data/doc/transactions.rdoc +6 -6
  42. data/doc/virtual_rows.rdoc +1 -1
  43. data/lib/sequel/adapters/ibmdb.rb +1 -1
  44. data/lib/sequel/adapters/jdbc/h2.rb +3 -0
  45. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -0
  46. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -0
  47. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +15 -0
  48. data/lib/sequel/adapters/jdbc/sqlserver.rb +4 -0
  49. data/lib/sequel/adapters/jdbc.rb +10 -6
  50. data/lib/sequel/adapters/mysql.rb +19 -7
  51. data/lib/sequel/adapters/mysql2.rb +2 -2
  52. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  53. data/lib/sequel/adapters/oracle.rb +1 -0
  54. data/lib/sequel/adapters/postgres.rb +62 -16
  55. data/lib/sequel/adapters/shared/access.rb +9 -1
  56. data/lib/sequel/adapters/shared/db2.rb +12 -0
  57. data/lib/sequel/adapters/shared/mssql.rb +71 -9
  58. data/lib/sequel/adapters/shared/mysql.rb +80 -1
  59. data/lib/sequel/adapters/shared/oracle.rb +17 -7
  60. data/lib/sequel/adapters/shared/postgres.rb +494 -164
  61. data/lib/sequel/adapters/shared/sqlanywhere.rb +18 -5
  62. data/lib/sequel/adapters/shared/sqlite.rb +40 -4
  63. data/lib/sequel/adapters/sqlite.rb +42 -3
  64. data/lib/sequel/adapters/trilogy.rb +117 -0
  65. data/lib/sequel/connection_pool/sharded_threaded.rb +16 -11
  66. data/lib/sequel/connection_pool/sharded_timed_queue.rb +374 -0
  67. data/lib/sequel/connection_pool/threaded.rb +14 -8
  68. data/lib/sequel/connection_pool/timed_queue.rb +270 -0
  69. data/lib/sequel/connection_pool.rb +57 -31
  70. data/lib/sequel/database/connecting.rb +25 -1
  71. data/lib/sequel/database/dataset.rb +16 -6
  72. data/lib/sequel/database/misc.rb +65 -14
  73. data/lib/sequel/database/query.rb +72 -1
  74. data/lib/sequel/database/schema_generator.rb +2 -1
  75. data/lib/sequel/database/schema_methods.rb +13 -3
  76. data/lib/sequel/database/transactions.rb +6 -0
  77. data/lib/sequel/dataset/actions.rb +60 -13
  78. data/lib/sequel/dataset/deprecated_singleton_class_methods.rb +42 -0
  79. data/lib/sequel/dataset/features.rb +15 -1
  80. data/lib/sequel/dataset/misc.rb +12 -2
  81. data/lib/sequel/dataset/placeholder_literalizer.rb +20 -9
  82. data/lib/sequel/dataset/query.rb +62 -37
  83. data/lib/sequel/dataset/sql.rb +58 -36
  84. data/lib/sequel/dataset.rb +4 -0
  85. data/lib/sequel/exceptions.rb +5 -0
  86. data/lib/sequel/extensions/_model_pg_row.rb +0 -12
  87. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  88. data/lib/sequel/extensions/any_not_empty.rb +2 -2
  89. data/lib/sequel/extensions/async_thread_pool.rb +21 -13
  90. data/lib/sequel/extensions/auto_cast_date_and_time.rb +94 -0
  91. data/lib/sequel/extensions/auto_literal_strings.rb +1 -1
  92. data/lib/sequel/extensions/connection_expiration.rb +15 -9
  93. data/lib/sequel/extensions/connection_validator.rb +16 -11
  94. data/lib/sequel/extensions/constraint_validations.rb +1 -1
  95. data/lib/sequel/extensions/date_arithmetic.rb +36 -8
  96. data/lib/sequel/extensions/duplicate_columns_handler.rb +10 -9
  97. data/lib/sequel/extensions/index_caching.rb +5 -1
  98. data/lib/sequel/extensions/is_distinct_from.rb +3 -1
  99. data/lib/sequel/extensions/looser_typecasting.rb +3 -0
  100. data/lib/sequel/extensions/migration.rb +65 -15
  101. data/lib/sequel/extensions/named_timezones.rb +22 -6
  102. data/lib/sequel/extensions/pg_array.rb +33 -4
  103. data/lib/sequel/extensions/pg_auto_parameterize.rb +509 -0
  104. data/lib/sequel/extensions/pg_auto_parameterize_in_array.rb +110 -0
  105. data/lib/sequel/extensions/pg_enum.rb +1 -2
  106. data/lib/sequel/extensions/pg_extended_date_support.rb +38 -27
  107. data/lib/sequel/extensions/pg_extended_integer_support.rb +116 -0
  108. data/lib/sequel/extensions/pg_hstore.rb +5 -0
  109. data/lib/sequel/extensions/pg_inet.rb +10 -11
  110. data/lib/sequel/extensions/pg_interval.rb +10 -11
  111. data/lib/sequel/extensions/pg_json.rb +10 -10
  112. data/lib/sequel/extensions/pg_json_ops.rb +52 -0
  113. data/lib/sequel/extensions/pg_multirange.rb +6 -11
  114. data/lib/sequel/extensions/pg_range.rb +9 -14
  115. data/lib/sequel/extensions/pg_row.rb +20 -19
  116. data/lib/sequel/extensions/pg_timestamptz.rb +27 -3
  117. data/lib/sequel/extensions/round_timestamps.rb +1 -1
  118. data/lib/sequel/extensions/schema_caching.rb +1 -1
  119. data/lib/sequel/extensions/schema_dumper.rb +32 -9
  120. data/lib/sequel/extensions/server_block.rb +2 -1
  121. data/lib/sequel/extensions/set_literalizer.rb +58 -0
  122. data/lib/sequel/extensions/sqlite_json_ops.rb +76 -18
  123. data/lib/sequel/extensions/symbol_aref.rb +2 -0
  124. data/lib/sequel/extensions/transaction_connection_validator.rb +78 -0
  125. data/lib/sequel/model/associations.rb +50 -11
  126. data/lib/sequel/model/base.rb +45 -21
  127. data/lib/sequel/model/dataset_module.rb +3 -0
  128. data/lib/sequel/model/exceptions.rb +15 -3
  129. data/lib/sequel/plugins/auto_validations.rb +53 -15
  130. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  131. data/lib/sequel/plugins/column_encryption.rb +27 -6
  132. data/lib/sequel/plugins/composition.rb +2 -2
  133. data/lib/sequel/plugins/concurrent_eager_loading.rb +4 -4
  134. data/lib/sequel/plugins/constraint_validations.rb +8 -5
  135. data/lib/sequel/plugins/defaults_setter.rb +16 -0
  136. data/lib/sequel/plugins/dirty.rb +1 -1
  137. data/lib/sequel/plugins/finder.rb +4 -2
  138. data/lib/sequel/plugins/list.rb +8 -3
  139. data/lib/sequel/plugins/many_through_many.rb +1 -1
  140. data/lib/sequel/plugins/mssql_optimistic_locking.rb +8 -38
  141. data/lib/sequel/plugins/nested_attributes.rb +4 -4
  142. data/lib/sequel/plugins/optimistic_locking.rb +9 -42
  143. data/lib/sequel/plugins/optimistic_locking_base.rb +55 -0
  144. data/lib/sequel/plugins/paged_operations.rb +181 -0
  145. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +9 -3
  146. data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +109 -0
  147. data/lib/sequel/plugins/prepared_statements.rb +2 -1
  148. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -1
  149. data/lib/sequel/plugins/primary_key_lookup_check_values.rb +154 -0
  150. data/lib/sequel/plugins/rcte_tree.rb +7 -4
  151. data/lib/sequel/plugins/require_valid_schema.rb +67 -0
  152. data/lib/sequel/plugins/single_table_inheritance.rb +8 -0
  153. data/lib/sequel/plugins/sql_comments.rb +5 -5
  154. data/lib/sequel/plugins/static_cache.rb +38 -0
  155. data/lib/sequel/plugins/static_cache_cache.rb +5 -1
  156. data/lib/sequel/plugins/tactical_eager_loading.rb +21 -14
  157. data/lib/sequel/plugins/validate_associated.rb +22 -12
  158. data/lib/sequel/plugins/validation_helpers.rb +29 -2
  159. data/lib/sequel/plugins/validation_helpers_generic_type_messages.rb +73 -0
  160. data/lib/sequel/version.rb +1 -1
  161. metadata +76 -6
@@ -0,0 +1,86 @@
1
+ = New Features
2
+
3
+ * An auto_cast_date_and_time extension has been added, which will
4
+ automatically cast date and time values using SQL standard functions.
5
+ This makes sure the database will treat the value as a date, time,
6
+ or timestamp, instead of treating it as a string or unknown type:
7
+
8
+ DB.get(Date.today).class
9
+ # SELECT '2024-01-01' AS v LIMIT 1
10
+ String
11
+
12
+ DB.extension(:auto_cast_date_and_time)
13
+ DB.get(Date.today).class
14
+ # SELECT DATE '2024-01-01' AS v LIMIT 1
15
+ Date
16
+
17
+ This was already Sequel's default behavior on adapters that required
18
+ it. This extension is usable on PostgreSQL and MySQL. It is not
19
+ usable on SQLite (no date/time types) or Microsoft SQL Server (no
20
+ support for the SQL standard conversion syntax).
21
+
22
+ This extension can break code that currently works. If using it on
23
+ PostgreSQL, it will cast the values to TIMESTAMP, not TIMESTAMP
24
+ WITH TIME ZONE, which can break code that depended on an implicit
25
+ conversion to TIMESTAMP WITH TIME ZONE. The pg_timestamptz
26
+ extension integrates with the the auto_cast_date_and_time extension
27
+ and will implicitly cast Time/DateTime to TIMESTAMP WITH TIME ZONE.
28
+
29
+ * The sqlite adapter now supports a :cached value for the
30
+ :setup_regexp_function Database option, which will cache regexp
31
+ values instead of creating a new regexp per value to compare. This
32
+ is much faster when using a regexp comparison on a large dataset,
33
+ but can result in a memory leak if using dynamic regexps. You can
34
+ also provide a Proc value for the :setup_regexp_function option,
35
+ which will be passed both the regexp source string and the database
36
+ string to compare, and should return whether the database string
37
+ matches the regexp string.
38
+
39
+ * The rcte_tree plugin now supports a :union_all option, which can
40
+ be set to false to use UNION instead of UNION ALL in the recursive
41
+ common table expression.
42
+
43
+ = Other Improvements
44
+
45
+ * Time/DateTime/SQLTime literalization speed has more than doubled
46
+ compared to the previous version. The internal code is also much
47
+ simpler, as the speedup resulted from removing multiple abstraction
48
+ layers that mostly existed for Ruby 1.8 support.
49
+
50
+ * Database#table_exists? on PostgreSQL now handles lock or statement
51
+ timeout errors as evidence the table exists.
52
+
53
+ * The round_timestamps extension now correctly rounds SQLTime values
54
+ on Microsoft SQL Server (the only database Sequel supports where
55
+ time precision is different than timestamp precision).
56
+
57
+ * Fractional times and timestamps are now supported on SQLAnywhere,
58
+ except for time values when using the jdbc adapter due to a
59
+ limitation in the JDBC sqlanywhere driver.
60
+
61
+ * Database#tables and #views on PostgreSQL now supports
62
+ SQL::Identifier values for the :schema option.
63
+
64
+ * The named_timezones extension now works around a bug in DateTime.jd
65
+ on JRuby.
66
+
67
+ = Backwards Compatibility
68
+
69
+ * Time/DateTime/SQLTime literalization internals have changed.
70
+ If you are using an external adapter and the external adapter
71
+ overrides or calls any of the following methods:
72
+
73
+ * requires_sql_standard_datetimes?
74
+ * supports_timestamp_usecs?
75
+ * supports_timestamp_timezones?
76
+ * timestamp_precision
77
+ * sqltime_precision
78
+
79
+ then the adapter may need to be updated to support Sequel 5.76.0.
80
+ Additionally, if the adapter uses %N or %z in
81
+ default_timestamp_format, it may need to be updated. Adapters
82
+ should now just override default_timestamp_format and/or
83
+ default_time_format methods as appropriate for the database.
84
+
85
+ * The Dataset#format_timestamp_offset private method has been
86
+ removed.
@@ -0,0 +1,63 @@
1
+ = New Features
2
+
3
+ * A transaction_connection_validator extension has been added. This
4
+ extension allows for transparently switching to a new connection if
5
+ a disconnect error is raised while trying to start a transaction, as
6
+ long as a connection was not already checked out from the pool
7
+ when the transaction method was called. Transparent reconnection
8
+ is safe in this case, since no user code is retried.
9
+
10
+ This extension can have lower overhead than the
11
+ connection_validator extension if that is configured to check for
12
+ validity more often than the default of one hour. However, it
13
+ only handles cases where transactions are used. It can detect
14
+ disconnects that would not be detected by default with the
15
+ connection_validator extension, since that extension defaults to
16
+ only checking validity if the connection has not been used in the
17
+ last hour.
18
+
19
+ * Sequel now supports a create_table :without_rowid option on SQLite,
20
+ to create a table WITHOUT ROWID, for better performance in some
21
+ cases. Users are encouraged to read the SQLite documentation on
22
+ WITHOUT ROWID before using this option.
23
+
24
+ * The sqlite adapter now supports a :regexp_function_cache option, if
25
+ the :setup_regexp_function option is set to :cached. The
26
+ :regexp_function_cache option should be a Proc (returning a cache
27
+ object to use), or a class. It's possible to use
28
+ ObjectSpace::WeakKeyMap as the value of the option on Ruby 3.3+
29
+ to avoid the memory leaks that are possible when using
30
+ :setup_regexp_function option :cached value with dynamic regexps.
31
+
32
+ * The duplicate_columns_handler extension now supports specifying
33
+ the on_duplicate_columns option as a connection string parameter.
34
+
35
+ = Other Improvements
36
+
37
+ * The list plugin now honors the :top option for the position when
38
+ adding the first item to the list, instead of always using 1.
39
+
40
+ * Regexp matches on SQLite are now faster on Ruby 2.4+, using
41
+ Regexp#match?.
42
+
43
+ * The uniqueness validation in the validation_helpers plugin now
44
+ uses empty? instead of count == 0, for better performance.
45
+
46
+ * On Ruby 3.4+, Sequel uses the timed_queue connection pool instead
47
+ of the threaded connection pool by default. This should make it
48
+ so no existing applications are affected by the default switch.
49
+ This should hopefully allow ample testing of the timed_queue
50
+ connection pool. At some point in the future, if no problems
51
+ are repoted, Sequel will likely switch to using the timed_queue
52
+ connection pool by default on Ruby 3.2+.
53
+
54
+ = Backwards Compatibility
55
+
56
+ * Sequel now warns by default if using eager_graph/association_join
57
+ with an association that uses a block, in the cases where the
58
+ block would be ignored and there are no appropriate graph options
59
+ set. In Sequel 6, this warning will be turned into an exception.
60
+ It is recommended that users use the auto_restrict_eager_graph
61
+ plugin to turn this into an exception now, or use the
62
+ :graph_use_association_block option so that the block is not
63
+ ignored when graphing.
@@ -0,0 +1,67 @@
1
+ = New Features
2
+
3
+ * SQLite 3.45+ jsonb functions are now supported in the sqlite_json_ops
4
+ extension. Similar to the postgres_json_ops extension, there are
5
+ now separate methods for dealing with json and jsonb types:
6
+
7
+ Sequel.sqlite_json_op(:column) # json
8
+ Sequel.sqlite_jsonb_op(:column) # jsonb
9
+
10
+ Some methods that use json_* functions for json ops use jsonb_*
11
+ functions for jsonb ops:
12
+
13
+ jb = Sequel.sqlite_jsonb_op(:column)
14
+ jb.extract('$.a') # jsonb_extract(column, '$.a')
15
+ jb.insert('$.a', 1) # jsonb_insert(column, '$.a', 1)
16
+ jb.set('$.a', 1) # jsonb_set(column, '$.a', 1)
17
+ jb.replace('$.a', 1) # jsonb_replace(column, '$.a', 1)
18
+ jb.remove('$.a') # jsonb_remove(column, '$.a')
19
+ jb.patch('{"a":2}') # jsonb_patch(column, '{"a":2}')
20
+
21
+ You can use the json and jsonb methods to convert jsonb to json
22
+ and json to jsonb, respectively.
23
+
24
+ jb.json # json(column)
25
+
26
+ Use of the json method on jsonb types is important, because if you
27
+ want to be able to deal with the values in Ruby, you must convert
28
+ the jsonb value to json in the database before the database returns
29
+ the value. Unlike PostgreSQL, SQLite will not convert the value
30
+ from jsonb to json on retrieval, and direct use of SQLite's jsonb
31
+ format is unsupported by SQLite as it is subject to change.
32
+
33
+ * Database#with_advisory_lock is now supported on PostgreSQL, MySQL,
34
+ and Microsoft SQL Server. This supports advisory (explicit)
35
+ locking, using the database-specific APIs. To work on all three
36
+ servers, lock ids should be integers in the signed 64-bit range.
37
+
38
+ DB.with_advisory_lock(1234) do
39
+ # do something
40
+ end
41
+
42
+ By default, an AdvisoryLockError is raised if the lock cannot be
43
+ immediately acquired. You can use the :wait option to wait until
44
+ the lock can be acquired, instead of raising.
45
+
46
+ DB.with_advisory_lock(1234, wait: true) do
47
+ # do something
48
+ end
49
+
50
+ * Migrator.run now supports a :use_advisory_lock option to use
51
+ advisory locks when running migrations, so that it does not
52
+ attempt to run the same migration more than once in the case
53
+ where multiple processes are running the migrator simultaneously.
54
+ It's probably best to avoid running the migrator in multiple
55
+ processes simultaneously instead of relying on this option.
56
+
57
+ = Other Improvements
58
+
59
+ * Database#values now supports chaining with compounds on
60
+ PostgreSQL.
61
+
62
+ DB.values([[1, 2]]).union(DB.values([[3, 4]]))
63
+ # SELECT * FROM (VALUES (1, 2) UNION (VALUES (3, 4))) AS t1
64
+
65
+ * The internal hash used to store transaction metadata now uses
66
+ compare_by_identity, which is faster and avoids potential
67
+ issues if a driver implements connection object equality.
@@ -81,8 +81,8 @@ appropriate 64-bit integer type for the database you are using.
81
81
 
82
82
  === Column options
83
83
 
84
- When using the type name as method, the third argument is an options hash, and when using the +column+
85
- method, the fourth argument is the options hash. The following options are supported:
84
+ When using the type name as method, the second argument is an options hash, and when using the +column+
85
+ method, the third argument is the options hash. The following options are supported:
86
86
 
87
87
  :default :: The default value for the column.
88
88
  :index :: Create an index on this column. If given a hash, use the hash as the
@@ -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/sharding.rdoc CHANGED
@@ -39,7 +39,9 @@ is the simplest configuration:
39
39
  servers: {read_only: {host: 'replica_server'}})
40
40
 
41
41
  This will use the replica_server for SELECT queries and primary_server for
42
- other queries.
42
+ other queries. The :read_only key in the :servers hash is special in that
43
+ it sets the default database for Dataset methods that use SELECT queries
44
+ (which are generally read queries that do not modify the database).
43
45
 
44
46
  If you want to ensure your queries are going to a specific database, you
45
47
  can force this for a given query by using the .server method and passing
data/doc/sql.rdoc CHANGED
@@ -59,7 +59,7 @@ Then, you call the +insert+, +update+, or +delete+ method on the returned datase
59
59
  update_ds.update
60
60
  delete_ds.delete
61
61
 
62
- +update+ and +delete+ should return the number of rows affected, and +insert+ should return the autogenerated primary key integer for the row inserted (if any).
62
+ +update+ and +delete+ generally return the number of rows affected, and +insert+ generally returns the autogenerated primary key integer for the row inserted (if any), but not all adapters/databases support this behavior for datasets using custom SQL (notably it is not supported for +insert+ on PostgreSQL).
63
63
 
64
64
  === Other Queries
65
65
 
@@ -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
 
@@ -159,28 +159,32 @@ The SEQUEL_INTEGRATION_URL environment variable specifies the Database connectio
159
159
 
160
160
  === Other
161
161
 
162
+ SEQUEL_AUTO_CAST_DATE_TIME :: Use the auto_cast_date_and_time extension when running the specs
162
163
  SEQUEL_ASYNC_THREAD_POOL :: Use the async_thread_pool extension when running the specs
163
164
  SEQUEL_ASYNC_THREAD_POOL_PREEMPT :: Use the async_thread_pool extension when running the specs, with the :preempt_async_thread option
165
+ 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
166
  SEQUEL_COLUMNS_INTROSPECTION :: Use the columns_introspection extension when running the specs
165
- SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when running the specs
166
- SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
167
167
  SEQUEL_CONCURRENT_EAGER_LOADING :: Use the async_thread_pool extension and concurrent_eager_loading plugin when running the specs
168
+ SEQUEL_CONNECTION_VALIDATOR :: Use the connection_validator extension when running the adapter/integration specs
169
+ SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
168
170
  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
171
  SEQUEL_FIBER_CONCURRENCY :: Use the fiber_concurrency extension when running the adapter and integration specs
171
172
  SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
172
173
  SEQUEL_IDENTIFIER_MANGLING :: Use the identifier_mangling extension when running the specs
174
+ SEQUEL_INDEX_CACHING :: Use the index_caching extension when running the specs
173
175
  SEQUEL_INTEGER64 :: Use the integer64 extension when running the adapter or integration specs
174
176
  SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements plugin when running the specs
175
177
  SEQUEL_MODEL_THROW_FAILURES :: Use the throw_failures plugin when running the specs
176
178
  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
179
  SEQUEL_NO_PENDING :: Don't skip any specs, try running all specs (note, can cause lockups for some adapters)
180
+ SEQUEL_PG_AUTO_PARAMETERIZE :: Use the pg_auto_parameterize extension when running the postgres specs. Value can be +in_array+ to test the pg_auto_parameterize_in_array extension, and +in_array_string+ to test the pg_auto_parameterize_in_array extension with the +:treat_in_string_list_as_text_array+ Database option set.
179
181
  SEQUEL_PG_TIMESTAMPTZ :: Use the pg_timestamptz extension when running the postgres specs
182
+ SEQUEL_PRIMARY_KEY_LOOKUP_CHECK_VALUES :: Use the primary_key_lookup_check_values extension when running the adapter or integration specs
180
183
  SEQUEL_QUERY_PER_ASSOCIATION_DB_0_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
181
184
  SEQUEL_QUERY_PER_ASSOCIATION_DB_1_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
182
185
  SEQUEL_QUERY_PER_ASSOCIATION_DB_2_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
183
186
  SEQUEL_QUERY_PER_ASSOCIATION_DB_3_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
184
187
  SEQUEL_SPLIT_SYMBOLS :: Turn on symbol splitting when running the adapter and integration specs
185
188
  SEQUEL_SYNCHRONIZE_SQL :: Use the synchronize_sql extension when running the specs
189
+ SEQUEL_TRANSACTION_CONNECTION_VALIDATOR :: Use the transaction_connection_validator extension when running the adapter/integration specs
186
190
  SEQUEL_TZINFO_VERSION :: Force the given tzinfo version when running the specs (e.g. '>=2')
@@ -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
@@ -301,7 +301,7 @@ module Sequel
301
301
  end
302
302
 
303
303
  def database_exception_sqlstate(exception, opts)
304
- exception.sqlstate
304
+ exception.sqlstate if exception.respond_to?(:sqlstate)
305
305
  end
306
306
 
307
307
  def dataset_class_default
@@ -1,6 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  Sequel::JDBC.load_driver('org.h2.Driver', :H2)
4
+ require_relative '../../extensions/auto_cast_date_and_time'
4
5
 
5
6
  module Sequel
6
7
  module JDBC
@@ -14,6 +15,8 @@ module Sequel
14
15
 
15
16
  module H2
16
17
  module DatabaseMethods
18
+ include AutoCastDateAndTime
19
+
17
20
  def commit_prepared_transaction(transaction_id, opts=OPTS)
18
21
  run("COMMIT TRANSACTION #{transaction_id}", opts)
19
22
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  Sequel::JDBC.load_driver('org.hsqldb.jdbcDriver', :HSQLDB)
4
4
  require_relative 'transactions'
5
+ require_relative '../../extensions/auto_cast_date_and_time'
5
6
 
6
7
  module Sequel
7
8
  module JDBC
@@ -15,6 +16,7 @@ module Sequel
15
16
 
16
17
  module HSQLDB
17
18
  module DatabaseMethods
19
+ include AutoCastDateAndTime
18
20
  include ::Sequel::JDBC::Transactions
19
21
 
20
22
  def database_type
@@ -199,6 +199,7 @@ module Sequel
199
199
  v.strftime("'%H:%M:%S#{sprintf(".%03d", (v.usec/1000.0).round)}'")
200
200
  end
201
201
 
202
+ INTEGER_TYPE = Java::JavaSQL::Types::INTEGER
202
203
  STRING_TYPE = Java::JavaSQL::Types::VARCHAR
203
204
  ARRAY_TYPE = Java::JavaSQL::Types::ARRAY
204
205
  PG_SPECIFIC_TYPES = [Java::JavaSQL::Types::ARRAY, Java::JavaSQL::Types::OTHER, Java::JavaSQL::Types::STRUCT, Java::JavaSQL::Types::TIME_WITH_TIMEZONE, Java::JavaSQL::Types::TIME].freeze
@@ -219,6 +220,8 @@ module Sequel
219
220
  oid = meta.getField(i).getOID
220
221
  if pr = db.oid_convertor_proc(oid)
221
222
  pr
223
+ elsif oid == 28 # XID (Transaction ID)
224
+ map[INTEGER_TYPE]
222
225
  elsif oid == 2950 # UUID
223
226
  map[STRING_TYPE]
224
227
  elsif meta.getPGType(i) == 'hstore'
@@ -36,6 +36,10 @@ module Sequel
36
36
 
37
37
  private
38
38
 
39
+ def database_exception_use_sqlstates?
40
+ false
41
+ end
42
+
39
43
  # Use @@IDENTITY to get the last inserted id
40
44
  def last_insert_id(conn, opts=OPTS)
41
45
  statement(conn) do |stmt|
@@ -52,6 +56,17 @@ module Sequel
52
56
 
53
57
  private
54
58
 
59
+ # JDBC SQLAnywhere driver does not appear to handle fractional
60
+ # times correctly.
61
+ def default_time_format
62
+ "'%H:%M:%S'"
63
+ end
64
+
65
+ # Set to zero to work around JDBC SQLAnywhere driver bug.
66
+ def sqltime_precision
67
+ 0
68
+ end
69
+
55
70
  SMALLINT_TYPE = Java::JavaSQL::Types::SMALLINT
56
71
  BOOLEAN_METHOD = Object.new
57
72
  def BOOLEAN_METHOD.call(r, i)
@@ -79,6 +79,10 @@ module Sequel
79
79
  super.with_extend(MetadataDatasetMethods)
80
80
  end
81
81
 
82
+ def database_exception_use_sqlstates?
83
+ false
84
+ end
85
+
82
86
  def disconnect_error?(exception, opts)
83
87
  super || (exception.message =~ /connection is closed/)
84
88
  end