sequel 5.35.0 → 5.36.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ac0d24707f9029714f4e5258c484148d7dc10a733c0c33865d252141cd4cc2e
4
- data.tar.gz: cdabb1bb51fdfe7b7a22df0a6a9102dd15366bbdd98100907b2e3d74db4e5878
3
+ metadata.gz: b3ea26531aa8ce58a1d98b14e4df51dc2c364285d915486baf3647347c482c96
4
+ data.tar.gz: f4588646c72d99490d19e637eede86fe9cd3421c8c2c861802c6e9bf4c3b5425
5
5
  SHA512:
6
- metadata.gz: d87a7d026c51d8897c964cca01ad30384b853bdbbda42811ee7245ef669ac23c1093e572a0e414db5daeb84b8f417e63c14c3ac13aa0b12ac9eb8f801ea6e6c2
7
- data.tar.gz: 3e788cabe74d01035b930ca699b5ebc763a6a34410c1b8a3a5075d5a276c5155355d9476303b6b606d1b0a74d6a535ca4fdca696cdc0b83e32658be45c8f946e
6
+ metadata.gz: aa483b284775682fb6b33b56bcccf33bc32a22e0161964a5e8679d461dd6ac3e5e4d4575a10887e71a730d85d8b04194fb739ee122093ae797df18a4e70534c9
7
+ data.tar.gz: fcc040944c40bc0be1faf2b4eafc3e1d34ea8a409c6ef45e26ae7f25f6d38c4f7b66445902b71b05e55eaccb37c1c1ee47c29d8a5135dd45b95a8b5d50ffe0dd
data/CHANGELOG CHANGED
@@ -1,3 +1,27 @@
1
+ === 5.36.0 (2020-09-01)
2
+
3
+ * Handle passing keyword arguments through class methods defined via Plugins.def_dataset_method on Ruby 2.7+ (jeremyevans)
4
+
5
+ * Handle passing keyword arguments through when loading plugins on Ruby 2.7+ (jeremyevans)
6
+
7
+ * Handle passing keyword arguments through migrations when defining custom Database methods that accept keywords on Ruby 2.7+ (jeremyevans)
8
+
9
+ * Handle passing keyword arguments through Dataset#query when using the query extension on Ruby 2.7+ (jeremyevans)
10
+
11
+ * Handle passing keyword arguments through the association proxy when using the association_proxies plugin on Ruby 2.7+ (jeremyevans)
12
+
13
+ * Handle passing keyword arguments through the class method to a method defined in dataset_module on Ruby 2.7+ (adam12) (#1713)
14
+
15
+ * Stream result sets in the odbc adapter for better performance and lower memory usage (sparrovv) (#1711)
16
+
17
+ * Add Postgres::JSONBOp#set_lax and #path_*_tz methods to the pg_json_ops extension for new jsonb functions added in PostgreSQL 13 (jeremyevans)
18
+
19
+ * Add Dataset#with_ties on PostgreSQL 13+ and Microsoft SQL Server to include rows with same order as final row (jeremyevans)
20
+
21
+ * Add a :current_schema option to Database#view_exists? (only defined on Oracle) to look in the current schema instead of non-system schemas (jeremyevans) (#1710)
22
+
23
+ * Recognize another disconnect error in the mysql and mysql2 adapters (jeremyevans) (#1706)
24
+
1
25
  === 5.35.0 (2020-08-01)
2
26
 
3
27
  * Recognize another disconnect error in the oracle adapter (sterlzbd) (#1705)
@@ -172,7 +172,7 @@ Datasets are the primary way records are retrieved and manipulated. They are ge
172
172
  posts = DB.from(:posts)
173
173
  posts = DB[:posts] # same
174
174
 
175
- Datasets will only fetch records when you tell them to. They can be manipulated to filter records, change ordering, join tables, etc.. Datasets are always frozen, and they safe to use by multiple threads concurrently.
175
+ Datasets will only fetch records when you tell them to. They can be manipulated to filter records, change ordering, join tables, etc. Datasets are always frozen, and they are safe to use by multiple threads concurrently.
176
176
 
177
177
  === Retrieving Records
178
178
 
@@ -212,7 +212,7 @@ In general you should only require plugin arguments if you absolutely must have
212
212
 
213
213
  == Handling Subclasses
214
214
 
215
- Sequel::Model uses a copy-on-subclassing approach to model state. So instead of model subclasses asking their parent class for a value if they don't have it defined, the value is automatically copied from the parent class to the subclass when the subclass is created. While you can do this by overriding the inherited class method, there is a available shortcut that handles most cases:
215
+ Sequel::Model uses a copy-on-subclassing approach to model state. So instead of having a model subclass ask its superclass for a value if the subclass don't have the value defined, the value should be copied from the parent class to the subclass when the subclass is created. While this can be implemented by overriding the +inherited+ class method, there is an available shortcut that handles most cases:
216
216
 
217
217
  module Sequel::Plugins::Foo
218
218
  module ClassMethods
@@ -0,0 +1,60 @@
1
+ = New Features
2
+
3
+ * Dataset#with_ties has been added on PostgreSQL 13+ and Microsoft
4
+ SQL Server, which will have a limited dataset also return all
5
+ rows with the same order as the final row.
6
+
7
+ * In the pg_json_ops extension, the following methods have been
8
+ added to Postgres::JSONBOp, all of which require PostgreSQL 13+:
9
+
10
+ * #set_lax
11
+ * #path_exists_tz!
12
+ * #path_match_tz!
13
+ * #path_query_tz
14
+ * #path_query_array_tz
15
+ * #path_query_first_tz
16
+
17
+ * On Oracle, the Database#view_exists? method now accepts a
18
+ :current_schema option to limit the views returned to the
19
+ current schema, instead of all non-system schemas.
20
+
21
+ = Other Improvements
22
+
23
+ * Sequel will now pass keyword arguments through in the following
24
+ cases:
25
+
26
+ * When loading plugins (Model.plugin)
27
+
28
+ * Class methods automically defined for methods defined in a
29
+ Model.dataset_module block
30
+
31
+ * Methods defined by Plugins.def_dataset_method
32
+
33
+ * Database methods called inside migrations
34
+
35
+ * Methods called via an association proxy when using the
36
+ association_proxies plugin.
37
+
38
+ * Dataset methods called inside a Dataset#query block when using
39
+ the query extension.
40
+
41
+ Previously, keywords were not handled in these cases, which would
42
+ cause deprecation warnings in Ruby 2.7 and ArgumentErrors in Ruby
43
+ 3.0. Note that Sequel itself does not use keyword arguments at
44
+ all, so all of these changes only affect cases where external
45
+ methods are defined that accept keywords, and Sequel methods are
46
+ called with keywords that end up being delegated to the external
47
+ methods.
48
+
49
+ * The odbc adapter will now stream result sets instead of loading
50
+ the entire result set in memory and then iterating over it.
51
+
52
+ * Sequel now recognizes another disconnect error in the mysql and
53
+ mysql2 adapters.
54
+
55
+ = Backwards Compatibility
56
+
57
+ * Due to the odbc adapter change to use streaming, issuing queries
58
+ inside a Dataset#each block will no longer work unless a different
59
+ shard or thread is used. The behavior of such code is considered
60
+ undefined on all Sequel adapters.
@@ -232,7 +232,7 @@ These methods check that the specified attributes can be valid integers or valid
232
232
 
233
233
  === +validates_operator+
234
234
 
235
- +validates_operator+ checks that a given +operator+ method returns a truthy value when called on attribute with a specified value for comparison. Generally, this is used for inequality checks (>, >=, etc) but any method that can be called on the attribute that accepts an argument and returns a truthy value may be used.
235
+ +validates_operator+ checks that a given +operator+ method returns a truthy value when called on attribute with a specified value for comparison. Generally, this is used for inequality checks (>, >=, etc.) but any method that can be called on the attribute that accepts an argument and returns a truthy value may be used.
236
236
 
237
237
  class Album < Sequel::Model
238
238
  def validate
@@ -92,12 +92,10 @@ module Sequel
92
92
  cols = s.columns(true).map{|c| [output_identifier(c.name), c.type, i+=1]}
93
93
  columns = cols.map{|c| c[0]}
94
94
  self.columns = columns
95
- if rows = s.fetch_all
96
- rows.each do |row|
97
- hash = {}
98
- cols.each{|n,t,j| hash[n] = convert_odbc_value(row[j], t)}
99
- yield hash
100
- end
95
+ s.each do |row|
96
+ hash = {}
97
+ cols.each{|n,t,j| hash[n] = convert_odbc_value(row[j], t)}
98
+ yield hash
101
99
  end
102
100
  end
103
101
  self
@@ -659,11 +659,11 @@ module Sequel
659
659
  # case by default, and that also adds a default order, so it's better to just
660
660
  # avoid the subquery.
661
661
  def select_sql
662
- if @opts[:offset] && !@opts[:order] && is_2012_or_later?
663
- order(1).select_sql
664
- else
665
- super
662
+ if @opts[:offset]
663
+ raise(Error, "Using with_ties is not supported with an offset on Microsoft SQL Server") if @opts[:limit_with_ties]
664
+ return order(1).select_sql if is_2012_or_later? && !@opts[:order]
666
665
  end
666
+ super
667
667
  end
668
668
 
669
669
  # The version of the database server.
@@ -755,6 +755,12 @@ module Sequel
755
755
  false
756
756
  end
757
757
 
758
+ # Use WITH TIES when limiting the result set to also include additional
759
+ # rows matching the last row.
760
+ def with_ties
761
+ clone(:limit_with_ties=>true)
762
+ end
763
+
758
764
  protected
759
765
 
760
766
  # If returned primary keys are requested, use OUTPUT unless already set on the
@@ -959,6 +965,10 @@ module Sequel
959
965
  sql << " TOP "
960
966
  literal_append(sql, l)
961
967
  end
968
+
969
+ if @opts[:limit_with_ties]
970
+ sql << " WITH TIES"
971
+ end
962
972
  end
963
973
 
964
974
  def update_limit_sql(sql)
@@ -103,12 +103,18 @@ module Sequel
103
103
  map{|r| m.call(r[:view_name])}
104
104
  end
105
105
 
106
- def view_exists?(name)
107
- m = input_identifier_meth
108
- metadata_dataset.from(:all_views).
109
- exclude(:owner=>IGNORE_OWNERS).
110
- where(:view_name=>m.call(name)).
111
- count > 0
106
+ # Whether a view with a given name exists. By default, looks in all schemas other than system
107
+ # schemas. If the :current_schema option is given, looks in the schema for the current user.
108
+ def view_exists?(name, opts=OPTS)
109
+ ds = metadata_dataset.from(:all_views).where(:view_name=>input_identifier_meth.call(name))
110
+
111
+ if opts[:current_schema]
112
+ ds = ds.where(:owner=>Sequel.function(:SYS_CONTEXT, 'userenv', 'current_schema'))
113
+ else
114
+ ds = ds.exclude(:owner=>IGNORE_OWNERS)
115
+ end
116
+
117
+ ds.count > 0
112
118
  end
113
119
 
114
120
  # The version of the Oracle server, used for determining capability.
@@ -1885,6 +1885,13 @@ module Sequel
1885
1885
  end
1886
1886
  end
1887
1887
 
1888
+ # Use WITH TIES when limiting the result set to also include additional
1889
+ # rules that have the same results for the order column as the final row.
1890
+ # Requires PostgreSQL 13.
1891
+ def with_ties
1892
+ clone(:limit_with_ties=>true)
1893
+ end
1894
+
1888
1895
  protected
1889
1896
 
1890
1897
  # If returned primary keys are requested, use RETURNING unless already set on the
@@ -2071,6 +2078,37 @@ module Sequel
2071
2078
  false
2072
2079
  end
2073
2080
 
2081
+ # Support FETCH FIRST WITH TIES on PostgreSQL 13+.
2082
+ def select_limit_sql(sql)
2083
+ l = @opts[:limit]
2084
+ o = @opts[:offset]
2085
+
2086
+ return unless l || o
2087
+
2088
+ if @opts[:limit_with_ties]
2089
+ if o
2090
+ sql << " OFFSET "
2091
+ literal_append(sql, o)
2092
+ end
2093
+
2094
+ if l
2095
+ sql << " FETCH FIRST "
2096
+ literal_append(sql, l)
2097
+ sql << " ROWS WITH TIES"
2098
+ end
2099
+ else
2100
+ if l
2101
+ sql << " LIMIT "
2102
+ literal_append(sql, l)
2103
+ end
2104
+
2105
+ if o
2106
+ sql << " OFFSET "
2107
+ literal_append(sql, o)
2108
+ end
2109
+ end
2110
+ end
2111
+
2074
2112
  # Support FOR SHARE locking when using the :share lock style.
2075
2113
  # Use SKIP LOCKED if skipping locked rows.
2076
2114
  def select_lock_sql(sql)
@@ -18,6 +18,7 @@ module Sequel
18
18
  This connection is still waiting for a result, try again once you have the result
19
19
  closed MySQL connection
20
20
  The MySQL server is running with the --read-only option so it cannot execute this statement
21
+ Connection was killed
21
22
  END
22
23
  # Error messages for mysql and mysql2 that indicate the current connection should be disconnected
23
24
  MYSQL_DATABASE_DISCONNECT_ERRORS = /\A#{Regexp.union(disconnect_errors)}/
@@ -154,7 +154,7 @@ module Sequel
154
154
  # Note that this should not be used unless the entire transaction
155
155
  # block is idempotent, as otherwise it can cause non-idempotent
156
156
  # behavior to execute multiple times.
157
- # :rollback :: Can the set to :reraise to reraise any Sequel::Rollback exceptions
157
+ # :rollback :: Can be set to :reraise to reraise any Sequel::Rollback exceptions
158
158
  # raised, or :always to always rollback even if no exceptions occur
159
159
  # (useful for testing).
160
160
  # :server :: The server to use for the transaction. Set to :default, :read_only, or
@@ -68,6 +68,7 @@ module Sequel
68
68
  # Allow calling private methods for backwards compatibility
69
69
  @db.send(method_sym, *args, &block)
70
70
  end
71
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
71
72
 
72
73
  # This object responds to all methods the database responds to.
73
74
  def respond_to_missing?(meth, include_private)
@@ -73,7 +73,10 @@
73
73
  # j.pretty # jsonb_pretty(jsonb_column)
74
74
  # j.set(%w'0 a', :h) # jsonb_set(jsonb_column, ARRAY['0','a'], h, true)
75
75
  #
76
- # On PostgreSQL 12+ SQL/JSON functions and operators are supported:
76
+ # j.set_lax(%w'0 a', :h, false, 'raise_exception')
77
+ # # jsonb_set_lax(jsonb_column, ARRAY['0','a'], h, false, 'raise_exception')
78
+ #
79
+ # On PostgreSQL 12+ SQL/JSON path functions and operators are supported:
77
80
  #
78
81
  # j.path_exists('$.foo') # (jsonb_column @? '$.foo')
79
82
  # j.path_match('$.foo') # (jsonb_column @@ '$.foo')
@@ -84,7 +87,15 @@
84
87
  # j.path_query_array('$.foo') # jsonb_path_query_array(jsonb_column, '$.foo')
85
88
  # j.path_query_first('$.foo') # jsonb_path_query_first(jsonb_column, '$.foo')
86
89
  #
87
- # For the PostgreSQL 12+ SQL/JSON functions, one argument is required (+path+) and
90
+ # On PostgreSQL 13+ timezone-aware SQL/JSON path functions and operators are supported:
91
+ #
92
+ # j.path_exists_tz!('$.foo') # jsonb_path_exists_tz(jsonb_column, '$.foo')
93
+ # j.path_match_tz!('$.foo') # jsonb_path_match_tz(jsonb_column, '$.foo')
94
+ # j.path_query_tz('$.foo') # jsonb_path_query_tz(jsonb_column, '$.foo')
95
+ # j.path_query_array_tz('$.foo') # jsonb_path_query_array_tz(jsonb_column, '$.foo')
96
+ # j.path_query_first_tz('$.foo') # jsonb_path_query_first_tz(jsonb_column, '$.foo')
97
+ #
98
+ # For the PostgreSQL 12+ SQL/JSON path functions, one argument is required (+path+) and
88
99
  # two more arguments are optional (+vars+ and +silent+). +path+ specifies the JSON path.
89
100
  # +vars+ specifies a hash or a string in JSON format of named variables to be
90
101
  # substituted in +path+. +silent+ specifies whether errors are suppressed. By default,
@@ -402,6 +413,11 @@ module Sequel
402
413
  Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists, path, vars, silent))
403
414
  end
404
415
 
416
+ # The same as #path_exists!, except that timezone-aware conversions are used for date/time values.
417
+ def path_exists_tz!(path, vars=nil, silent=nil)
418
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_exists_tz, path, vars, silent))
419
+ end
420
+
405
421
  # Returns the first item of the result of JSON path predicate check for the json object.
406
422
  # Returns nil if the first item is not true or false.
407
423
  #
@@ -425,6 +441,11 @@ module Sequel
425
441
  Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match, path, vars, silent))
426
442
  end
427
443
 
444
+ # The same as #path_match!, except that timezone-aware conversions are used for date/time values.
445
+ def path_match_tz!(path, vars=nil, silent=nil)
446
+ Sequel::SQL::BooleanExpression.new(:NOOP, _path_function(:jsonb_path_match_tz, path, vars, silent))
447
+ end
448
+
428
449
  # Returns a set of all jsonb values specified by the JSON path
429
450
  # for the json object.
430
451
  #
@@ -440,6 +461,11 @@ module Sequel
440
461
  _path_function(:jsonb_path_query, path, vars, silent)
441
462
  end
442
463
 
464
+ # The same as #path_query, except that timezone-aware conversions are used for date/time values.
465
+ def path_query_tz(path, vars=nil, silent=nil)
466
+ _path_function(:jsonb_path_query_tz, path, vars, silent)
467
+ end
468
+
443
469
  # Returns a jsonb array of all values specified by the JSON path
444
470
  # for the json object.
445
471
  #
@@ -455,6 +481,11 @@ module Sequel
455
481
  JSONBOp.new(_path_function(:jsonb_path_query_array, path, vars, silent))
456
482
  end
457
483
 
484
+ # The same as #path_query_array, except that timezone-aware conversions are used for date/time values.
485
+ def path_query_array_tz(path, vars=nil, silent=nil)
486
+ JSONBOp.new(_path_function(:jsonb_path_query_array_tz, path, vars, silent))
487
+ end
488
+
458
489
  # Returns the first item of the result specified by the JSON path
459
490
  # for the json object.
460
491
  #
@@ -470,6 +501,11 @@ module Sequel
470
501
  JSONBOp.new(_path_function(:jsonb_path_query_first, path, vars, silent))
471
502
  end
472
503
 
504
+ # The same as #path_query_first, except that timezone-aware conversions are used for date/time values.
505
+ def path_query_first_tz(path, vars=nil, silent=nil)
506
+ JSONBOp.new(_path_function(:jsonb_path_query_first_tz, path, vars, silent))
507
+ end
508
+
473
509
  # Return the receiver, since it is already a JSONBOp.
474
510
  def pg_jsonb
475
511
  self
@@ -492,6 +528,12 @@ module Sequel
492
528
  self.class.new(function(:set, wrap_input_array(path), wrap_input_jsonb(other), create_missing))
493
529
  end
494
530
 
531
+ # The same as #set, except if +other+ is +nil+, then behaves according to +null_value_treatment+,
532
+ # which can be one of 'raise_exception', 'use_json_null' (default), 'delete_key', or 'return_target'.
533
+ def set_lax(path, other, create_missing=true, null_value_treatment='use_json_null')
534
+ self.class.new(function(:set_lax, wrap_input_array(path), wrap_input_jsonb(other), create_missing, null_value_treatment))
535
+ end
536
+
495
537
  private
496
538
 
497
539
  # Internals of the jsonb SQL/JSON path functions.
@@ -74,6 +74,7 @@ module Sequel
74
74
  raise(Sequel::Error, "method #{method.inspect} did not return a dataset") unless @dataset.is_a?(Dataset)
75
75
  self
76
76
  end
77
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
77
78
  end
78
79
  end
79
80
 
@@ -79,7 +79,7 @@ module Sequel
79
79
  def_Model(::Sequel)
80
80
 
81
81
  # The setter methods (methods ending with =) that are never allowed
82
- # to be called automatically via +set+/+update+/+new+/etc..
82
+ # to be called automatically via +set+/+update+/+new+/etc.
83
83
  RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}.freeze
84
84
  end
85
85
  end
@@ -508,6 +508,7 @@ module Sequel
508
508
 
509
509
  m.configure(self, *args, &block) if m.respond_to?(:configure)
510
510
  end
511
+ ruby2_keywords(:plugin) if respond_to?(:ruby2_keywords, true)
511
512
 
512
513
  # Returns primary key attribute hash. If using a composite primary key
513
514
  # value such be an array with values for each primary key in the correct
@@ -756,6 +757,7 @@ module Sequel
756
757
  else
757
758
  define_singleton_method(meth){|*args, &block| dataset.public_send(meth, *args, &block)}
758
759
  end
760
+ singleton_class.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true)
759
761
  end
760
762
 
761
763
  # Get the schema from the database, fall back on checking the columns
@@ -31,6 +31,7 @@ module Sequel
31
31
  def self.def_dataset_methods(mod, meths)
32
32
  Array(meths).each do |meth|
33
33
  mod.class_eval("def #{meth}(*args, &block); dataset.#{meth}(*args, &block) end", __FILE__, __LINE__)
34
+ mod.send(:ruby2_keywords, meth) if respond_to?(:ruby2_keywords, true)
34
35
  end
35
36
  end
36
37
 
@@ -99,6 +99,7 @@ module Sequel
99
99
  end
100
100
  v.public_send(meth, *args, &block)
101
101
  end
102
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
102
103
  end
103
104
 
104
105
  module ClassMethods
@@ -6,7 +6,7 @@ module Sequel
6
6
 
7
7
  # The minor version of Sequel. Bumped for every non-patch level
8
8
  # release, generally around once a month.
9
- MINOR = 35
9
+ MINOR = 36
10
10
 
11
11
  # The tiny version of Sequel. Usually 0, only bumped for bugfix
12
12
  # releases that fix regressions from previous versions.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.35.0
4
+ version: 5.36.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-01 00:00:00.000000000 Z
11
+ date: 2020-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -183,6 +183,7 @@ extra_rdoc_files:
183
183
  - doc/release_notes/5.33.0.txt
184
184
  - doc/release_notes/5.34.0.txt
185
185
  - doc/release_notes/5.35.0.txt
186
+ - doc/release_notes/5.36.0.txt
186
187
  files:
187
188
  - CHANGELOG
188
189
  - MIT-LICENSE
@@ -239,6 +240,7 @@ files:
239
240
  - doc/release_notes/5.33.0.txt
240
241
  - doc/release_notes/5.34.0.txt
241
242
  - doc/release_notes/5.35.0.txt
243
+ - doc/release_notes/5.36.0.txt
242
244
  - doc/release_notes/5.4.0.txt
243
245
  - doc/release_notes/5.5.0.txt
244
246
  - doc/release_notes/5.6.0.txt