sequel 4.48.0 → 4.49.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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +56 -0
  3. data/doc/advanced_associations.rdoc +1 -1
  4. data/doc/opening_databases.rdoc +3 -2
  5. data/doc/release_notes/4.49.0.txt +222 -0
  6. data/lib/sequel/adapters/ibmdb.rb +6 -1
  7. data/lib/sequel/adapters/jdbc.rb +3 -1
  8. data/lib/sequel/adapters/jdbc/h2.rb +10 -1
  9. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
  10. data/lib/sequel/adapters/jdbc/sqlserver.rb +9 -2
  11. data/lib/sequel/adapters/mock.rb +3 -0
  12. data/lib/sequel/adapters/mysql2.rb +1 -1
  13. data/lib/sequel/adapters/postgres.rb +2 -1
  14. data/lib/sequel/adapters/shared/mysql.rb +4 -1
  15. data/lib/sequel/adapters/shared/oracle.rb +26 -3
  16. data/lib/sequel/connection_pool.rb +9 -2
  17. data/lib/sequel/connection_pool/sharded_single.rb +1 -1
  18. data/lib/sequel/connection_pool/sharded_threaded.rb +1 -1
  19. data/lib/sequel/connection_pool/single.rb +2 -2
  20. data/lib/sequel/connection_pool/threaded.rb +2 -2
  21. data/lib/sequel/database/connecting.rb +3 -3
  22. data/lib/sequel/database/dataset_defaults.rb +14 -1
  23. data/lib/sequel/dataset.rb +1 -1
  24. data/lib/sequel/dataset/actions.rb +54 -0
  25. data/lib/sequel/dataset/dataset_module.rb +58 -0
  26. data/lib/sequel/dataset/query.rb +3 -3
  27. data/lib/sequel/exceptions.rb +8 -0
  28. data/lib/sequel/extensions/_model_pg_row.rb +5 -2
  29. data/lib/sequel/extensions/current_datetime_timestamp.rb +2 -1
  30. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  31. data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -2
  32. data/lib/sequel/extensions/migration.rb +5 -2
  33. data/lib/sequel/extensions/null_dataset.rb +1 -0
  34. data/lib/sequel/model/associations.rb +3 -0
  35. data/lib/sequel/model/base.rb +10 -55
  36. data/lib/sequel/model/dataset_module.rb +5 -43
  37. data/lib/sequel/model/errors.rb +2 -1
  38. data/lib/sequel/model/inflections.rb +17 -5
  39. data/lib/sequel/plugins/active_model.rb +2 -2
  40. data/lib/sequel/plugins/class_table_inheritance.rb +1 -0
  41. data/lib/sequel/plugins/composition.rb +2 -2
  42. data/lib/sequel/plugins/dataset_associations.rb +25 -13
  43. data/lib/sequel/plugins/json_serializer.rb +2 -2
  44. data/lib/sequel/plugins/pg_row.rb +4 -2
  45. data/lib/sequel/plugins/serialization.rb +1 -0
  46. data/lib/sequel/plugins/single_table_inheritance.rb +6 -1
  47. data/lib/sequel/plugins/touch.rb +2 -1
  48. data/lib/sequel/plugins/validation_helpers.rb +10 -2
  49. data/lib/sequel/sql.rb +16 -7
  50. data/lib/sequel/version.rb +1 -1
  51. data/spec/adapters/mssql_spec.rb +4 -4
  52. data/spec/adapters/mysql_spec.rb +5 -1
  53. data/spec/adapters/oracle_spec.rb +4 -0
  54. data/spec/bin_spec.rb +7 -1
  55. data/spec/core/connection_pool_spec.rb +28 -14
  56. data/spec/core/database_spec.rb +149 -0
  57. data/spec/core/dataset_spec.rb +173 -0
  58. data/spec/extensions/class_table_inheritance_spec.rb +58 -17
  59. data/spec/extensions/composition_spec.rb +13 -0
  60. data/spec/extensions/dataset_associations_spec.rb +12 -0
  61. data/spec/extensions/many_through_many_spec.rb +4 -4
  62. data/spec/extensions/null_dataset_spec.rb +1 -1
  63. data/spec/extensions/serialization_spec.rb +1 -1
  64. data/spec/extensions/single_table_inheritance_spec.rb +16 -0
  65. data/spec/extensions/validation_helpers_spec.rb +1 -2
  66. data/spec/integration/associations_test.rb +8 -0
  67. data/spec/integration/plugin_test.rb +8 -3
  68. data/spec/model/association_reflection_spec.rb +1 -1
  69. data/spec/model/associations_spec.rb +29 -9
  70. data/spec/model/class_dataset_methods_spec.rb +6 -0
  71. data/spec/model/eager_loading_spec.rb +8 -8
  72. data/spec/model/plugins_spec.rb +34 -0
  73. data/spec/model/record_spec.rb +1 -1
  74. data/spec/spec_config.rb +2 -0
  75. metadata +5 -2
@@ -260,7 +260,7 @@ module Sequel
260
260
 
261
261
  # Use streaming to implement paging if Mysql2 supports it.
262
262
  def paged_each(opts=OPTS, &block)
263
- if STREAMING_SUPPORTED
263
+ if STREAMING_SUPPORTED && opts[:stream] != false
264
264
  stream.each(&block)
265
265
  else
266
266
  super
@@ -218,7 +218,8 @@ module Sequel
218
218
  :user => opts[:user],
219
219
  :password => opts[:password],
220
220
  :connect_timeout => opts[:connect_timeout] || 20,
221
- :sslmode => opts[:sslmode]
221
+ :sslmode => opts[:sslmode],
222
+ :sslrootcert => opts[:sslrootcert]
222
223
  }.delete_if { |key, value| blank_object?(value) }
223
224
  connection_params.merge!(opts[:driver_options]) if opts[:driver_options]
224
225
  conn = Adapter.connect(connection_params)
@@ -841,7 +841,10 @@ module Sequel
841
841
  # Transforms an CROSS JOIN to an INNER JOIN if the expr is not nil.
842
842
  # Raises an error on use of :full_outer type, since MySQL doesn't support it.
843
843
  def join_table(type, table, expr=nil, opts=OPTS, &block)
844
- type = :inner if (type == :cross) && !expr.nil?
844
+ if (type == :cross) && !expr.nil?
845
+ Sequel::Deprecation.deprecate(":cross join type with conditions being converted to INNER JOIN on MySQL", "Use :inner join type instead")
846
+ type = :inner
847
+ end
845
848
  raise(Sequel::Error, "MySQL doesn't support FULL OUTER JOIN or NATURAL FULL JOIN") if type == :full_outer || type == :natural_full
846
849
  super(type, table, expr, opts, &block)
847
850
  end
@@ -348,7 +348,7 @@ module Sequel
348
348
  Sequel::Deprecation.deprecate_constant(self, :SKIP_LOCKED)
349
349
 
350
350
  include(Module.new do
351
- Dataset.def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order lock')
351
+ Dataset.def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order limit lock')
352
352
  end)
353
353
 
354
354
  def complex_expression_sql_append(sql, op, args)
@@ -421,7 +421,10 @@ module Sequel
421
421
  # Handle LIMIT by using a unlimited subselect filtered with ROWNUM.
422
422
  def select_sql
423
423
  return super if @opts[:sql]
424
- if o = @opts[:offset]
424
+ return super if supports_fetch_next_rows?
425
+
426
+ o = @opts[:offset]
427
+ if o && o != 0
425
428
  columns = clone(:append_sql=>String.new, :placeholder_literal_null=>true).columns
426
429
  dsa1 = dataset_alias(1)
427
430
  rn = row_number_column
@@ -437,7 +440,7 @@ module Sequel
437
440
  subselect_sql_append(sql, ds)
438
441
  sql
439
442
  elsif limit = @opts[:limit]
440
- ds = clone(:limit=>nil)
443
+ ds = unlimited
441
444
  # Lock doesn't work in subselects, so don't use a subselect when locking.
442
445
  # Don't use a subselect if custom SQL is used, as it breaks somethings.
443
446
  ds = ds.from_self unless @opts[:lock]
@@ -449,6 +452,21 @@ module Sequel
449
452
  end
450
453
  end
451
454
 
455
+ def select_limit_sql(sql)
456
+ return unless supports_fetch_next_rows?
457
+
458
+ if offset = @opts[:offset]
459
+ sql << " OFFSET "
460
+ literal_append(sql, offset)
461
+ sql << " ROWS"
462
+ end
463
+
464
+ if limit = @opts[:limit]
465
+ sql << " FETCH NEXT "
466
+ literal_append(sql, limit)
467
+ sql << " ROWS ONLY"
468
+ end
469
+ end
452
470
  # Oracle requires recursive CTEs to have column aliases.
453
471
  def recursive_cte_requires_column_aliases?
454
472
  true
@@ -463,6 +481,11 @@ module Sequel
463
481
  false
464
482
  end
465
483
 
484
+ # Oracle supports FETCH NEXT ROWS since 12c
485
+ def supports_fetch_next_rows?
486
+ server_version >= 12000000 && !(@opts[:lock] || @opts[:skip_locked])
487
+ end
488
+
466
489
  # Oracle supports GROUP BY CUBE
467
490
  def supports_group_cube?
468
491
  true
@@ -29,12 +29,15 @@ class Sequel::ConnectionPool
29
29
 
30
30
  # The default server to use
31
31
  DEFAULT_SERVER = :default
32
+ Sequel::Deprecation.deprecate_constant(self, :DEFAULT_SERVER)
32
33
 
33
34
  # A map of [single threaded, sharded] values to symbols or ConnectionPool subclasses.
34
35
  CONNECTION_POOL_MAP = {[true, false] => :single,
35
36
  [true, true] => :sharded_single,
36
37
  [false, false] => :threaded,
37
38
  [false, true] => :sharded_threaded}
39
+ CONNECTION_POOL__MAP = CONNECTION_POOL_MAP
40
+ Sequel::Deprecation.deprecate_constant(self, :CONNECTION_POOL_MAP)
38
41
 
39
42
  # Class methods used to return an appropriate pool subclass, separated
40
43
  # into a module for easier overridding by extensions.
@@ -57,7 +60,10 @@ class Sequel::ConnectionPool
57
60
 
58
61
  # Return a connection pool class based on the given options.
59
62
  def connection_pool_class(opts)
60
- CONNECTION_POOL_MAP[opts[:pool_class]] || opts[:pool_class] || CONNECTION_POOL_MAP[[!!opts[:single_threaded], !!opts[:servers]]]
63
+ if opts[:pool_class] && !opts[:pool_class].is_a?(Class) && ![:threaded, :single, :sharded_threaded, :sharded_single].include?(opts[:pool_class])
64
+ Sequel::Deprecation.deprecate("Using an unrecognized :pool_class option", "Use a class for the :pool_class option to select a custom pool class, or one of the following symbols for one of the default pool classes: :threaded, :single, :sharded_threaded, :sharded_single")
65
+ end
66
+ CONNECTION_POOL__MAP[opts[:pool_class]] || opts[:pool_class] || CONNECTION_POOL__MAP[[!!opts[:single_threaded], !!opts[:servers]]]
61
67
  end
62
68
  end
63
69
  extend ClassMethods
@@ -89,12 +95,13 @@ class Sequel::ConnectionPool
89
95
 
90
96
  # Alias for +size+, not aliased directly for ease of subclass implementation
91
97
  def created_count(*args)
98
+ Sequel::Deprecation.deprecate("Sequel::ConnectionPool#created_count", "Use #size instead")
92
99
  size(*args)
93
100
  end
94
101
 
95
102
  # An array of symbols for all shards/servers, which is a single <tt>:default</tt> by default.
96
103
  def servers
97
- [DEFAULT_SERVER]
104
+ [:default]
98
105
  end
99
106
 
100
107
  private
@@ -111,5 +111,5 @@ class Sequel::ShardedSingleConnectionPool < Sequel::ConnectionPool
111
111
  servers.each{|s| hold(s){}}
112
112
  end
113
113
 
114
- CONNECTION_POOL_MAP[[true, true]] = self
114
+ CONNECTION_POOL__MAP[[true, true]] = self
115
115
  end
@@ -353,5 +353,5 @@ class Sequel::ShardedThreadedConnectionPool < Sequel::ThreadedConnectionPool
353
353
  disconnect_connection(conn)
354
354
  end
355
355
 
356
- CONNECTION_POOL_MAP[[false, true]] = self
356
+ CONNECTION_POOL__MAP[[false, true]] = self
357
357
  end
@@ -26,7 +26,7 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
26
26
  def hold(server=nil)
27
27
  begin
28
28
  unless c = @conn.first
29
- @conn.replace([c = make_new(DEFAULT_SERVER)])
29
+ @conn.replace([c = make_new(:default)])
30
30
  end
31
31
  yield c
32
32
  rescue Sequel::DatabaseDisconnectError, *@error_classes => e
@@ -57,5 +57,5 @@ class Sequel::SingleConnectionPool < Sequel::ConnectionPool
57
57
  hold{}
58
58
  end
59
59
 
60
- CONNECTION_POOL_MAP[[true, false]] = self
60
+ CONNECTION_POOL__MAP[[true, false]] = self
61
61
  end
@@ -198,7 +198,7 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
198
198
  # available, tries to create a new connection. The calling code should already
199
199
  # have the mutex before calling this.
200
200
  def available
201
- next_available || make_new(DEFAULT_SERVER)
201
+ next_available || make_new(:default)
202
202
  end
203
203
 
204
204
  # Return a connection to the pool of available connections, returns the connection.
@@ -282,5 +282,5 @@ class Sequel::ThreadedConnectionPool < Sequel::ConnectionPool
282
282
  @mutex.synchronize{yield}
283
283
  end
284
284
 
285
- CONNECTION_POOL_MAP[[false, false]] = self
285
+ CONNECTION_POOL__MAP[[false, false]] = self
286
286
  end
@@ -220,14 +220,14 @@ module Sequel
220
220
 
221
221
  # Disconnects all available connections from the connection pool. Any
222
222
  # connections currently in use will not be disconnected. Options:
223
- # :servers :: Should be a symbol specifing the server to disconnect from,
223
+ # :server :: Should be a symbol specifing the server to disconnect from,
224
224
  # or an array of symbols to specify multiple servers.
225
225
  #
226
226
  # Example:
227
227
  #
228
228
  # DB.disconnect # All servers
229
- # DB.disconnect(:servers=>:server1) # Single server
230
- # DB.disconnect(:servers=>[:server1, :server2]) # Multiple servers
229
+ # DB.disconnect(:server=>:server1) # Single server
230
+ # DB.disconnect(:server=>[:server1, :server2]) # Multiple servers
231
231
  def disconnect(opts = OPTS)
232
232
  pool.disconnect(opts)
233
233
  end
@@ -69,6 +69,9 @@ module Sequel
69
69
  # This allows you to override any of the dataset methods even if they are
70
70
  # defined directly on the dataset class that this Database object uses.
71
71
  #
72
+ # If a block is given, a Dataset::DatasetModule instance is created, allowing
73
+ # for the easy creation of named dataset methods that will do caching.
74
+ #
72
75
  # Examples:
73
76
  #
74
77
  # # Introspec columns for all of DB's datasets
@@ -82,9 +85,19 @@ module Sequel
82
85
  # super
83
86
  # end
84
87
  # end
88
+ #
89
+ # # Add some named dataset methods
90
+ # DB.extend_datasets do
91
+ # order :by_id, :id
92
+ # select :with_id_and_name, :id, :name
93
+ # where :active, :active
94
+ # end
95
+ #
96
+ # DB[:table].active.with_id_and_name.by_id
97
+ # # SELECT id, name FROM table WHERE active ORDER BY id
85
98
  def extend_datasets(mod=nil, &block)
86
99
  raise(Error, "must provide either mod or block, not both") if mod && block
87
- mod = Module.new(&block) if block
100
+ mod = Dataset::DatasetModule.new(&block) if block
88
101
  if @dataset_modules.empty?
89
102
  @dataset_modules = [mod]
90
103
  @dataset_class = Class.new(@dataset_class)
@@ -42,5 +42,5 @@ module Sequel
42
42
  include SQL::StringMethods
43
43
  end
44
44
 
45
- require(%w"query actions features graph prepared_statements misc mutation sql placeholder_literalizer", 'dataset')
45
+ require(%w"query actions features graph prepared_statements misc mutation sql placeholder_literalizer dataset_module", 'dataset')
46
46
  end
@@ -15,6 +15,7 @@ module Sequel
15
15
  empty? fetch_rows first first! get import insert interval last
16
16
  map max min multi_insert paged_each range select_hash select_hash_groups select_map select_order_map
17
17
  single_record single_record! single_value single_value! sum to_hash to_hash_groups truncate update
18
+ where_all where_each where_single_value
18
19
  METHS
19
20
  # SEQUEL5: Remove interval, range
20
21
 
@@ -917,6 +918,52 @@ module Sequel
917
918
  end
918
919
  end
919
920
 
921
+ # Return an array of all rows matching the given filter condition, also
922
+ # yielding each row to the given block. Basically the same as where(cond).all(&block),
923
+ # except it can be optimized to not create an intermediate dataset.
924
+ #
925
+ # DB[:table].where_all(:id=>[1,2,3])
926
+ # # SELECT * FROM table WHERE (id IN (1, 2, 3))
927
+ def where_all(cond, &block)
928
+ if loader = _where_loader
929
+ loader.all(filter_expr(cond), &block)
930
+ else
931
+ where(cond).all(&block)
932
+ end
933
+ end
934
+
935
+ # Iterate over all rows matching the given filter condition,
936
+ # yielding each row to the given block. Basically the same as where(cond).each(&block),
937
+ # except it can be optimized to not create an intermediate dataset.
938
+ #
939
+ # DB[:table].where_each(:id=>[1,2,3]){|row| p row}
940
+ # # SELECT * FROM table WHERE (id IN (1, 2, 3))
941
+ def where_each(cond, &block)
942
+ if loader = _where_loader
943
+ loader.each(filter_expr(cond), &block)
944
+ else
945
+ where(cond).each(&block)
946
+ end
947
+ end
948
+
949
+ # Filter the datasets using the given filter condition, then return a single value.
950
+ # This assumes that the dataset has already been setup to limit the selection to
951
+ # a single column. Basically the same as where(cond).single_value,
952
+ # except it can be optimized to not create an intermediate dataset.
953
+ #
954
+ # DB[:table].select(:name).where_single_value(:id=>1)
955
+ # # SELECT name FROM table WHERE (id = 1) LIMIT 1
956
+ def where_single_value(cond)
957
+ if loader = cached_placeholder_literalizer(:_where_single_value_loader) do |pl|
958
+ single_value_ds.where(pl.arg)
959
+ end
960
+
961
+ loader.get(filter_expr(cond))
962
+ else
963
+ where(cond).single_value
964
+ end
965
+ end
966
+
920
967
  # Run the given SQL and return an array of all rows. If a block is given,
921
968
  # each row is yielded to the block after all rows are loaded. See with_sql_each.
922
969
  def with_sql_all(sql, &block)
@@ -1044,6 +1091,13 @@ module Sequel
1044
1091
  cached_dataset(:_single_record_ds){clone(:limit=>1)}
1045
1092
  end
1046
1093
 
1094
+ # Loader used for where_all and where_each.
1095
+ def _where_loader
1096
+ cached_placeholder_literalizer(:_where_loader) do |pl|
1097
+ where(pl.arg)
1098
+ end
1099
+ end
1100
+
1047
1101
  # Automatically alias the given expression if it does not have an identifiable alias.
1048
1102
  def auto_alias_expression(v)
1049
1103
  case v
@@ -0,0 +1,58 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Sequel
4
+ class Dataset
5
+ # This Module subclass is used by Database#extend_datasets
6
+ # and Dataset#with_extend to add dataset methods to classes.
7
+ # It adds some helper methods inside the module that can define
8
+ # named methods on the dataset instances which do specific actions.
9
+ # For example:
10
+ #
11
+ # DB.extend_datasets do
12
+ # order :by_id, :id
13
+ # select :with_id_and_name, :id, :name
14
+ # where :active, :active
15
+ # end
16
+ #
17
+ # DB[:table].active.with_id_and_name.by_id
18
+ # # SELECT id, name FROM table WHERE active ORDER BY id
19
+ class DatasetModule < ::Module
20
+ %w'where exclude exclude_having having'.map(&:to_sym).each do |meth|
21
+ define_method(meth) do |name, *args, &block|
22
+ if block || args.flatten.any?{|arg| arg.is_a?(Proc)}
23
+ define_method(name){send(meth, *args, &block)}
24
+ else
25
+ key = :"_#{meth}_#{name}_ds"
26
+ define_method(name) do
27
+ cached_dataset(key){send(meth, *args)}
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ meths = (<<-METHS).split.map(&:to_sym)
34
+ distinct grep group group_and_count group_append
35
+ limit offset order order_append order_prepend
36
+ select select_all select_append select_group server
37
+ METHS
38
+
39
+ # Define a method in the module
40
+ def self.def_dataset_caching_method(mod, meth)
41
+ mod.send(:define_method, meth) do |name, *args, &block|
42
+ if block
43
+ define_method(name){send(meth, *args, &block)}
44
+ else
45
+ key = :"_#{meth}_#{name}_ds"
46
+ define_method(name) do
47
+ cached_dataset(key){send(meth, *args)}
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ meths.each do |meth|
54
+ def_dataset_caching_method(self, meth)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1087,12 +1087,12 @@ module Sequel
1087
1087
  # Return a clone of the dataset extended with the given modules.
1088
1088
  # Note that like Object#extend, when multiple modules are provided
1089
1089
  # as arguments the cloned dataset is extended with the modules in reverse
1090
- # order. If a block is provided, a module is created using the block and
1090
+ # order. If a block is provided, a DatasetModule is created using the block and
1091
1091
  # the clone is extended with that module after any modules given as arguments.
1092
1092
  def with_extend(*mods, &block)
1093
1093
  c = _clone(:freeze=>false)
1094
1094
  c.extend(*mods) unless mods.empty?
1095
- c.extend(Module.new(&block)) if block
1095
+ c.extend(DatasetModule.new(&block)) if block
1096
1096
  c.freeze if frozen? # SEQUEL5: Remove if frozen?
1097
1097
  c
1098
1098
  end
@@ -1101,7 +1101,7 @@ module Sequel
1101
1101
  def with_extend(*mods, &block) # :nodoc:
1102
1102
  c = clone
1103
1103
  c.extend(*mods) unless mods.empty?
1104
- c.extend(Module.new(&block)) if block
1104
+ c.extend(DatasetModule.new(&block)) if block
1105
1105
  c
1106
1106
  end
1107
1107
  # :nocov:
@@ -7,6 +7,14 @@ module Sequel
7
7
  # If this exception wraps an underlying exception, the underlying
8
8
  # exception is held here.
9
9
  attr_accessor :wrapped_exception
10
+
11
+ if RUBY_VERSION >= '2.1'
12
+ # Returned the wrapped exception if one exists, otherwise use
13
+ # ruby's default behavior.
14
+ def cause
15
+ wrapped_exception || super
16
+ end
17
+ end
10
18
  end
11
19
 
12
20
  (
@@ -5,14 +5,17 @@ module Sequel
5
5
  module PgRow
6
6
  module DatabaseMethods
7
7
  ESCAPE_RE = /("|\\)/.freeze
8
+ Sequel::Deprecation.deprecate_constant(self, :ESCAPE_RE)
8
9
  ESCAPE_REPLACEMENT = '\\\\\1'.freeze
10
+ Sequel::Deprecation.deprecate_constant(self, :ESCAPE_REPLACEMENT)
9
11
  COMMA = ','
12
+ Sequel::Deprecation.deprecate_constant(self, :COMMA)
10
13
 
11
14
  # Handle Sequel::Model instances in bound variables.
12
15
  def bound_variable_arg(arg, conn)
13
16
  case arg
14
17
  when Sequel::Model
15
- "(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(COMMA)})"
18
+ "(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(',')})"
16
19
  else
17
20
  super
18
21
  end
@@ -34,7 +37,7 @@ module Sequel
34
37
  def bound_variable_array(arg)
35
38
  case arg
36
39
  when Sequel::Model
37
- "\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(COMMA).gsub(ESCAPE_RE, ESCAPE_REPLACEMENT)})\""
40
+ "\"(#{arg.values.values_at(*arg.columns).map{|v| bound_variable_array(v)}.join(',').gsub(/("|\\)/, '\\\\\1')})\""
38
41
  else
39
42
  super
40
43
  end
@@ -32,7 +32,7 @@ module Sequel
32
32
  # Return an instance of Sequel.datetime_class that will be literalized
33
33
  # as CURRENT_TIMESTAMP.
34
34
  def current_datetime
35
- MAP.fetch(Sequel.datetime_class).now
35
+ (Sequel.datetime_class == ::Time ? Time : DateTime).now
36
36
  end
37
37
 
38
38
  private
@@ -56,6 +56,7 @@ module Sequel
56
56
 
57
57
  # Mapping of Time/DateTime classes to subclasses literalized as CURRENT_TIMESTAMP
58
58
  MAP = {::Time=>Time, ::DateTime=>DateTime}
59
+ Sequel::Deprecation.deprecate_constant(self, :MAP)
59
60
  end
60
61
 
61
62
  Dataset.register_extension(:current_datetime_timestamp, CurrentDateTimeTimestamp::DatasetMethods)