sequel 5.74.0 → 5.75.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: 16c90ef17199e4e48f39edee069981ba0030cf63dc481b136f637b1fe069743e
4
- data.tar.gz: 52063f32827a04c33173867207290da294878d898d25b80c37666cf66a54b780
3
+ metadata.gz: 3047129164c9cdffee31414419904329e410db71e7e4243c0549614498a2b0d4
4
+ data.tar.gz: 9cc84ed8e9dba53aac7175be04699089932566e4015aed7a465c43552808c8b4
5
5
  SHA512:
6
- metadata.gz: d808534a13ae702a884524ceae4adcdb8eff9d46681a62d5b2c0d926b46279743350520248311c41f8a385c7fc66d17cbc44c7f1af52f1cffd356fca498d6bb2
7
- data.tar.gz: 309d0f0c0a7c47a4f1acc90107443e7fd2aa51cb09038082354e822711b11986ae271bb784e710336cebafc83b8b5a99adf088bfd19e2353728d25de86f942c4
6
+ metadata.gz: 15ed5c13e4793191546cd452aa5865e65fd7b3bb0458ffdb674d526398b7c9446e2da0f43a339daa3f1dc256eb551f0b773ac9ffc192b4d19f389d0c7e296d98
7
+ data.tar.gz: 1f25851b50857fbbf8378216794f26d0d8e9baa247f008feac466a218ae6b0777249252b6d05756e075096c5312b9d3b1334b7c4bc1884251e7b892cc17ae7c6
data/CHANGELOG CHANGED
@@ -1,3 +1,15 @@
1
+ === 5.75.0 (2023-12-01)
2
+
3
+ * Make any_not_empty? extension support passing pattern argument to any? (jeremyevans) (#2100)
4
+
5
+ * Respect :skip_transaction option in PostgreSQL Dataset#paged_each (jeremyevans) (#2097)
6
+
7
+ * Add TimestampMigrator.run_single to run a single migration file up or down (opya, jeremyevans) (#2093)
8
+
9
+ * Support INSERT RETURNING on MariaDB 10.5+, and use it when saving new model objects (jeremyevans)
10
+
11
+ * Add Database#{defer,immediate}_constraints on PostgreSQL for changing handling of deferrable constraints in a transaction (jeremyevans)
12
+
1
13
  === 5.74.0 (2023-11-01)
2
14
 
3
15
  * Make generated columns show up in Database#schema when using SQLite 3.37+ (jeremyevans) (#2087)
@@ -0,0 +1,35 @@
1
+ = New Features
2
+
3
+ * Database#{defer,immediate}_constraints methods have been added on
4
+ PostgreSQL for changing handling of deferrable constraints inside
5
+ a transaction. defer_constraints sets deferrable constraints to
6
+ be deferred (not checked until transaction commit), and
7
+ immediate_constraints sets deferrable constraints to be checked
8
+ as part of the related query, and any already deferred constraint
9
+ checks to be applied immediately. You can pass the :constraints
10
+ option to only apply the changes to specific constraints.
11
+
12
+ * TimestampMigrator.run_single has been added, to migrate a single
13
+ migration up or down.
14
+
15
+ = Other Improvements
16
+
17
+ * INSERT RETURNING is now supported on MariaDB 10.5+, and used
18
+ automatically when saving new model objects. Note that this
19
+ is not supported when using the jdbc adapter, because the
20
+ jdbc-mysql driver doesn't support it. A jdbc/mariadb adapter
21
+ could be added, as it's likely recent versions of the
22
+ jdbc-mariadb driver would support it, but the jdbc-mariadb gem
23
+ hasn't been updated in over 4 years. Talk to the jdbc-mariadb
24
+ gem maintainers if you want to use this feature with the jdbc
25
+ adapter.
26
+
27
+ * The Dataset#paged_each optimization in the postgres adapter
28
+ now respects the :skip_transaction option, making it the
29
+ same as the :hold option. Note that this has effects beyond
30
+ just skipping the transaction, but non-HOLD cursors are only
31
+ supported inside transactions.
32
+
33
+ * The any_not_empty? extension's Dataset#any? method now supports
34
+ an argument, passing it to Enumerable#any? (which has supported
35
+ an argument since Ruby 2.5).
@@ -672,6 +672,7 @@ module Sequel
672
672
  # cursor usage.
673
673
  # :rows_per_fetch :: The number of rows per fetch (default 1000). Higher
674
674
  # numbers result in fewer queries but greater memory use.
675
+ # :skip_transaction :: Same as :hold, but :hold takes priority.
675
676
  #
676
677
  # Usage:
677
678
  #
@@ -764,13 +765,13 @@ module Sequel
764
765
 
765
766
  # Use a cursor to fetch groups of records at a time, yielding them to the block.
766
767
  def cursor_fetch_rows(sql)
767
- server_opts = {:server=>@opts[:server] || :read_only}
768
768
  cursor = @opts[:cursor]
769
- hold = cursor[:hold]
769
+ hold = cursor.fetch(:hold){cursor[:skip_transaction]}
770
+ server_opts = {:server=>@opts[:server] || :read_only, :skip_transaction=>hold}
770
771
  cursor_name = quote_identifier(cursor[:cursor_name] || 'sequel_cursor')
771
772
  rows_per_fetch = cursor[:rows_per_fetch].to_i
772
773
 
773
- db.public_send(*(hold ? [:synchronize, server_opts[:server]] : [:transaction, server_opts])) do
774
+ db.transaction(server_opts) do
774
775
  begin
775
776
  execute_ddl("DECLARE #{cursor_name} NO SCROLL CURSOR WITH#{'OUT' unless hold} HOLD FOR #{sql}", server_opts)
776
777
  rows_per_fetch = 1000 if rows_per_fetch <= 0
@@ -646,7 +646,7 @@ module Sequel
646
646
  MATCH_AGAINST_BOOLEAN = ["MATCH ".freeze, " AGAINST (".freeze, " IN BOOLEAN MODE)".freeze].freeze
647
647
 
648
648
  Dataset.def_sql_method(self, :delete, %w'with delete from where order limit')
649
- Dataset.def_sql_method(self, :insert, %w'insert ignore into columns values on_duplicate_key_update')
649
+ Dataset.def_sql_method(self, :insert, %w'insert ignore into columns values on_duplicate_key_update returning')
650
650
  Dataset.def_sql_method(self, :select, %w'with select distinct calc_found_rows columns from join where group having window compounds order limit lock')
651
651
  Dataset.def_sql_method(self, :update, %w'with update ignore table set where order limit')
652
652
 
@@ -774,6 +774,21 @@ module Sequel
774
774
  clone(:insert_ignore=>true)
775
775
  end
776
776
 
777
+ # Support insert select for associations, so that the model code can use
778
+ # returning instead of a separate query.
779
+ def insert_select(*values)
780
+ return unless supports_insert_select?
781
+ # Handle case where query does not return a row
782
+ server?(:default).with_sql_first(insert_select_sql(*values)) || false
783
+ end
784
+
785
+ # The SQL to use for an insert_select, adds a RETURNING clause to the insert
786
+ # unless the RETURNING clause is already present.
787
+ def insert_select_sql(*values)
788
+ ds = opts[:returning] ? self : returning
789
+ ds.insert_sql(*values)
790
+ end
791
+
777
792
  # Sets up the insert methods to use ON DUPLICATE KEY UPDATE
778
793
  # If you pass no arguments, ALL fields will be
779
794
  # updated with the new values. If you pass the fields you
@@ -871,6 +886,11 @@ module Sequel
871
886
  true
872
887
  end
873
888
 
889
+ # MariaDB 10.5.0 supports INSERT RETURNING.
890
+ def supports_returning?(type)
891
+ (type == :insert && db.mariadb? && db.adapter_scheme != :jdbc) ? (db.server_version >= 100500) : false
892
+ end
893
+
874
894
  # MySQL 8+ supports SKIP LOCKED.
875
895
  def supports_skip_locked?
876
896
  !db.mariadb? && db.server_version >= 80000
@@ -498,6 +498,25 @@ module Sequel
498
498
  :postgres
499
499
  end
500
500
 
501
+ # For constraints that are deferrable, defer constraints until
502
+ # transaction commit. Options:
503
+ #
504
+ # :constraints :: An identifier of the constraint, or an array of
505
+ # identifiers for constraints, to apply this
506
+ # change to specific constraints.
507
+ # :server :: The server/shard on which to run the query.
508
+ #
509
+ # Examples:
510
+ #
511
+ # DB.defer_constraints
512
+ # # SET CONSTRAINTS ALL DEFERRED
513
+ #
514
+ # DB.defer_constraints(constraints: [:c1, Sequel[:sc][:c2]])
515
+ # # SET CONSTRAINTS "c1", "sc"."s2" DEFERRED
516
+ def defer_constraints(opts=OPTS)
517
+ _set_constraints(' DEFERRED', opts)
518
+ end
519
+
501
520
  # Use PostgreSQL's DO syntax to execute an anonymous code block. The code should
502
521
  # be the literal code string to use in the underlying procedural language. Options:
503
522
  #
@@ -611,6 +630,24 @@ module Sequel
611
630
  super
612
631
  end
613
632
 
633
+ # Immediately apply deferrable constraints.
634
+ #
635
+ # :constraints :: An identifier of the constraint, or an array of
636
+ # identifiers for constraints, to apply this
637
+ # change to specific constraints.
638
+ # :server :: The server/shard on which to run the query.
639
+ #
640
+ # Examples:
641
+ #
642
+ # DB.immediate_constraints
643
+ # # SET CONSTRAINTS ALL IMMEDIATE
644
+ #
645
+ # DB.immediate_constraints(constraints: [:c1, Sequel[:sc][:c2]])
646
+ # # SET CONSTRAINTS "c1", "sc"."s2" IMMEDIATE
647
+ def immediate_constraints(opts=OPTS)
648
+ _set_constraints(' IMMEDIATE', opts)
649
+ end
650
+
614
651
  # Use the pg_* system tables to determine indexes on a table
615
652
  def indexes(table, opts=OPTS)
616
653
  m = output_identifier_meth
@@ -1038,6 +1075,23 @@ module Sequel
1038
1075
  end
1039
1076
  end
1040
1077
 
1078
+ # Internals of defer_constraints/immediate_constraints
1079
+ def _set_constraints(type, opts)
1080
+ execute_ddl(_set_constraints_sql(type, opts), opts)
1081
+ end
1082
+
1083
+ # SQL to use for SET CONSTRAINTS
1084
+ def _set_constraints_sql(type, opts)
1085
+ sql = String.new
1086
+ sql << "SET CONSTRAINTS "
1087
+ if constraints = opts[:constraints]
1088
+ dataset.send(:source_list_append, sql, Array(constraints))
1089
+ else
1090
+ sql << "ALL"
1091
+ end
1092
+ sql << type
1093
+ end
1094
+
1041
1095
  def alter_table_add_column_sql(table, op)
1042
1096
  "ADD COLUMN#{' IF NOT EXISTS' if op[:if_not_exists]} #{column_definition_sql(op)}"
1043
1097
  end
@@ -32,8 +32,8 @@
32
32
  module Sequel
33
33
  module AnyNotEmpty
34
34
  # If a block is not given, return whether the dataset is not empty.
35
- def any?
36
- if defined?(yield)
35
+ def any?(*a)
36
+ if !a.empty? || defined?(yield)
37
37
  super
38
38
  else
39
39
  !empty?
@@ -693,6 +693,13 @@ module Sequel
693
693
  @migration_tuples = get_migration_tuples
694
694
  end
695
695
 
696
+ # Apply the migration in the given file path. See Migrator.run for the
697
+ # available options. Additionally, this method supports the :direction
698
+ # option for whether to run the migration up (default) or down.
699
+ def self.run_single(db, path, opts=OPTS)
700
+ new(db, File.dirname(path), opts).run_single(path, opts[:direction] || :up)
701
+ end
702
+
696
703
  # The timestamp migrator is current if there are no migrations to apply
697
704
  # in either direction.
698
705
  def is_current?
@@ -702,20 +709,39 @@ module Sequel
702
709
  # Apply all migration tuples on the database
703
710
  def run
704
711
  migration_tuples.each do |m, f, direction|
705
- t = Time.now
706
- db.log_info("Begin applying migration #{f}, direction: #{direction}")
707
- checked_transaction(m) do
708
- m.apply(db, direction)
709
- fi = f.downcase
710
- direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete
711
- end
712
- db.log_info("Finished applying migration #{f}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
712
+ apply_migration(m, f, direction)
713
713
  end
714
714
  nil
715
715
  end
716
716
 
717
+ # Apply single migration tuple at the given path with the given direction
718
+ # on the database.
719
+ def run_single(path, direction)
720
+ migration = load_migration_file(path)
721
+ file_name = File.basename(path)
722
+ already_applied = applied_migrations.include?(file_name.downcase)
723
+
724
+ return if direction == :up ? already_applied : !already_applied
725
+
726
+ apply_migration(migration, file_name, direction)
727
+ nil
728
+ end
729
+
717
730
  private
718
731
 
732
+ # Apply a single migration with the given filename in the given direction.
733
+ def apply_migration(migration, file_name, direction)
734
+ fi = file_name.downcase
735
+ t = Time.now
736
+
737
+ db.log_info("Begin applying migration #{file_name}, direction: #{direction}")
738
+ checked_transaction(migration) do
739
+ migration.apply(db, direction)
740
+ direction == :up ? ds.insert(column=>fi) : ds.where(column=>fi).delete
741
+ end
742
+ db.log_info("Finished applying migration #{file_name}, direction: #{direction}, took #{sprintf('%0.6f', Time.now - t)} seconds")
743
+ end
744
+
719
745
  # Convert the schema_info table to the new schema_migrations table format,
720
746
  # using the version of the schema_info table and the current migration files.
721
747
  def convert_from_schema_info
@@ -325,7 +325,7 @@ module Sequel
325
325
  # DB.alter_table(:ce_test) do
326
326
  # c = Sequel[:encrypted_column_name]
327
327
  # add_constraint(:enc_base64) do
328
- # octet_length(decode(regexp_replace(regexp_replace(c, '_', '/', 'g'), '-', '+', 'g'), 'base64')) >= 65}
328
+ # octet_length(decode(regexp_replace(regexp_replace(c, '_', '/', 'g'), '-', '+', 'g'), 'base64')) >= 65
329
329
  # end
330
330
  # end
331
331
  #
@@ -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 = 74
9
+ MINOR = 75
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.74.0
4
+ version: 5.75.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: 2023-11-01 00:00:00.000000000 Z
11
+ date: 2023-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -221,6 +221,7 @@ extra_rdoc_files:
221
221
  - doc/release_notes/5.72.0.txt
222
222
  - doc/release_notes/5.73.0.txt
223
223
  - doc/release_notes/5.74.0.txt
224
+ - doc/release_notes/5.75.0.txt
224
225
  - doc/release_notes/5.8.0.txt
225
226
  - doc/release_notes/5.9.0.txt
226
227
  files:
@@ -323,6 +324,7 @@ files:
323
324
  - doc/release_notes/5.72.0.txt
324
325
  - doc/release_notes/5.73.0.txt
325
326
  - doc/release_notes/5.74.0.txt
327
+ - doc/release_notes/5.75.0.txt
326
328
  - doc/release_notes/5.8.0.txt
327
329
  - doc/release_notes/5.9.0.txt
328
330
  - doc/schema_modification.rdoc