sequel 5.108.0 → 5.110.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sequel/adapters/ado.rb +1 -0
  3. data/lib/sequel/adapters/amalgalite.rb +34 -8
  4. data/lib/sequel/adapters/jdbc/mssql.rb +28 -5
  5. data/lib/sequel/adapters/jdbc/postgresql.rb +14 -3
  6. data/lib/sequel/adapters/jdbc.rb +2 -1
  7. data/lib/sequel/adapters/postgres.rb +5 -2
  8. data/lib/sequel/adapters/shared/access.rb +5 -1
  9. data/lib/sequel/adapters/shared/db2.rb +3 -0
  10. data/lib/sequel/adapters/shared/mssql.rb +7 -1
  11. data/lib/sequel/adapters/shared/oracle.rb +7 -0
  12. data/lib/sequel/adapters/shared/postgres.rb +97 -1001
  13. data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -32
  14. data/lib/sequel/adapters/sqlite.rb +13 -9
  15. data/lib/sequel/adapters/trilogy.rb +2 -1
  16. data/lib/sequel/core.rb +71 -23
  17. data/lib/sequel/database/misc.rb +1 -6
  18. data/lib/sequel/database/schema_methods.rb +3 -3
  19. data/lib/sequel/database/transactions.rb +1 -3
  20. data/lib/sequel/dataset/actions.rb +1 -1
  21. data/lib/sequel/dataset/sql.rb +14 -3
  22. data/lib/sequel/extensions/core_refinements.rb +1 -4
  23. data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -2
  24. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -3
  25. data/lib/sequel/extensions/lit_require_frozen.rb +17 -1
  26. data/lib/sequel/extensions/named_timezones.rb +9 -7
  27. data/lib/sequel/extensions/pg_array.rb +1 -0
  28. data/lib/sequel/extensions/pg_json_ops.rb +4 -2
  29. data/lib/sequel/extensions/pg_loose_count.rb +37 -2
  30. data/lib/sequel/extensions/s.rb +4 -8
  31. data/lib/sequel/extensions/schema_dumper.rb +6 -2
  32. data/lib/sequel/extensions/sql_comments.rb +0 -4
  33. data/lib/sequel/extensions/string_date_time.rb +7 -4
  34. data/lib/sequel/extensions/symbol_aref.rb +11 -31
  35. data/lib/sequel/extensions/symbol_aref_refinement.rb +1 -4
  36. data/lib/sequel/extensions/symbol_as.rb +1 -2
  37. data/lib/sequel/extensions/symbol_as_refinement.rb +1 -5
  38. data/lib/sequel/model/base.rb +4 -9
  39. data/lib/sequel/plugins/caching.rb +27 -2
  40. data/lib/sequel/plugins/csv_serializer.rb +9 -20
  41. data/lib/sequel/plugins/instance_filters.rb +8 -0
  42. data/lib/sequel/plugins/instance_hooks.rb +19 -0
  43. data/lib/sequel/plugins/mssql_optimistic_locking.rb +9 -0
  44. data/lib/sequel/plugins/optimistic_locking.rb +12 -2
  45. data/lib/sequel/plugins/optimistic_locking_base.rb +14 -0
  46. data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +11 -2
  47. data/lib/sequel/plugins/select_on_skipped_update.rb +63 -0
  48. data/lib/sequel/plugins/single_table_inheritance.rb +20 -2
  49. data/lib/sequel/plugins/subset_conditions.rb +5 -16
  50. data/lib/sequel/plugins/throw_failures.rb +1 -1
  51. data/lib/sequel/plugins/validate_associated.rb +7 -1
  52. data/lib/sequel/plugins/validate_associated_context.rb +52 -0
  53. data/lib/sequel/sql.rb +109 -105
  54. data/lib/sequel/version.rb +1 -1
  55. metadata +5 -3
@@ -305,38 +305,6 @@ module Sequel
305
305
  super(sql, :+, args)
306
306
  when :<<, :>>
307
307
  complex_expression_emulate_append(sql, op, args)
308
- when :LIKE, :"NOT LIKE"
309
- sql << '('
310
- literal_append(sql, args[0])
311
- sql << (op == :LIKE ? ' REGEXP ' : ' NOT REGEXP ')
312
- pattern = String.new
313
- last_c = ''
314
- args[1].each_char do |c|
315
- if c == '_' and not pattern.end_with?('\\') and last_c != '\\'
316
- pattern << '.'
317
- elsif c == '%' and not pattern.end_with?('\\') and last_c != '\\'
318
- pattern << '.*'
319
- elsif c == '[' and not pattern.end_with?('\\') and last_c != '\\'
320
- pattern << '\['
321
- elsif c == ']' and not pattern.end_with?('\\') and last_c != '\\'
322
- pattern << '\]'
323
- elsif c == '*' and not pattern.end_with?('\\') and last_c != '\\'
324
- pattern << '\*'
325
- elsif c == '?' and not pattern.end_with?('\\') and last_c != '\\'
326
- pattern << '\?'
327
- else
328
- pattern << c
329
- end
330
- if c == '\\' and last_c == '\\'
331
- last_c = ''
332
- else
333
- last_c = c
334
- end
335
- end
336
- literal_append(sql, pattern)
337
- sql << " ESCAPE "
338
- literal_append(sql, "\\")
339
- sql << ')'
340
308
  when :ILIKE, :"NOT ILIKE"
341
309
  super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args)
342
310
  when :extract
@@ -336,16 +336,20 @@ module Sequel
336
336
  log_sql << sql
337
337
  log_sql << ")"
338
338
  end
339
- if block
340
- log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)}
341
- else
342
- log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}}
343
- case type
344
- when :insert
345
- conn.last_insert_row_id
346
- when :update
347
- conn.changes
339
+ begin
340
+ if block
341
+ log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)}
342
+ else
343
+ log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}}
344
+ case type
345
+ when :insert
346
+ conn.last_insert_row_id
347
+ when :update
348
+ conn.changes
349
+ end
348
350
  end
351
+ ensure
352
+ cps.clear_bindings!
349
353
  end
350
354
  end
351
355
 
@@ -62,7 +62,8 @@ module Sequel
62
62
  private
63
63
 
64
64
  def database_specific_error_class(exception, opts)
65
- if exception.error_code == 1205
65
+ case exception.error_code
66
+ when 1205, 3572
66
67
  DatabaseLockTimeout
67
68
  else
68
69
  super
data/lib/sequel/core.rb CHANGED
@@ -10,7 +10,7 @@
10
10
  # DB = Sequel.sqlite # Memory database
11
11
  # DB = Sequel.sqlite('blog.db')
12
12
  # DB = Sequel.postgres('database_name',
13
- # user:'user',
13
+ # user: 'user',
14
14
  # password: 'password',
15
15
  # host: 'host'
16
16
  # port: 5432,
@@ -25,7 +25,7 @@
25
25
  # For a more expanded introduction, see the {README}[rdoc-ref:README.rdoc].
26
26
  # For a quicker introduction, see the {cheat sheet}[rdoc-ref:doc/cheat_sheet.rdoc].
27
27
  module Sequel
28
- @convert_two_digit_years = true
28
+ @convert_two_digit_years = true # SEQUEL6: Remove
29
29
  @datetime_class = Time # SEQUEL6: Remove
30
30
  @split_symbols = false # SEQUEL6: Remove
31
31
  @single_threaded = false
@@ -37,6 +37,8 @@ module Sequel
37
37
  OPTS = {}.freeze
38
38
 
39
39
  SPLIT_SYMBOL_CACHE = {} # SEQUEL6: Remove
40
+ SPLIT_SYMBOL_CACHE_ = SPLIT_SYMBOL_CACHE
41
+ private_constant :SPLIT_SYMBOL_CACHE_
40
42
 
41
43
  module SequelMethods
42
44
  # Sequel converts two digit years in <tt>Date</tt>s and <tt>DateTime</tt>s by default,
@@ -45,7 +47,16 @@ module Sequel
45
47
  # January 2nd, 0003 and December 13, 0099, respectively, by:
46
48
  #
47
49
  # Sequel.convert_two_digit_years = false
48
- attr_accessor :convert_two_digit_years
50
+ #
51
+ # The setter method is deprecated and will be removed in Sequel 6.
52
+ # The reader method will be deprecated in Sequel 6.0 and removed in
53
+ # Sequel 6.1.
54
+ attr_reader :convert_two_digit_years # SEQUEL6.1: Remove
55
+
56
+ def convert_two_digit_years=(v)
57
+ Sequel::Deprecation.deprecate("Sequel.convert_two_digit_years= is deprecated and will be removed in Sequel 6.")
58
+ @convert_two_digit_years = v
59
+ end
49
60
 
50
61
  # Sequel can use either +Time+ or +DateTime+ for times returned from the
51
62
  # database. It defaults to +Time+. To change it to +DateTime+:
@@ -55,9 +66,16 @@ module Sequel
55
66
  # Note that +Time+ and +DateTime+ objects have a different API, and in
56
67
  # cases where they implement the same methods, they often implement them
57
68
  # differently (e.g. + using seconds on +Time+ and days on +DateTime+).
58
- attr_accessor :datetime_class
59
- # SEQUEL6: Remove datetime_class=
60
- # SEQUEL6.1: Remove datetime_class
69
+ #
70
+ # The setter method is deprecated and will be removed in Sequel 6.
71
+ # The reader method will be deprecated in Sequel 6.0 and removed in
72
+ # Sequel 6.1.
73
+ attr_reader :datetime_class # SEQUEL6.1: Remove
74
+
75
+ def datetime_class=(v)
76
+ Sequel::Deprecation.deprecate("Sequel.datetime_class= is deprecated and will be removed in Sequel 6.")
77
+ @datetime_class = v
78
+ end
61
79
 
62
80
  # Set whether Sequel is being used in single threaded mode. By default,
63
81
  # Sequel uses a thread-safe connection pool, which isn't as fast as the
@@ -68,8 +86,8 @@ module Sequel
68
86
  # Sequel.single_threaded = true
69
87
  attr_accessor :single_threaded
70
88
 
71
- # # SEQUEL6: Remove
72
- alias orig_require require
89
+ # SEQUEL6: Remove
90
+ define_method(:orig_require, Kernel.instance_method(:require))
73
91
  private :orig_require
74
92
 
75
93
  # Returns true if the passed object could be a specifier of conditions, false otherwise.
@@ -92,7 +110,7 @@ module Sequel
92
110
  end
93
111
  end
94
112
 
95
- # Creates a new database object based on the supplied connection string
113
+ # Creates a new Database object based on the supplied connection string
96
114
  # and optional arguments. The specified scheme determines the database
97
115
  # class used, and the rest of the string specifies the connection options.
98
116
  # For example:
@@ -156,18 +174,30 @@ module Sequel
156
174
  # Sequel.extension(:blank)
157
175
  # Sequel.extension(:core_extensions, :named_timezones)
158
176
  def extension(*extensions)
159
- extensions.each{|e| orig_require("sequel/extensions/#{e}")}
177
+ extensions.each do |e|
178
+ e = e.to_s
179
+
180
+ if %r{..[/\\]} =~ e
181
+ raise Error, "cannot use extension with ../ for security reasons"
182
+ end
183
+
184
+ Kernel.require("sequel/extensions/#{e}")
185
+ end
160
186
  end
161
187
 
162
- # The exception classed raised if there is an error parsing JSON.
188
+ # The exception class raised if there is an error parsing JSON.
163
189
  # This can be overridden to use an alternative json implementation.
164
- def json_parser_error_class
190
+ #
191
+ # This method is deprecated and will be removed in Sequel 6.1.
192
+ def json_parser_error_class # SEQUEL6.1: Remove
165
193
  JSON::ParserError
166
194
  end
167
195
 
168
196
  if RUBY_VERSION >= '3'
169
197
  # Join the array or set.
170
- def array_or_set_join(obj, arg)
198
+ #
199
+ # This method is deprecated and will be removed in Sequel 6.1.
200
+ def array_or_set_join(obj, arg) # SEQUEL6.1: Remove
171
201
  obj.join(arg)
172
202
  end
173
203
  # simplecov:disable
@@ -196,14 +226,22 @@ module Sequel
196
226
 
197
227
  # Convert given object to json and return the result.
198
228
  # This can be overridden to use an alternative json implementation.
199
- def object_to_json(obj, *args, &block)
229
+ #
230
+ # This method is deprecated and will be removed in Sequel 6.1.
231
+ def object_to_json(obj, *args, &block) # SEQUEL6.1: Remove
200
232
  obj.to_json(*args, &block)
201
233
  end
202
234
 
203
235
  # Parse the string as JSON and return the result.
204
236
  # This can be overridden to use an alternative json implementation.
205
- def parse_json(json)
206
- JSON.parse(json, :create_additions=>false)
237
+ #
238
+ # This method is deprecated and will be removed in Sequel 6.1.
239
+ def parse_json(json) # SEQUEL6.1: Remove
240
+ if JSON::VERSION >= '3'
241
+ JSON.parse(json)
242
+ else
243
+ JSON.parse(json, :create_additions=>false)
244
+ end
207
245
  end
208
246
 
209
247
  # If a mutex is given, synchronize access using it. If nil is given, just
@@ -249,7 +287,7 @@ module Sequel
249
287
  # For tables, these parts are the schema, table, and alias.
250
288
  def split_symbol(sym)
251
289
  # SEQUEL6.1: Remove
252
- unless v = Sequel.synchronize{SPLIT_SYMBOL_CACHE[sym]}
290
+ unless v = Sequel.synchronize{SPLIT_SYMBOL_CACHE_[sym]}
253
291
  if split_symbols?
254
292
  v = case s = sym.to_s
255
293
  when /\A((?:(?!__).)+)__((?:(?!___).)+)___(.+)\z/
@@ -264,7 +302,7 @@ module Sequel
264
302
  else
265
303
  v = [nil,sym.to_s.freeze,nil].freeze
266
304
  end
267
- Sequel.synchronize{SPLIT_SYMBOL_CACHE[sym] = v}
305
+ Sequel.synchronize{SPLIT_SYMBOL_CACHE_[sym] = v}
268
306
  end
269
307
  v
270
308
  end
@@ -300,8 +338,8 @@ module Sequel
300
338
  # Sequel.expr{table__column} # table__column
301
339
  # Sequel.expr{table[:column]} # table.column
302
340
  def split_symbols=(v)
303
- # SEQUEL6: Remove
304
- Sequel.synchronize{SPLIT_SYMBOL_CACHE.clear}
341
+ Sequel::Deprecation.deprecate("Sequel.split_symbols= is deprecated and will be removed in Sequel 6.")
342
+ Sequel.synchronize{SPLIT_SYMBOL_CACHE_.clear}
305
343
  @split_symbols = v
306
344
  end
307
345
 
@@ -324,7 +362,9 @@ module Sequel
324
362
  # value of <tt>Sequel.datetime_class</tt>.
325
363
  #
326
364
  # Sequel.string_to_datetime('2010-09-10 10:20:30') # Time.local(2010, 09, 10, 10, 20, 30)
327
- def string_to_datetime(string)
365
+ #
366
+ # This method is deprecated and will be removed in Sequel 6.1.
367
+ def string_to_datetime(string) # SEQUEL6.1: Remove
328
368
  if datetime_class == DateTime
329
369
  DateTime.parse(string, convert_two_digit_years)
330
370
  else
@@ -356,7 +396,10 @@ module Sequel
356
396
  if RUBY_VERSION >= '2.1'
357
397
  # A timer object that can be passed to Sequel.elapsed_seconds_since
358
398
  # to return the number of seconds elapsed.
359
- def start_timer
399
+ #
400
+ # This method is deprecated and will be removed in Sequel 6.1 (or
401
+ # potentially in 6.0 if Ruby 2.1 support is dropped before 6.0).
402
+ def start_timer # SEQUEL6.1: Remove
360
403
  Process.clock_gettime(Process::CLOCK_MONOTONIC)
361
404
  end
362
405
  else
@@ -369,7 +412,10 @@ module Sequel
369
412
 
370
413
  # The elapsed seconds since the given timer object was created. The
371
414
  # timer object should have been created via Sequel.start_timer.
372
- def elapsed_seconds_since(timer)
415
+ #
416
+ # This method is deprecated and will be removed in Sequel 6.1 (or
417
+ # potentially in 6.0 if Ruby 2.1 support is dropped before 6.0).
418
+ def elapsed_seconds_since(timer) # SEQUEL6.1: Remove
373
419
  start_timer - timer
374
420
  end
375
421
 
@@ -481,4 +527,6 @@ module Sequel
481
527
 
482
528
  # Add the database adapter class methods to Sequel via metaprogramming
483
529
  def_adapter_method(*Database::ADAPTERS)
530
+
531
+ Deprecation.deprecate_constant(self, :SPLIT_SYMBOL_CACHE)
484
532
  end
@@ -229,12 +229,7 @@ module Sequel
229
229
  end
230
230
 
231
231
  # Disallow dup/clone for Database instances
232
- undef_method :dup, :clone, :initialize_copy
233
- # simplecov:disable
234
- if RUBY_VERSION >= '1.9.3'
235
- # simplecov:enable
236
- undef_method :initialize_clone, :initialize_dup
237
- end
232
+ undef_method :dup, :clone, :initialize_copy, :initialize_clone, :initialize_dup
238
233
 
239
234
  # Cast the given type to a literal type
240
235
  #
@@ -170,18 +170,18 @@ module Sequel
170
170
  # :engine :: The table engine to use for the table.
171
171
  #
172
172
  # PostgreSQL specific options:
173
- # :on_commit :: Either :preserve_rows (default), :drop or :delete_rows. Should
174
- # only be specified when creating a temporary table.
175
173
  # :foreign :: Create a foreign table. The value should be the name of the
176
174
  # foreign server that was specified in CREATE SERVER.
177
175
  # :inherits :: Inherit from a different table. An array can be
178
176
  # specified to inherit from multiple tables.
179
- # :unlogged :: Create the table as an unlogged table.
177
+ # :on_commit :: Either :preserve_rows (default), :drop or :delete_rows. Should
178
+ # only be specified when creating a temporary table.
180
179
  # :options :: The OPTIONS clause to use for foreign tables. Should be a hash
181
180
  # where keys are option names and values are option values. Note
182
181
  # that option names are unquoted, so you should not use untrusted
183
182
  # keys.
184
183
  # :tablespace :: The tablespace to use for the table.
184
+ # :unlogged :: Create the table as an unlogged table.
185
185
  #
186
186
  # SQLite specific options:
187
187
  # :strict :: Create a STRICT table, which checks that the values for the columns
@@ -374,9 +374,7 @@ module Sequel
374
374
 
375
375
  # Whether to commit the current transaction. Thread.current.status is
376
376
  # checked because Thread#kill skips rescue blocks (so exception would be
377
- # nil), but the transaction should still be rolled back. On Ruby 1.9 (but
378
- # not 2.0+), the thread status will still be "run", so Thread#kill
379
- # will erroneously commit the transaction, and there isn't a workaround.
377
+ # nil), but the transaction should still be rolled back.
380
378
  def commit_or_rollback_transaction(exception, conn, opts)
381
379
  if exception
382
380
  false
@@ -242,7 +242,7 @@ module Sequel
242
242
  end
243
243
  when 1
244
244
  arg = args[0]
245
- if arg.is_a?(Integer)
245
+ if arg.is_a?(Integer) && arg >= 0
246
246
  res = if block
247
247
  if loader = cached_placeholder_literalizer(:_first_integer_cond_loader) do |pl|
248
248
  where(pl.arg).limit(pl.arg)
@@ -1346,10 +1346,21 @@ module Sequel
1346
1346
  alias delete_returning_sql insert_returning_sql
1347
1347
  alias update_returning_sql insert_returning_sql
1348
1348
 
1349
- # SQL fragment specifying a JOIN type, converts underscores to
1350
- # spaces and upcases.
1349
+ JOIN_TYPE_SQL = {}
1350
+ (CONDITIONED_JOIN_TYPES + UNCONDITIONED_JOIN_TYPES + %i[natural_inner natural_left_outer natural_right_outer natural_full_outer]).each do |join_type|
1351
+ JOIN_TYPE_SQL[join_type] = "#{join_type.to_s.tr('_', ' ').upcase} JOIN".freeze
1352
+ end
1353
+ JOIN_TYPE_SQL[nil] = "JOIN"
1354
+ JOIN_TYPE_SQL.freeze
1355
+ private_constant :JOIN_TYPE_SQL
1356
+
1357
+ # SQL fragment for join type
1351
1358
  def join_type_sql(join_type)
1352
- "#{join_type.to_s.tr('_', ' ').upcase} JOIN"
1359
+ JOIN_TYPE_SQL.fetch(join_type) do
1360
+ # SEQUEL6: Raise error
1361
+ Sequel::Deprecation.deprecate("Unrecognized join type used: #{join_type.inspect}. This will raise an error starting in Sequel 6.")
1362
+ "#{join_type.to_s.tr('_', ' ').upcase} JOIN"
1363
+ end
1353
1364
  end
1354
1365
 
1355
1366
  # Append USING clause for JOIN USING
@@ -10,10 +10,7 @@
10
10
  #
11
11
  # using Sequel::CoreRefinements
12
12
 
13
- # simplecov:disable
14
- raise(Sequel::Error, "Refinements require ruby 2.0.0 or greater") unless RUBY_VERSION >= '2.0.0'
15
- # simplecov:enable
16
-
13
+ #
17
14
  module Sequel::CoreRefinements
18
15
  # simplecov:disable
19
16
  include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
@@ -38,7 +38,7 @@ module Sequel
38
38
  private
39
39
 
40
40
  # Literalize custom DateTime subclass objects as CURRENT_TIMESTAMP.
41
- def literal_datetime_append(sql, v)
41
+ def literal_datetime_append(sql, v) # SEQUEL6: Remove
42
42
  v.is_a?(DateTime) ? literal_append(sql, Sequel::CURRENT_TIMESTAMP) : super
43
43
  end
44
44
 
@@ -52,7 +52,7 @@ module Sequel
52
52
  class Time < ::Time; end
53
53
 
54
54
  # DateTime subclass literalized as CURRENT_TIMESTAMP
55
- class DateTime < ::DateTime; end
55
+ class DateTime < ::DateTime; end # SEQUEL6.1: Remove
56
56
  end
57
57
 
58
58
  Dataset.register_extension(:current_datetime_timestamp, CurrentDateTimeTimestamp::DatasetMethods)
@@ -40,9 +40,7 @@
40
40
 
41
41
  module Sequel
42
42
  module DuplicateColumnsHandler
43
- # simplecov:disable
44
- CALLER_ARGS = (RUBY_VERSION >= '2.0' ? [0,1] : [0]).freeze
45
- # simplecov:enable
43
+ CALLER_ARGS = [0,1].freeze
46
44
 
47
45
  # Customize handling of duplicate columns for this dataset.
48
46
  def on_duplicate_columns(handler = (raise Error, "Must provide either an argument or a block to on_duplicate_columns" unless defined?(yield); nil), &block)
@@ -63,6 +63,20 @@ module Sequel
63
63
  class Error < Sequel::Error
64
64
  end
65
65
 
66
+ module BooleanExpressionClassMethods
67
+ private
68
+
69
+ # Do not freeze literal strings in value pairs, so they don't skip
70
+ # the frozen checks.
71
+ def from_value_pair(l, r)
72
+ if LiteralString === r
73
+ new(:'=', l, r)
74
+ else
75
+ super
76
+ end
77
+ end
78
+ end
79
+
66
80
  module DatabaseMethods
67
81
  def self.extended(db)
68
82
  db.extend_datasets(DatasetMethods)
@@ -105,7 +119,7 @@ module Sequel
105
119
  def _check_unfrozen_literal_string(str)
106
120
  return if !str.is_a?(String) || str.frozen?
107
121
 
108
- if str.is_a?(LiteralString)
122
+ if str.is_a?(LiteralString) && str == str.source
109
123
  _check_unfrozen_literal_string(str.source)
110
124
  else
111
125
  raise Error, "cannot treat unfrozen string as literal SQL: #{str.inspect}"
@@ -126,6 +140,8 @@ module Sequel
126
140
  end
127
141
  end
128
142
 
143
+ SQL::BooleanExpression.extend(LitRequireFrozen::BooleanExpressionClassMethods)
144
+
129
145
  Dataset.register_extension(:lit_require_frozen, LitRequireFrozen::DatasetMethods)
130
146
  Database.register_extension(:lit_require_frozen, LitRequireFrozen::DatabaseMethods)
131
147
  end
@@ -1,17 +1,17 @@
1
1
  # frozen-string-literal: true
2
2
  #
3
3
  # Allows the use of named timezones via TZInfo (requires tzinfo).
4
- # Forces the use of DateTime as Sequel's datetime_class, since
4
+ # Forces the use of DateTime as Sequel's datetime_class by default, since
5
5
  # historically, Ruby's Time class doesn't support timezones other
6
6
  # than local and UTC. To continue using Ruby's Time class when using
7
- # the named_timezones extension:
7
+ # the named_timezones extension, set the
8
+ # +SEQUEL_NAMED_TIMEZONES_USE_TIME+ environment variable before
9
+ # loading the extension:
8
10
  #
9
11
  # # Load the extension
12
+ # ENV['SEQUEL_NAMED_TIMEZONES_USE_TIME'] = "1"
10
13
  # Sequel.extension :named_timezones
11
14
  #
12
- # # Set Sequel.datetime_class back to Time
13
- # Sequel.datetime_class = Time
14
- #
15
15
  # This allows you to either pass strings or TZInfo::Timezone
16
16
  # instance to Sequel.database_timezone=, application_timezone=, and
17
17
  # typecast_timezone=. If a string is passed, it is converted to a
@@ -49,7 +49,9 @@ require 'tzinfo'
49
49
 
50
50
  #
51
51
  module Sequel
52
- self.datetime_class = DateTime
52
+ # simplecov:disable
53
+ self.datetime_class = DateTime unless ENV["SEQUEL_NAMED_TIMEZONES_USE_TIME"]
54
+ # simplecov:enable
53
55
 
54
56
  module NamedTimezones
55
57
  module DatabaseMethods
@@ -69,7 +71,7 @@ module Sequel
69
71
 
70
72
  if RUBY_VERSION >= '2.6'
71
73
  # Whether Time.at with :nsec and :in is broken. True on JRuby < 9.3.9.0.
72
- BROKEN_TIME_AT_WITH_NSEC = defined?(JRUBY_VERSION) && (JRUBY_VERSION < '9.3' || (JRUBY_VERSION < '9.4' && JRUBY_VERSION.split('.')[2].to_i < 9))
74
+ BROKEN_TIME_AT_WITH_NSEC = defined?(JRUBY_VERSION) && (JRUBY_VERSION.to_r < Rational('9.3') || (JRUBY_VERSION.to_r < Rational('9.4') && JRUBY_VERSION.split('.')[2].to_i < 9))
73
75
  private_constant :BROKEN_TIME_AT_WITH_NSEC
74
76
 
75
77
  # Convert the given input Time (which must be in UTC) to the given input timezone,
@@ -390,6 +390,7 @@ module Sequel
390
390
  elsif char == '{'
391
391
  raise Sequel::Error, "invalid array, opening brace with existing recorded data" unless @recorded.empty?
392
392
 
393
+ raise Sequel::Error, "cannot parse array with more than 6 dimensions" if @stack.length >= 6
393
394
  # Start of new array, add it to the stack
394
395
  new = []
395
396
  @stack.last << new
@@ -984,7 +984,8 @@ module Sequel
984
984
  comma = true
985
985
  end
986
986
  ds.literal_append(sql, v)
987
- sql << " AS " << k.to_s
987
+ sql << " AS "
988
+ ds.send(:identifier_append, sql, k)
988
989
  end
989
990
  end
990
991
  end
@@ -1254,7 +1255,8 @@ module Sequel
1254
1255
  comma = true
1255
1256
  end
1256
1257
  ds.literal_append(sql, v)
1257
- sql << " AS " << k.to_s
1258
+ sql << " AS "
1259
+ ds.send(:identifier_append, sql, k)
1258
1260
  end
1259
1261
  end
1260
1262
 
@@ -10,7 +10,11 @@
10
10
  #
11
11
  # DB.loose_count(Sequel[:schema][:table]) # => 123456
12
12
  #
13
- # How accurate this count is depends on the number of rows
13
+ # To get the loose count of all tables in a given schema:
14
+ #
15
+ # DB.loose_counts(:schema) # => {table: 123456, ...}
16
+ #
17
+ # How accurate these counts are depends on the number of rows
14
18
  # added/deleted from the table since the last time it was
15
19
  # analyzed. If the table has not been vacuumed or analyzed
16
20
  # yet, this can return 0 or -1 depending on the PostgreSQL
@@ -31,9 +35,40 @@ module Sequel
31
35
  def loose_count(table)
32
36
  from(:pg_class).where(:oid=>regclass_oid(table)).get(Sequel.cast(:reltuples, Integer))
33
37
  end
38
+
39
+ # Look at the table statistics for the given schema and return a
40
+ # hash with table name keys and approximate counts. Results include
41
+ # normal tables, materialized views, and partitioned tables.
42
+ def loose_counts(schema)
43
+ case schema
44
+ when Symbol
45
+ schema = schema.to_s
46
+ when String
47
+ nil
48
+ when SQL::Identifier
49
+ schema = schema.value.to_s
50
+ else
51
+ raise Error, "unsupported argument type, should be symbol, string, or Sequel::SQL::Identifier, given #{schema.inspect}"
52
+ end
53
+
54
+ namespace_oid = if server_version >= 90500
55
+ Sequel.function(:to_regnamespace, schema).cast(:oid)
56
+ else
57
+ from(:pg_namespace).where(nspname: schema).select(:oid)
58
+ end
59
+
60
+ hash = {}
61
+ from(:pg_class).
62
+ where(relnamespace: namespace_oid, relkind: %w"r m p").
63
+ order(:relname).
64
+ select_map([:relname, Sequel.cast(:reltuples, Integer).as(:v)]).
65
+ each do |k, v|
66
+ hash[k.to_sym] = v
67
+ end
68
+ hash
69
+ end
34
70
  end
35
71
  end
36
72
 
37
73
  Database.register_extension(:pg_loose_count, Postgres::LooseCount)
38
74
  end
39
-
@@ -29,8 +29,7 @@
29
29
  #
30
30
  # Object.send(:include, Sequel::S)
31
31
  #
32
- # If you are using Ruby 2+, and you would like to use refinements, you
33
- # can use Sequel::S as a refinement, in which case the private #S method
32
+ # You can use also Sequel::S as a refinement, in which case the private #S method
34
33
  # will be available on all objects while the refinement is active.
35
34
  #
36
35
  # using Sequel::S
@@ -39,7 +38,6 @@
39
38
  #
40
39
  # Related module: Sequel::S
41
40
 
42
-
43
41
  #
44
42
  module Sequel::S
45
43
  private
@@ -50,11 +48,9 @@ module Sequel::S
50
48
  end
51
49
 
52
50
  # simplecov:disable
53
- if RUBY_VERSION >= '2.0.0'
54
- include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
51
+ include_meth = RUBY_VERSION >= '3.1' ? :import_methods : :include
55
52
  # simplecov:enable
56
- refine Object do
57
- send include_meth, Sequel::S
58
- end
53
+ refine Object do
54
+ send include_meth, Sequel::S
59
55
  end
60
56
  end
@@ -200,8 +200,12 @@ END_MIG
200
200
 
201
201
  # Recreate the column in the passed Schema::CreateTableGenerator from the given name and parsed database schema.
202
202
  def recreate_column(name, schema, gen, options)
203
+ db_type = schema[:db_type]
204
+ db_type = literal(db_type) if options[:same_db] && database_type == :sqlite
205
+
203
206
  if options[:single_pk] && schema_autoincrementing_primary_key?(schema)
204
- type_hash = options[:same_db] ? {:type=>schema[:db_type]} : column_schema_to_ruby_type(schema)
207
+ type_hash = options[:same_db] ? {:type=>db_type} : column_schema_to_ruby_type(schema)
208
+
205
209
  [:table, :key, :on_delete, :on_update, :deferrable].each{|f| type_hash[f] = schema[f] if schema[f]}
206
210
  if type_hash == {:type=>Integer} || type_hash == {:type=>"integer"} || type_hash == {:type=>"INTEGER"}
207
211
  type_hash.delete(:type)
@@ -220,7 +224,7 @@ END_MIG
220
224
  end
221
225
  else
222
226
  col_opts = if options[:same_db]
223
- h = {:type=>schema[:db_type]}
227
+ h = {:type=>db_type}
224
228
  if database_type == :mysql && h[:type].start_with?("timestamp")
225
229
  h[:null] = true
226
230
  end
@@ -84,10 +84,6 @@
84
84
  # # SELECT * FROM albums -- model:Album,action:all -- Some Comment
85
85
  # end
86
86
  #
87
- # Note that Microsoft Access does not support inline comments,
88
- # and attempting to use comments on it will result in SQL syntax
89
- # errors.
90
- #
91
87
  # Related modules: Sequel::SQLComments, Sequel::Database::SQLComments
92
88
 
93
89
  #