sequel 5.75.0 → 5.77.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +48 -0
  3. data/doc/opening_databases.rdoc +4 -2
  4. data/doc/release_notes/5.76.0.txt +86 -0
  5. data/doc/release_notes/5.77.0.txt +63 -0
  6. data/doc/testing.rdoc +3 -1
  7. data/lib/sequel/adapters/jdbc/h2.rb +3 -0
  8. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -0
  9. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -0
  10. data/lib/sequel/adapters/mysql2.rb +2 -2
  11. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  12. data/lib/sequel/adapters/postgres.rb +2 -2
  13. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  14. data/lib/sequel/adapters/shared/mysql.rb +10 -0
  15. data/lib/sequel/adapters/shared/oracle.rb +4 -6
  16. data/lib/sequel/adapters/shared/postgres.rb +22 -1
  17. data/lib/sequel/adapters/shared/sqlanywhere.rb +10 -4
  18. data/lib/sequel/adapters/shared/sqlite.rb +20 -2
  19. data/lib/sequel/adapters/sqlite.rb +42 -3
  20. data/lib/sequel/connection_pool.rb +4 -2
  21. data/lib/sequel/database/misc.rb +2 -2
  22. data/lib/sequel/database/schema_methods.rb +6 -0
  23. data/lib/sequel/dataset/features.rb +10 -1
  24. data/lib/sequel/dataset/sql.rb +47 -34
  25. data/lib/sequel/extensions/auto_cast_date_and_time.rb +94 -0
  26. data/lib/sequel/extensions/duplicate_columns_handler.rb +10 -9
  27. data/lib/sequel/extensions/named_timezones.rb +1 -1
  28. data/lib/sequel/extensions/pg_array.rb +2 -0
  29. data/lib/sequel/extensions/pg_extended_date_support.rb +4 -4
  30. data/lib/sequel/extensions/pg_range.rb +2 -2
  31. data/lib/sequel/extensions/pg_timestamptz.rb +27 -3
  32. data/lib/sequel/extensions/round_timestamps.rb +1 -1
  33. data/lib/sequel/extensions/transaction_connection_validator.rb +78 -0
  34. data/lib/sequel/model/associations.rb +9 -2
  35. data/lib/sequel/model/base.rb +5 -2
  36. data/lib/sequel/plugins/list.rb +5 -2
  37. data/lib/sequel/plugins/rcte_tree.rb +7 -4
  38. data/lib/sequel/plugins/validation_helpers.rb +1 -1
  39. data/lib/sequel/version.rb +1 -1
  40. metadata +9 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3047129164c9cdffee31414419904329e410db71e7e4243c0549614498a2b0d4
4
- data.tar.gz: 9cc84ed8e9dba53aac7175be04699089932566e4015aed7a465c43552808c8b4
3
+ metadata.gz: 9951772dd3785c8ce91090bd31034a1e57ac5dcbc17af774b980a115cea15347
4
+ data.tar.gz: 3cfcaefaf6aa4758ef2cfaf78cbe6ccdc688e8b3836718bd63c42c5bdb220026
5
5
  SHA512:
6
- metadata.gz: 15ed5c13e4793191546cd452aa5865e65fd7b3bb0458ffdb674d526398b7c9446e2da0f43a339daa3f1dc256eb551f0b773ac9ffc192b4d19f389d0c7e296d98
7
- data.tar.gz: 1f25851b50857fbbf8378216794f26d0d8e9baa247f008feac466a218ae6b0777249252b6d05756e075096c5312b9d3b1334b7c4bc1884251e7b892cc17ae7c6
6
+ metadata.gz: '0885577c11fd7285a5278d0a1b52ae411e557cec7bce2f3a49f8128a0be63928ebfa55b2b1a86c8b28ee1c3782c1dc5ebf5d4ecf00f0194ad33da89cb6ffc12a'
7
+ data.tar.gz: ccc7b8b6c68049ee1fed2211a3d193157ee36fde9c340324eba2a8cebd8925bc97b4dc1777b61f8a2fb94d83439c41f33afb832c080f4d54bab16d09924a4fe2
data/CHANGELOG CHANGED
@@ -1,3 +1,51 @@
1
+ === 5.77.0 (2024-02-01)
2
+
3
+ * Support create_table :without_rowid option on SQLite (loranger32) (#2126)
4
+
5
+ * Warn by default if trying to eager_graph/association_join an association that uses a block, when the block would be ignored (jeremyevans)
6
+
7
+ * Speed up validates_unique in validation_helpers plugin by using empty? instead of count == 0 (numbata) (#2122)
8
+
9
+ * Speed up regexp matches in sqlite adapter on Ruby 2.4+ (jeremyevans)
10
+
11
+ * Add sqlite adapter :regexp_function_cache option for specifying the cache object to use (paddor, jeremyevans) (#2116)
12
+
13
+ * Respect list plugin :top option when inserting the first row into the model's table (johanmagnusson) (#2115)
14
+
15
+ * Switch default connection pool to timed_queue on Ruby 3.4+ (jeremyevans)
16
+
17
+ * Support on_duplicate_columns={raise,warn} parameter in connection URL when using duplicate_columns_handler extension (jeremyevans)
18
+
19
+ * Add transaction_connection_validator extension for retrying transactions on new connection if ther is a disconnect error when starting transaction (jeremyevans)
20
+
21
+ === 5.76.0 (2024-01-01)
22
+
23
+ * Improve performance and flexibility of regexp matching in sqlite adapter (paddor) (#2108)
24
+
25
+ * Support SQL::Identifier for Database#tables :schema option values on PostgreSQL (jeremyevans)
26
+
27
+ * Support generating rcte queries using UNION or UNION ALL in the rcte plugin (jonathanfrias) (#2107)
28
+
29
+ * Make Database#table_exists? on PostgreSQL handle lock or statement timeout errors as evidence the table exists (jeremyevans) (#2106)
30
+
31
+ * Work around DateTime.jd fractional second bug on JRuby in named_timezones extension (jeremyevans)
32
+
33
+ * Support fractional times and timestamps on SQLAnywhere (jeremyevans)
34
+
35
+ * Make round_timestamps extension use Dataset#sqltime_precision for rounding Sequel::SQLTime values (jeremyevans)
36
+
37
+ * Remove special handling of %N modifier in Dataset#default_timestamp_format (jeremyevans)
38
+
39
+ * Add Dataset#default_time_format private method, for adapters to override for time (not timestamp) formatting (jeremyevans)
40
+
41
+ * Remove Dataset#format_timestamp_offset private method (jeremyevans)
42
+
43
+ * Remove special handling of %z modifier in Dataset#default_timestamp_format (jeremyevans)
44
+
45
+ * Add Dataset#literal_date_or_time, for simpler use by bound argument code (jeremyevans)
46
+
47
+ * Add auto_cast_date_and_time extension, for casting date and time values using SQL standard functions (jeremyevans)
48
+
1
49
  === 5.75.0 (2023-12-01)
2
50
 
3
51
  * Make any_not_empty? extension support passing pattern argument to any? (jeremyevans) (#2100)
@@ -388,8 +388,10 @@ The following additional options are supported:
388
388
  :readonly :: open database in read-only mode
389
389
  :timeout :: the busy timeout to use in milliseconds (default: 5000).
390
390
  :setup_regexp_function :: Whether to setup a REGEXP function in the underlying SQLite3::Database object. Doing so
391
- allows you to use regexp support in dataset expressions. Note that this creates a new
392
- Regexp object per call to the function, so it is not an efficient implementation.
391
+ allows you to use regexp support in dataset expressions. If +:cached+ or <tt>"cached"</tt>+, caches each
392
+ unique regex (more efficient but risk of memory leak). If a Proc is provided, it will be called with
393
+ a string for the regexp and a string for the value to compare, and should return whether the regexp
394
+ string matches the string value to compare. The default Proc used does <tt>Regexp.new(regexp_str).match(str)</tt>.
393
395
 
394
396
  Note that SQLite memory databases are restricted to a single connection by
395
397
  default. This is because SQLite does not allow multiple connections to
@@ -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.
data/doc/testing.rdoc CHANGED
@@ -159,12 +159,13 @@ 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
164
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
165
166
  SEQUEL_COLUMNS_INTROSPECTION :: Use the columns_introspection extension when running the specs
166
167
  SEQUEL_CONCURRENT_EAGER_LOADING :: Use the async_thread_pool extension and concurrent_eager_loading plugin when running the specs
167
- SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when running the specs
168
+ SEQUEL_CONNECTION_VALIDATOR :: Use the connection_validator extension when running the adapter/integration specs
168
169
  SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
169
170
  SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
170
171
  SEQUEL_FIBER_CONCURRENCY :: Use the fiber_concurrency extension when running the adapter and integration specs
@@ -185,4 +186,5 @@ SEQUEL_QUERY_PER_ASSOCIATION_DB_2_URL :: Run query-per-association integration t
185
186
  SEQUEL_QUERY_PER_ASSOCIATION_DB_3_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
186
187
  SEQUEL_SPLIT_SYMBOLS :: Turn on symbol splitting when running the adapter and integration specs
187
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
188
190
  SEQUEL_TZINFO_VERSION :: Force the given tzinfo version when running the specs (e.g. '>=2')
@@ -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
@@ -56,6 +56,17 @@ module Sequel
56
56
 
57
57
  private
58
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
+
59
70
  SMALLINT_TYPE = Java::JavaSQL::Types::SMALLINT
60
71
  BOOLEAN_METHOD = Object.new
61
72
  def BOOLEAN_METHOD.call(r, i)
@@ -182,8 +182,8 @@ module Sequel
182
182
  1
183
183
  when false
184
184
  0
185
- when DateTime, Time
186
- literal(arg)[1...-1]
185
+ when Time, Date
186
+ @default_dataset.literal_date_or_time(arg, true)
187
187
  else
188
188
  arg
189
189
  end
@@ -43,7 +43,7 @@ module Sequel
43
43
  # Use ODBC format, not Microsoft format, as the ODBC layer does
44
44
  # some translation, but allow for millisecond precision.
45
45
  def default_timestamp_format
46
- "{ts '%Y-%m-%d %H:%M:%S%N'}"
46
+ "{ts '%Y-%m-%d %H:%M:%S.%3N'}"
47
47
  end
48
48
 
49
49
  # Use ODBC format, not Microsoft format, as the ODBC layer does
@@ -188,8 +188,8 @@ module Sequel
188
188
  # :nocov:
189
189
  # Not covered by tests as tests use pg_extended_date_support
190
190
  # extension, which has basically the same code.
191
- when DateTime, Time
192
- literal(arg)
191
+ when Time, DateTime
192
+ @default_dataset.literal_date_or_time(arg)
193
193
  # :nocov:
194
194
  else
195
195
  arg
@@ -932,7 +932,7 @@ module Sequel
932
932
  # since that is the format that is multilanguage and not
933
933
  # DATEFORMAT dependent.
934
934
  def default_timestamp_format
935
- "'%Y-%m-%dT%H:%M:%S%N%z'"
935
+ "'%Y-%m-%dT%H:%M:%S.%3N'"
936
936
  end
937
937
 
938
938
  # Only include the primary table in the main delete clause
@@ -929,6 +929,16 @@ module Sequel
929
929
  super if type == :truncate || @opts[:offset]
930
930
  end
931
931
 
932
+ # The strftime format to use when literalizing time (Sequel::SQLTime) values.
933
+ def default_time_format
934
+ db.supports_timestamp_usecs? ? super : "'%H:%M:%S'"
935
+ end
936
+
937
+ # The strftime format to use when literalizing timestamp (Time/DateTime) values.
938
+ def default_timestamp_format
939
+ db.supports_timestamp_usecs? ? super : "'%Y-%m-%d %H:%M:%S'"
940
+ end
941
+
932
942
  # Consider the first table in the joined dataset is the table to delete
933
943
  # from, but include the others for the purposes of selecting rows.
934
944
  def delete_from_sql(sql)
@@ -1,6 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  require_relative '../utils/emulate_offset_with_row_number'
4
+ require_relative '../../extensions/auto_cast_date_and_time'
4
5
 
5
6
  module Sequel
6
7
  module Oracle
@@ -326,6 +327,8 @@ module Sequel
326
327
  end
327
328
 
328
329
  module DatasetMethods
330
+ include AutoCastDateAndTime
331
+
329
332
  ROW_NUMBER_EXPRESSION = LiteralString.new('ROWNUM').freeze
330
333
  BITAND_PROC = lambda{|a, b| Sequel.lit(["CAST(BITAND(", ", ", ") AS INTEGER)"], a, b)}
331
334
 
@@ -623,7 +626,7 @@ module Sequel
623
626
 
624
627
  # The strftime format to use when literalizing the time.
625
628
  def default_timestamp_format
626
- "TIMESTAMP '%Y-%m-%d %H:%M:%S%N %z'"
629
+ "'%Y-%m-%d %H:%M:%S.%6N %:z'"
627
630
  end
628
631
 
629
632
  def empty_from_sql
@@ -660,11 +663,6 @@ module Sequel
660
663
  super
661
664
  end
662
665
 
663
- # Use a colon for the timestamp offset, since Oracle appears to require it.
664
- def format_timestamp_offset(hour, minute)
665
- sprintf("%+03i:%02i", hour, minute)
666
- end
667
-
668
666
  # Oracle doesn't support empty values when inserting.
669
667
  def insert_supports_empty_values?
670
668
  false
@@ -1092,6 +1092,14 @@ module Sequel
1092
1092
  sql << type
1093
1093
  end
1094
1094
 
1095
+ # Consider lock or statement timeout errors as evidence that the table exists
1096
+ # but is locked.
1097
+ def _table_exists?(ds)
1098
+ super
1099
+ rescue DatabaseError => e
1100
+ raise e unless /canceling statement due to (?:statement|lock) timeout/ =~ e.message
1101
+ end
1102
+
1095
1103
  def alter_table_add_column_sql(table, op)
1096
1104
  "ADD COLUMN#{' IF NOT EXISTS' if op[:if_not_exists]} #{column_definition_sql(op)}"
1097
1105
  end
@@ -1505,7 +1513,11 @@ module Sequel
1505
1513
  # currently visible schemas.
1506
1514
  def filter_schema(ds, opts)
1507
1515
  expr = if schema = opts[:schema]
1508
- schema.to_s
1516
+ if schema.is_a?(SQL::Identifier)
1517
+ schema.value.to_s
1518
+ else
1519
+ schema.to_s
1520
+ end
1509
1521
  else
1510
1522
  Sequel.function(:any, Sequel.function(:current_schemas, false))
1511
1523
  end
@@ -2138,10 +2150,14 @@ module Sequel
2138
2150
  server_version >= 90500
2139
2151
  end
2140
2152
 
2153
+ # :nocov:
2154
+
2141
2155
  # PostgreSQL supports timezones in literal timestamps
2142
2156
  def supports_timestamp_timezones?
2157
+ # SEQUEL6: Remove
2143
2158
  true
2144
2159
  end
2160
+ # :nocov:
2145
2161
 
2146
2162
  # PostgreSQL 8.4+ supports WINDOW clause.
2147
2163
  def supports_window_clause?
@@ -2261,6 +2277,11 @@ module Sequel
2261
2277
  raise(InvalidOperation, "Joined datasets cannot be truncated") if opts[:join]
2262
2278
  end
2263
2279
 
2280
+ # The strftime format to use when literalizing the time.
2281
+ def default_timestamp_format
2282
+ "'%Y-%m-%d %H:%M:%S.%6N%z'"
2283
+ end
2284
+
2264
2285
  # Only include the primary table in the main delete clause
2265
2286
  def delete_from_sql(sql)
2266
2287
  sql << ' FROM '
@@ -281,10 +281,6 @@ module Sequel
281
281
  false
282
282
  end
283
283
 
284
- def supports_timestamp_usecs?
285
- false
286
- end
287
-
288
284
  def supports_window_clause?
289
285
  true
290
286
  end
@@ -378,6 +374,16 @@ module Sequel
378
374
 
379
375
  private
380
376
 
377
+ # SQLAnywhere only supports 3 digits after the decimal point for times.
378
+ def default_time_format
379
+ "'%H:%M:%S.%3N'"
380
+ end
381
+
382
+ # SQLAnywhere only supports 3 digits after the decimal point for timestamps.
383
+ def default_timestamp_format
384
+ "'%Y-%m-%d %H:%M:%S.%3N'"
385
+ end
386
+
381
387
  # Use 1 for true on Sybase
382
388
  def literal_true
383
389
  '1'
@@ -145,6 +145,11 @@ module Sequel
145
145
  sqlite_version >= 30608
146
146
  end
147
147
 
148
+ # SQLite 3.8.2+ supports the without rowid table constraint
149
+ def support_without_rowid?
150
+ sqlite_version >= 30802
151
+ end
152
+
148
153
  # Override the default setting for whether to use timezones in timestamps.
149
154
  # It is set to +false+ by default, as SQLite's date/time methods do not
150
155
  # support timezones in timestamps.
@@ -344,9 +349,17 @@ module Sequel
344
349
  ps
345
350
  end
346
351
 
347
- # Support creating STRICT tables via :strict option
352
+ # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options
348
353
  def create_table_sql(name, generator, options)
349
- "#{super}#{' STRICT' if options[:strict]}"
354
+ if options[:strict] && options[:without_rowid]
355
+ "#{super} STRICT, WITHOUT ROWID"
356
+ elsif options[:strict]
357
+ "#{super} STRICT"
358
+ elsif options[:without_rowid]
359
+ "#{super} WITHOUT ROWID"
360
+ else
361
+ super
362
+ end
350
363
  end
351
364
 
352
365
  # SQLite support creating temporary views.
@@ -917,6 +930,11 @@ module Sequel
917
930
  500
918
931
  end
919
932
 
933
+ # The strftime format to use when literalizing the time.
934
+ def default_timestamp_format
935
+ db.use_timestamp_timezones? ? "'%Y-%m-%d %H:%M:%S.%6N%z'" : super
936
+ end
937
+
920
938
  # SQL fragment specifying a list of identifiers
921
939
  def identifier_list(columns)
922
940
  columns.map{|i| quote_identifier(i)}.join(', ')
@@ -111,6 +111,18 @@ module Sequel
111
111
  # static data that you do not want to modify
112
112
  # :timeout :: how long to wait for the database to be available if it
113
113
  # is locked, given in milliseconds (default is 5000)
114
+ # :setup_regexp_function :: enable use of Regexp objects with SQL
115
+ # 'REGEXP' operator. If the value is :cached or "cached",
116
+ # caches the generated regexps, which can result in a memory
117
+ # leak if dynamic regexps are used. If the value is a Proc,
118
+ # it will be called with a string for the regexp and a string
119
+ # for the value to compare, and should return whether the regexp
120
+ # matches.
121
+ # :regexp_function_cache :: If setting +setup_regexp_function+ to +cached+, this
122
+ # determines the cache to use. It should either be a proc or a class, and it
123
+ # defaults to +Hash+. You can use +ObjectSpace::WeakKeyMap+ on Ruby 3.3+ to
124
+ # have the VM automatically remove regexps from the cache after they
125
+ # are no longer used.
114
126
  def connect(server)
115
127
  opts = server_opts(server)
116
128
  opts[:database] = ':memory:' if blank_object?(opts[:database])
@@ -126,9 +138,7 @@ module Sequel
126
138
  connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}}
127
139
 
128
140
  if typecast_value_boolean(opts[:setup_regexp_function])
129
- db.create_function("regexp", 2) do |func, regexp_str, string|
130
- func.result = Regexp.new(regexp_str).match(string) ? 1 : 0
131
- end
141
+ setup_regexp_function(db, opts[:setup_regexp_function])
132
142
  end
133
143
 
134
144
  class << db
@@ -202,6 +212,35 @@ module Sequel
202
212
  @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp)
203
213
  set_integer_booleans
204
214
  end
215
+
216
+ def setup_regexp_function(db, how)
217
+ case how
218
+ when Proc
219
+ # nothing
220
+ when :cached, "cached"
221
+ cache = @opts[:regexp_function_cache] || Hash
222
+ cache = cache.is_a?(Proc) ? cache.call : cache.new
223
+ how = if RUBY_VERSION >= '2.4'
224
+ lambda do |regexp_str, str|
225
+ (cache[regexp_str] ||= Regexp.new(regexp_str)).match?(str)
226
+ end
227
+ else
228
+ lambda do |regexp_str, str|
229
+ (cache[regexp_str] ||= Regexp.new(regexp_str)).match(str)
230
+ end
231
+ end
232
+ else
233
+ how = if RUBY_VERSION >= '2.4'
234
+ lambda{|regexp_str, str| Regexp.new(regexp_str).match?(str)}
235
+ else
236
+ lambda{|regexp_str, str| Regexp.new(regexp_str).match(str)}
237
+ end
238
+ end
239
+
240
+ db.create_function("regexp", 2) do |func, regexp_str, str|
241
+ func.result = how.call(regexp_str, str) ? 1 : 0
242
+ end
243
+ end
205
244
 
206
245
  # Yield an available connection. Rescue
207
246
  # any SQLite3::Exceptions and turn them into DatabaseErrors.
@@ -70,8 +70,10 @@ class Sequel::ConnectionPool
70
70
  else
71
71
  pc = if opts[:single_threaded]
72
72
  opts[:servers] ? :sharded_single : :single
73
- #elsif RUBY_VERSION >= '3.2' # SEQUEL6 or maybe earlier
74
- # opts[:servers] ? :sharded_timed_queue : :timed_queue
73
+ # :nocov:
74
+ elsif RUBY_VERSION >= '3.4' # SEQUEL6 or maybe earlier switch to 3.2
75
+ opts[:servers] ? :sharded_timed_queue : :timed_queue
76
+ # :nocov:
75
77
  else
76
78
  opts[:servers] ? :sharded_threaded : :threaded
77
79
  end
@@ -263,8 +263,8 @@ module Sequel
263
263
  # Proxy the literal call to the dataset.
264
264
  #
265
265
  # DB.literal(1) # 1
266
- # DB.literal(:a) # a
267
- # DB.literal('a') # 'a'
266
+ # DB.literal(:a) # "a" # or `a`, [a], or a, depending on identifier quoting
267
+ # DB.literal("a") # 'a'
268
268
  def literal(v)
269
269
  schema_utility_dataset.literal(v)
270
270
  end
@@ -191,6 +191,12 @@ module Sequel
191
191
  # The +any+ type is treated like a SQLite column in a non-strict table,
192
192
  # allowing any type of data to be stored. This option is supported on
193
193
  # SQLite 3.37.0+.
194
+ # :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special
195
+ # 'rowid' column, that uniquely identifies that row within the table.
196
+ # If this option is used, the 'rowid' column is omitted, which can
197
+ # sometimes provide some space and speed advantages. Note that you
198
+ # must then provide an explicit primary key when you create the table.
199
+ # This option is supported on SQLite 3.8.2+.
194
200
  #
195
201
  # See <tt>Schema::CreateTableGenerator</tt> and the {"Schema Modification" guide}[rdoc-ref:doc/schema_modification.rdoc].
196
202
  def create_table(name, options=OPTS, &block)