sequel 5.108.0 → 5.109.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/sequel/adapters/amalgalite.rb +34 -8
  3. data/lib/sequel/adapters/jdbc/mssql.rb +28 -5
  4. data/lib/sequel/adapters/jdbc/postgresql.rb +14 -3
  5. data/lib/sequel/adapters/jdbc.rb +2 -1
  6. data/lib/sequel/adapters/postgres.rb +5 -2
  7. data/lib/sequel/adapters/shared/db2.rb +3 -0
  8. data/lib/sequel/adapters/shared/mssql.rb +7 -1
  9. data/lib/sequel/adapters/shared/postgres.rb +19 -990
  10. data/lib/sequel/adapters/shared/sqlanywhere.rb +0 -32
  11. data/lib/sequel/adapters/sqlite.rb +13 -9
  12. data/lib/sequel/adapters/trilogy.rb +2 -1
  13. data/lib/sequel/core.rb +14 -2
  14. data/lib/sequel/database/misc.rb +1 -6
  15. data/lib/sequel/database/transactions.rb +1 -3
  16. data/lib/sequel/dataset/actions.rb +1 -1
  17. data/lib/sequel/dataset/sql.rb +14 -3
  18. data/lib/sequel/extensions/core_refinements.rb +1 -4
  19. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -3
  20. data/lib/sequel/extensions/lit_require_frozen.rb +17 -1
  21. data/lib/sequel/extensions/named_timezones.rb +1 -1
  22. data/lib/sequel/extensions/pg_array.rb +1 -0
  23. data/lib/sequel/extensions/pg_json_ops.rb +4 -2
  24. data/lib/sequel/extensions/s.rb +4 -8
  25. data/lib/sequel/extensions/schema_dumper.rb +6 -2
  26. data/lib/sequel/extensions/symbol_aref.rb +11 -31
  27. data/lib/sequel/extensions/symbol_aref_refinement.rb +1 -4
  28. data/lib/sequel/extensions/symbol_as.rb +1 -2
  29. data/lib/sequel/extensions/symbol_as_refinement.rb +1 -5
  30. data/lib/sequel/model/base.rb +1 -6
  31. data/lib/sequel/plugins/caching.rb +27 -2
  32. data/lib/sequel/plugins/csv_serializer.rb +9 -20
  33. data/lib/sequel/plugins/instance_filters.rb +8 -0
  34. data/lib/sequel/plugins/instance_hooks.rb +19 -0
  35. data/lib/sequel/plugins/mssql_optimistic_locking.rb +9 -0
  36. data/lib/sequel/plugins/optimistic_locking.rb +12 -2
  37. data/lib/sequel/plugins/optimistic_locking_base.rb +14 -0
  38. data/lib/sequel/plugins/pg_xmin_optimistic_locking.rb +11 -2
  39. data/lib/sequel/plugins/select_on_skipped_update.rb +63 -0
  40. data/lib/sequel/plugins/single_table_inheritance.rb +20 -2
  41. data/lib/sequel/plugins/subset_conditions.rb +5 -16
  42. data/lib/sequel/plugins/throw_failures.rb +1 -1
  43. data/lib/sequel/plugins/validate_associated.rb +7 -1
  44. data/lib/sequel/plugins/validate_associated_context.rb +52 -0
  45. data/lib/sequel/sql.rb +109 -105
  46. data/lib/sequel/version.rb +1 -1
  47. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebb20cf6a0935b45043b5dc3d5ba39256f5c9fe34a1894a32383211f4cbeced5
4
- data.tar.gz: a5a0c9a83a2862f133516a91b76862e0f69e6b4ac95356a7358e0ae798ab6449
3
+ metadata.gz: d532e5b8b7464ce5420441aada5a737826aadf657b7ae2d74e00947fb9073b8c
4
+ data.tar.gz: 8768f69d56e2683b1a3613fb087372fb419fe5086f6e6c399278d648e106527b
5
5
  SHA512:
6
- metadata.gz: bde58f0598455d105c3c4a2e3d30ebf86776c2acbef2ccfdf6ea0f3c36772396c42be9678f8e03bbfab41e06a593f2d3e6e651a8fbded9ffa3fb2f13c2f1f1eb
7
- data.tar.gz: d92f6fa652e500b92106aaafb5646dab52c80647e0cf1d42164cdccdf16e8e56209b3205b8699e99704bfae480bdd4846769100e7e602c2ac72d4a9383765b60
6
+ metadata.gz: 9e1c3559c9fe77f574f54e6b0c67a1ab421d9cc2661aba5121693bc0a101e7d922474e443ae2c93ff55a7a4e7880c7a1eb9b6476a9b2b4b22fbb361d616996db
7
+ data.tar.gz: '07583c0e8b4375f7016a8806973ff555ec8dc2225f0306b8a73535e34c1a517a3d5071299613d80b328cd1835519a5df577b372495ef793c1e58aad271ae9661'
@@ -7,13 +7,39 @@ module Sequel
7
7
  module Amalgalite
8
8
  # Type conversion map class for Sequel's use of Amalgamite
9
9
  class SequelTypeMap < ::Amalgalite::TypeMaps::DefaultMap
10
- methods_handling_sql_types.delete('string')
11
- methods_handling_sql_types.merge!(
12
- 'datetime' => %w'datetime timestamp',
13
- 'time' => %w'time',
14
- 'float' => ['float', 'double', 'real', 'double precision'],
15
- 'decimal' => %w'numeric decimal money'
16
- )
10
+ if respond_to?(:methods_handling_sql_types, true)
11
+ # Amalgalite < 2 support
12
+ methods_handling_sql_types.delete('string')
13
+ methods_handling_sql_types.merge!(
14
+ 'datetime' => %w'datetime timestamp',
15
+ 'time' => %w'time',
16
+ 'float' => ['float', 'double', 'real', 'double precision'],
17
+ 'decimal' => %w'numeric decimal money'
18
+
19
+ )
20
+
21
+ def result_value_method(type)
22
+ self.class.sql_to_method(type)
23
+ end
24
+ else
25
+ # Amalgalite 2 support
26
+ SQL_TO_METHOD = superclass::SQL_TO_METHOD.merge(
27
+ 'datetime' => :datetime,
28
+ 'timestamp' => :datetime,
29
+ 'time' => :time,
30
+ 'float' => :float,
31
+ 'double' => :float,
32
+ 'real' => :float,
33
+ 'double precision' => :float,
34
+ 'decimal' => :decimal,
35
+ 'numeric' => :decimal,
36
+ 'money' => :decimal
37
+ )
38
+
39
+ def result_value_method(type)
40
+ SQL_TO_METHOD[type]
41
+ end
42
+ end
17
43
 
18
44
  # Store the related database object, in order to be able to correctly
19
45
  # handle the database timezone.
@@ -48,7 +74,7 @@ module Sequel
48
74
  if value.is_a?(::Amalgalite::Blob)
49
75
  SQL::Blob.new(value.to_s)
50
76
  elsif value.is_a?(String) && declared_type
51
- (meth = self.class.sql_to_method(declared_type.downcase)) ? public_send(meth, value) : value
77
+ (meth = result_value_method(declared_type.downcase)) ? public_send(meth, value) : value
52
78
  else
53
79
  super
54
80
  end
@@ -12,11 +12,34 @@ module Sequel
12
12
 
13
13
  # Get the last inserted id using SCOPE_IDENTITY().
14
14
  def last_insert_id(conn, opts=OPTS)
15
- statement(conn) do |stmt|
16
- sql = opts[:prepared] ? 'SELECT @@IDENTITY' : 'SELECT SCOPE_IDENTITY()'
17
- rs = log_connection_yield(sql, conn){stmt.executeQuery(sql)}
18
- rs.next
19
- rs.getLong(1)
15
+ if (stmt = opts[:stmt]) && opts[:prepared]
16
+ rs = stmt.getGeneratedKeys
17
+ begin
18
+ if rs.next
19
+ begin
20
+ rs.getLong(1)
21
+ rescue
22
+ rs.getObject(1) rescue nil
23
+ end
24
+ end
25
+ ensure
26
+ rs.close
27
+ end
28
+ else
29
+ statement(conn) do |stmt|
30
+ sql = 'SELECT SCOPE_IDENTITY()'
31
+ rs = log_connection_yield(sql, conn){stmt.executeQuery(sql)}
32
+ rs.next
33
+ rs.getLong(1)
34
+ end
35
+ end
36
+ end
37
+
38
+ def prepare_jdbc_statement(conn, sql, opts)
39
+ if opts[:type] == :insert
40
+ conn.prepareStatement(sql, JavaSQL::Statement::RETURN_GENERATED_KEYS)
41
+ else
42
+ super
20
43
  end
21
44
  end
22
45
 
@@ -75,7 +75,14 @@ module Sequel
75
75
  def copy_table(table, opts=OPTS)
76
76
  synchronize(opts[:server]) do |conn|
77
77
  copy_manager = Java::OrgPostgresqlCopy::CopyManager.new(conn)
78
- copier = copy_manager.copy_out(copy_table_sql(table, opts))
78
+ sql = copy_table_sql(table, opts)
79
+
80
+ begin
81
+ copier = copy_manager.copy_out(sql)
82
+ rescue *DATABASE_ERROR_CLASSES => e
83
+ raise_error(e)
84
+ end
85
+
79
86
  begin
80
87
  if defined?(yield)
81
88
  while buf = copier.readFromCopy
@@ -147,7 +154,11 @@ module Sequel
147
154
  # a PGObject instance with unknown type and the bound argument string value,
148
155
  # and set that as the prepared statement argument.
149
156
  def set_ps_arg(cps, arg, i)
150
- if v = bound_variable_arg(arg, nil)
157
+ unless v = bound_variable_arg(arg, nil)
158
+ v = arg.strftime("%F %T.%6N%z") if arg.is_a?(DateTime)
159
+ end
160
+
161
+ if v
151
162
  obj = Java::OrgPostgresqlUtil::PGobject.new
152
163
  obj.setType("unknown")
153
164
  obj.setValue(v)
@@ -202,7 +213,7 @@ module Sequel
202
213
  INTEGER_TYPE = Java::JavaSQL::Types::INTEGER
203
214
  STRING_TYPE = Java::JavaSQL::Types::VARCHAR
204
215
  ARRAY_TYPE = Java::JavaSQL::Types::ARRAY
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
216
+ 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, Java::JavaSQL::Types::TIMESTAMP_WITH_TIMEZONE, Java::JavaSQL::Types::TIMESTAMP].freeze
206
217
 
207
218
  # Return PostgreSQL hstore types as ruby Hashes instead of
208
219
  # Java HashMaps. Only used if the database does not have a
@@ -24,7 +24,7 @@ module Sequel
24
24
 
25
25
  # Default database error classes
26
26
  DATABASE_ERROR_CLASSES = [NativeException]
27
- if JRUBY_VERSION < '9.2'
27
+ if JRUBY_VERSION.to_r < Rational('9.2')
28
28
  # On JRuby <9.2, still include ::NativeException, as it is still needed in some cases
29
29
  DATABASE_ERROR_CLASSES << ::NativeException
30
30
  end
@@ -496,6 +496,7 @@ module Sequel
496
496
  rescue *DATABASE_ERROR_CLASSES => e
497
497
  raise_error(e)
498
498
  ensure
499
+ cps.clear_parameters
499
500
  cps.close unless name
500
501
  end
501
502
  end
@@ -371,7 +371,8 @@ module Sequel
371
371
  #
372
372
  # The following options are respected:
373
373
  #
374
- # :format :: The format to use. text is the default, so this should be :csv or :binary.
374
+ # :format :: The format to use. The PostgreSQL default is text, possible options are :csv,
375
+ # :json, or :binary.
375
376
  # :options :: An options SQL string to use, which should contain comma separated options.
376
377
  # :server :: The server on which to run the query.
377
378
  #
@@ -380,7 +381,9 @@ module Sequel
380
381
  # of the data.
381
382
  def copy_table(table, opts=OPTS)
382
383
  synchronize(opts[:server]) do |conn|
383
- conn.execute(copy_table_sql(table, opts))
384
+ sql = copy_table_sql(table, opts)
385
+ check_database_errors{conn.execute(sql)}
386
+
384
387
  begin
385
388
  if defined?(yield)
386
389
  while buf = conn.get_copy_data
@@ -190,6 +190,9 @@ module Sequel
190
190
  # creating the table, since it is not possible to do it in one step.
191
191
  def create_table_as(name, sql, options)
192
192
  super
193
+ if options[:temp]
194
+ name = Sequel.qualify(:session, name)
195
+ end
193
196
  from(name).insert(sql.is_a?(Dataset) ? sql : dataset.with_sql(sql))
194
197
  end
195
198
 
@@ -400,6 +400,9 @@ module Sequel
400
400
  # Error if a string is given.
401
401
  def create_table_as(name, ds, options)
402
402
  raise(Error, "must provide dataset instance as value of create_table :as option on MSSQL") unless ds.is_a?(Sequel::Dataset)
403
+ if options[:temp]
404
+ name = create_table_temp_table_name_sql(name, options)
405
+ end
403
406
  run(ds.into(name).sql.freeze)
404
407
  end
405
408
 
@@ -679,7 +682,10 @@ module Sequel
679
682
 
680
683
  # MSSQL uses the CONTAINS keyword for full text search
681
684
  def full_text_search(cols, terms, opts = OPTS)
682
- terms = "\"#{Sequel.array_or_set_join(terms, '" OR "')}\"" if terms.is_a?(Array) || terms.is_a?(Set)
685
+ case terms
686
+ when Array, Set
687
+ terms = Sequel.array_or_set_join(terms.map{|term| "\"#{term.to_s.gsub('"', '""')}\""}, " OR ")
688
+ end
683
689
  where(Sequel.lit("CONTAINS (?, ?)", cols, terms))
684
690
  end
685
691