sequel 5.76.0 → 5.77.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.
- checksums.yaml +4 -4
- data/CHANGELOG +20 -0
- data/doc/release_notes/5.76.0.txt +1 -1
- data/doc/release_notes/5.77.0.txt +63 -0
- data/doc/testing.rdoc +2 -1
- data/lib/sequel/adapters/shared/sqlite.rb +15 -2
- data/lib/sequel/adapters/sqlite.rb +21 -3
- data/lib/sequel/connection_pool.rb +4 -2
- data/lib/sequel/database/misc.rb +2 -2
- data/lib/sequel/database/schema_methods.rb +6 -0
- data/lib/sequel/extensions/duplicate_columns_handler.rb +10 -9
- data/lib/sequel/extensions/transaction_connection_validator.rb +78 -0
- data/lib/sequel/model/associations.rb +9 -2
- data/lib/sequel/model/base.rb +5 -2
- data/lib/sequel/plugins/list.rb +5 -2
- data/lib/sequel/plugins/validation_helpers.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- metadata +5 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 9951772dd3785c8ce91090bd31034a1e57ac5dcbc17af774b980a115cea15347
         | 
| 4 | 
            +
              data.tar.gz: 3cfcaefaf6aa4758ef2cfaf78cbe6ccdc688e8b3836718bd63c42c5bdb220026
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: '0885577c11fd7285a5278d0a1b52ae411e557cec7bce2f3a49f8128a0be63928ebfa55b2b1a86c8b28ee1c3782c1dc5ebf5d4ecf00f0194ad33da89cb6ffc12a'
         | 
| 7 | 
            +
              data.tar.gz: ccc7b8b6c68049ee1fed2211a3d193157ee36fde9c340324eba2a8cebd8925bc97b4dc1777b61f8a2fb94d83439c41f33afb832c080f4d54bab16d09924a4fe2
         | 
    
        data/CHANGELOG
    CHANGED
    
    | @@ -1,3 +1,23 @@ | |
| 1 | 
            +
            === 5.77.0 (2024-02-01)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Support create_table :without_rowid option on SQLite (loranger32) (#2126)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            * Warn by default if trying to eager_graph/association_join an association that uses a block, when the block would be ignored (jeremyevans)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Speed up validates_unique in validation_helpers plugin by using empty? instead of count == 0 (numbata) (#2122)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Speed up regexp matches in sqlite adapter on Ruby 2.4+ (jeremyevans)
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * Add sqlite adapter :regexp_function_cache option for specifying the cache object to use (paddor, jeremyevans) (#2116)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            * Respect list plugin :top option when inserting the first row into the model's table (johanmagnusson) (#2115)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            * Switch default connection pool to timed_queue on Ruby 3.4+ (jeremyevans)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            * Support on_duplicate_columns={raise,warn} parameter in connection URL when using duplicate_columns_handler extension (jeremyevans)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * Add transaction_connection_validator extension for retrying transactions on new connection if ther is a disconnect error when starting transaction (jeremyevans)
         | 
| 20 | 
            +
             | 
| 1 21 | 
             
            === 5.76.0 (2024-01-01)
         | 
| 2 22 |  | 
| 3 23 | 
             
            * Improve performance and flexibility of regexp matching in sqlite adapter (paddor) (#2108)
         | 
| @@ -42,7 +42,7 @@ | |
| 42 42 |  | 
| 43 43 | 
             
            = Other Improvements
         | 
| 44 44 |  | 
| 45 | 
            -
            * Time/DateTime/ | 
| 45 | 
            +
            * Time/DateTime/SQLTime literalization speed has more than doubled
         | 
| 46 46 | 
             
              compared to the previous version.  The internal code is also much
         | 
| 47 47 | 
             
              simpler, as the speedup resulted from removing multiple abstraction
         | 
| 48 48 | 
             
              layers that mostly existed for Ruby 1.8 support.
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            = New Features
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * A transaction_connection_validator extension has been added.  This
         | 
| 4 | 
            +
              extension allows for transparently switching to a new connection if
         | 
| 5 | 
            +
              a disconnect error is raised while trying to start a transaction, as
         | 
| 6 | 
            +
              long as a connection was not already checked out from the pool
         | 
| 7 | 
            +
              when the transaction method was called.  Transparent reconnection
         | 
| 8 | 
            +
              is safe in this case, since no user code is retried.
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              This extension can have lower overhead than the
         | 
| 11 | 
            +
              connection_validator extension if that is configured to check for
         | 
| 12 | 
            +
              validity more often than the default of one hour.  However, it
         | 
| 13 | 
            +
              only handles cases where transactions are used.  It can detect
         | 
| 14 | 
            +
              disconnects that would not be detected by default with the
         | 
| 15 | 
            +
              connection_validator extension, since that extension defaults to
         | 
| 16 | 
            +
              only checking validity if the connection has not been used in the
         | 
| 17 | 
            +
              last hour.
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            * Sequel now supports a create_table :without_rowid option on SQLite,
         | 
| 20 | 
            +
              to create a table WITHOUT ROWID, for better performance in some
         | 
| 21 | 
            +
              cases. Users are encouraged to read the SQLite documentation on
         | 
| 22 | 
            +
              WITHOUT ROWID before using this option.
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            * The sqlite adapter now supports a :regexp_function_cache option, if
         | 
| 25 | 
            +
              the :setup_regexp_function option is set to :cached.  The
         | 
| 26 | 
            +
              :regexp_function_cache option should be a Proc (returning a cache
         | 
| 27 | 
            +
              object to use), or a class.  It's possible to use
         | 
| 28 | 
            +
              ObjectSpace::WeakKeyMap as the value of the option on Ruby 3.3+
         | 
| 29 | 
            +
              to avoid the memory leaks that are possible when using
         | 
| 30 | 
            +
              :setup_regexp_function option :cached value with dynamic regexps.
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            * The duplicate_columns_handler extension now supports specifying
         | 
| 33 | 
            +
              the on_duplicate_columns option as a connection string parameter.
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            = Other Improvements
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            * The list plugin now honors the :top option for the position when
         | 
| 38 | 
            +
              adding the first item to the list, instead of always using 1.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            * Regexp matches on SQLite are now faster on Ruby 2.4+, using
         | 
| 41 | 
            +
              Regexp#match?.
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            * The uniqueness validation in the validation_helpers plugin now
         | 
| 44 | 
            +
              uses empty? instead of count == 0, for better performance.
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            * On Ruby 3.4+, Sequel uses the timed_queue connection pool instead
         | 
| 47 | 
            +
              of the threaded connection pool by default.  This should make it
         | 
| 48 | 
            +
              so no existing applications are affected by the default switch.
         | 
| 49 | 
            +
              This should hopefully allow ample testing of the timed_queue
         | 
| 50 | 
            +
              connection pool.  At some point in the future, if no problems
         | 
| 51 | 
            +
              are repoted, Sequel will likely switch to using the timed_queue
         | 
| 52 | 
            +
              connection pool by default on Ruby 3.2+.
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            = Backwards Compatibility
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            * Sequel now warns by default if using eager_graph/association_join
         | 
| 57 | 
            +
              with an association that uses a block, in the cases where the
         | 
| 58 | 
            +
              block would be ignored and there are no appropriate graph options
         | 
| 59 | 
            +
              set. In Sequel 6, this warning will be turned into an exception.
         | 
| 60 | 
            +
              It is recommended that users use the auto_restrict_eager_graph
         | 
| 61 | 
            +
              plugin to turn this into an exception now, or use the
         | 
| 62 | 
            +
              :graph_use_association_block option so that the block is not
         | 
| 63 | 
            +
              ignored when graphing.
         | 
    
        data/doc/testing.rdoc
    CHANGED
    
    | @@ -165,7 +165,7 @@ SEQUEL_ASYNC_THREAD_POOL_PREEMPT :: Use the async_thread_pool extension when run | |
| 165 165 | 
             
            SEQUEL_CHECK_PENDING :: Try running all specs (note, can cause lockups for some adapters), and raise errors for skipped specs that don't fail
         | 
| 166 166 | 
             
            SEQUEL_COLUMNS_INTROSPECTION :: Use the columns_introspection extension when running the specs
         | 
| 167 167 | 
             
            SEQUEL_CONCURRENT_EAGER_LOADING :: Use the async_thread_pool extension and concurrent_eager_loading plugin when running the specs
         | 
| 168 | 
            -
            SEQUEL_CONNECTION_VALIDATOR :: Use the  | 
| 168 | 
            +
            SEQUEL_CONNECTION_VALIDATOR :: Use the connection_validator extension when running the adapter/integration specs
         | 
| 169 169 | 
             
            SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
         | 
| 170 170 | 
             
            SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
         | 
| 171 171 | 
             
            SEQUEL_FIBER_CONCURRENCY :: Use the fiber_concurrency extension when running the adapter and integration specs
         | 
| @@ -186,4 +186,5 @@ SEQUEL_QUERY_PER_ASSOCIATION_DB_2_URL :: Run query-per-association integration t | |
| 186 186 | 
             
            SEQUEL_QUERY_PER_ASSOCIATION_DB_3_URL :: Run query-per-association integration tests with multiple databases (all 4 must be set to run)
         | 
| 187 187 | 
             
            SEQUEL_SPLIT_SYMBOLS :: Turn on symbol splitting when running the adapter and integration specs
         | 
| 188 188 | 
             
            SEQUEL_SYNCHRONIZE_SQL :: Use the synchronize_sql extension when running the specs
         | 
| 189 | 
            +
            SEQUEL_TRANSACTION_CONNECTION_VALIDATOR :: Use the transaction_connection_validator extension when running the adapter/integration specs
         | 
| 189 190 | 
             
            SEQUEL_TZINFO_VERSION :: Force the given tzinfo version when running the specs (e.g. '>=2')
         | 
| @@ -145,6 +145,11 @@ module Sequel | |
| 145 145 | 
             
                    sqlite_version >= 30608
         | 
| 146 146 | 
             
                  end
         | 
| 147 147 |  | 
| 148 | 
            +
                  # SQLite 3.8.2+ supports the without rowid table constraint
         | 
| 149 | 
            +
                  def support_without_rowid?
         | 
| 150 | 
            +
                    sqlite_version >= 30802
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
             | 
| 148 153 | 
             
                  # Override the default setting for whether to use timezones in timestamps.
         | 
| 149 154 | 
             
                  # It is set to +false+ by default, as SQLite's date/time methods do not
         | 
| 150 155 | 
             
                  # support timezones in timestamps.
         | 
| @@ -344,9 +349,17 @@ module Sequel | |
| 344 349 | 
             
                    ps
         | 
| 345 350 | 
             
                  end
         | 
| 346 351 |  | 
| 347 | 
            -
                  # Support creating STRICT tables via :strict  | 
| 352 | 
            +
                  # Support creating STRICT AND/OR WITHOUT ROWID tables via :strict and :without_rowid options
         | 
| 348 353 | 
             
                  def create_table_sql(name, generator, options)
         | 
| 349 | 
            -
                     | 
| 354 | 
            +
                    if options[:strict] && options[:without_rowid]
         | 
| 355 | 
            +
                      "#{super} STRICT, WITHOUT ROWID"
         | 
| 356 | 
            +
                    elsif options[:strict]
         | 
| 357 | 
            +
                      "#{super} STRICT"
         | 
| 358 | 
            +
                    elsif options[:without_rowid]
         | 
| 359 | 
            +
                      "#{super} WITHOUT ROWID"
         | 
| 360 | 
            +
                    else
         | 
| 361 | 
            +
                      super
         | 
| 362 | 
            +
                    end
         | 
| 350 363 | 
             
                  end
         | 
| 351 364 |  | 
| 352 365 | 
             
                  # SQLite support creating temporary views.
         | 
| @@ -118,6 +118,11 @@ module Sequel | |
| 118 118 | 
             
                  #             it will be called with a string for the regexp and a string
         | 
| 119 119 | 
             
                  #             for the value to compare, and should return whether the regexp
         | 
| 120 120 | 
             
                  #             matches.
         | 
| 121 | 
            +
                  # :regexp_function_cache :: If setting +setup_regexp_function+ to +cached+, this
         | 
| 122 | 
            +
                  #             determines the cache to use.  It should either be a proc or a class, and it
         | 
| 123 | 
            +
                  #             defaults to +Hash+. You can use +ObjectSpace::WeakKeyMap+ on Ruby 3.3+ to
         | 
| 124 | 
            +
                  #             have the VM automatically remove regexps from the cache after they
         | 
| 125 | 
            +
                  #             are no longer used.
         | 
| 121 126 | 
             
                  def connect(server)
         | 
| 122 127 | 
             
                    opts = server_opts(server)
         | 
| 123 128 | 
             
                    opts[:database] = ':memory:' if blank_object?(opts[:database])
         | 
| @@ -213,10 +218,23 @@ module Sequel | |
| 213 218 | 
             
                    when Proc
         | 
| 214 219 | 
             
                      # nothing
         | 
| 215 220 | 
             
                    when :cached, "cached"
         | 
| 216 | 
            -
                      cache =  | 
| 217 | 
            -
                       | 
| 221 | 
            +
                      cache = @opts[:regexp_function_cache] || Hash
         | 
| 222 | 
            +
                      cache = cache.is_a?(Proc) ? cache.call : cache.new
         | 
| 223 | 
            +
                      how = if RUBY_VERSION >= '2.4'
         | 
| 224 | 
            +
                        lambda do |regexp_str, str|
         | 
| 225 | 
            +
                          (cache[regexp_str] ||= Regexp.new(regexp_str)).match?(str)
         | 
| 226 | 
            +
                        end
         | 
| 227 | 
            +
                      else
         | 
| 228 | 
            +
                        lambda do |regexp_str, str|
         | 
| 229 | 
            +
                          (cache[regexp_str] ||= Regexp.new(regexp_str)).match(str)
         | 
| 230 | 
            +
                        end
         | 
| 231 | 
            +
                      end
         | 
| 218 232 | 
             
                    else
         | 
| 219 | 
            -
                      how =  | 
| 233 | 
            +
                      how = if RUBY_VERSION >= '2.4'
         | 
| 234 | 
            +
                        lambda{|regexp_str, str| Regexp.new(regexp_str).match?(str)}
         | 
| 235 | 
            +
                      else
         | 
| 236 | 
            +
                        lambda{|regexp_str, str| Regexp.new(regexp_str).match(str)}
         | 
| 237 | 
            +
                      end
         | 
| 220 238 | 
             
                    end
         | 
| 221 239 |  | 
| 222 240 | 
             
                    db.create_function("regexp", 2) do |func, regexp_str, str|
         | 
| @@ -70,8 +70,10 @@ class Sequel::ConnectionPool | |
| 70 70 | 
             
                  else
         | 
| 71 71 | 
             
                    pc = if opts[:single_threaded]
         | 
| 72 72 | 
             
                      opts[:servers] ? :sharded_single : :single
         | 
| 73 | 
            -
                    # | 
| 74 | 
            -
                    # | 
| 73 | 
            +
                    # :nocov:
         | 
| 74 | 
            +
                    elsif RUBY_VERSION >= '3.4' # SEQUEL6 or maybe earlier switch to 3.2
         | 
| 75 | 
            +
                      opts[:servers] ? :sharded_timed_queue : :timed_queue
         | 
| 76 | 
            +
                    # :nocov:
         | 
| 75 77 | 
             
                    else
         | 
| 76 78 | 
             
                      opts[:servers] ? :sharded_threaded : :threaded
         | 
| 77 79 | 
             
                    end
         | 
    
        data/lib/sequel/database/misc.rb
    CHANGED
    
    | @@ -263,8 +263,8 @@ module Sequel | |
| 263 263 | 
             
                # Proxy the literal call to the dataset.
         | 
| 264 264 | 
             
                #
         | 
| 265 265 | 
             
                #   DB.literal(1)   # 1
         | 
| 266 | 
            -
                #   DB.literal(:a)  # a
         | 
| 267 | 
            -
                #   DB.literal( | 
| 266 | 
            +
                #   DB.literal(:a)  # "a" # or `a`, [a], or a, depending on identifier quoting
         | 
| 267 | 
            +
                #   DB.literal("a") # 'a'
         | 
| 268 268 | 
             
                def literal(v)
         | 
| 269 269 | 
             
                  schema_utility_dataset.literal(v)
         | 
| 270 270 | 
             
                end
         | 
| @@ -191,6 +191,12 @@ module Sequel | |
| 191 191 | 
             
                #            The +any+ type is treated like a SQLite column in a non-strict table,
         | 
| 192 192 | 
             
                #            allowing any type of data to be stored. This option is supported on
         | 
| 193 193 | 
             
                #            SQLite 3.37.0+.
         | 
| 194 | 
            +
                # :without_rowid :: Create a WITHOUT ROWID table. Every row in SQLite has a special
         | 
| 195 | 
            +
                #                   'rowid' column, that uniquely identifies that row within the table.
         | 
| 196 | 
            +
                #                   If this option is used, the 'rowid' column is omitted, which can
         | 
| 197 | 
            +
                #                   sometimes provide some space and speed advantages. Note that you
         | 
| 198 | 
            +
                #                   must then provide an explicit primary key when you create the table.
         | 
| 199 | 
            +
                #                   This option is supported on SQLite 3.8.2+.
         | 
| 194 200 | 
             
                #
         | 
| 195 201 | 
             
                # See <tt>Schema::CreateTableGenerator</tt> and the {"Schema Modification" guide}[rdoc-ref:doc/schema_modification.rdoc].
         | 
| 196 202 | 
             
                def create_table(name, options=OPTS, &block)
         | 
| @@ -14,12 +14,12 @@ | |
| 14 14 | 
             
            #
         | 
| 15 15 | 
             
            #   ds = DB[:items].extension(:duplicate_columns_handler)
         | 
| 16 16 | 
             
            #
         | 
| 17 | 
            -
            #  | 
| 18 | 
            -
            # or any object that responds to :call.
         | 
| 17 | 
            +
            # If the Database option :on_duplicate_columns is set, it configures how this
         | 
| 18 | 
            +
            # extension works. The value should be # or any object that responds to :call.
         | 
| 19 19 | 
             
            #
         | 
| 20 | 
            -
            #   on_duplicate_columns: :raise
         | 
| 21 | 
            -
            #   on_duplicate_columns: :warn
         | 
| 22 | 
            -
            #   on_duplicate_columns: :ignore
         | 
| 20 | 
            +
            #   on_duplicate_columns: :raise # or 'raise'
         | 
| 21 | 
            +
            #   on_duplicate_columns: :warn # or 'warn'
         | 
| 22 | 
            +
            #   on_duplicate_columns: :ignore # or anything unrecognized
         | 
| 23 23 | 
             
            #   on_duplicate_columns: lambda{|columns| arbitrary_condition? ? :raise : :warn}
         | 
| 24 24 | 
             
            #
         | 
| 25 25 | 
             
            # You may also configure duplicate columns handling for a specific dataset:
         | 
| @@ -30,9 +30,10 @@ | |
| 30 30 | 
             
            #   ds.on_duplicate_columns{|columns| arbitrary_condition? ? :raise : :warn}
         | 
| 31 31 | 
             
            #   ds.on_duplicate_columns(lambda{|columns| arbitrary_condition? ? :raise : :warn})
         | 
| 32 32 | 
             
            #
         | 
| 33 | 
            -
            # If :raise is specified, a Sequel::DuplicateColumnError is raised.
         | 
| 34 | 
            -
            # If :warn is specified, you will receive a warning via +warn+.
         | 
| 33 | 
            +
            # If :raise or 'raise' is specified, a Sequel::DuplicateColumnError is raised.
         | 
| 34 | 
            +
            # If :warn or 'warn' is specified, you will receive a warning via +warn+.
         | 
| 35 35 | 
             
            # If a callable is specified, it will be called.
         | 
| 36 | 
            +
            # For other values, duplicate columns are ignored (Sequel's default behavior)
         | 
| 36 37 | 
             
            # If no on_duplicate_columns is specified, the default is :warn.
         | 
| 37 38 | 
             
            #
         | 
| 38 39 | 
             
            # Related module: Sequel::DuplicateColumnsHandler
         | 
| @@ -64,9 +65,9 @@ module Sequel | |
| 64 65 | 
             
                  message = "#{caller(*CALLER_ARGS).first}: One or more duplicate columns present in #{cols.inspect}"
         | 
| 65 66 |  | 
| 66 67 | 
             
                  case duplicate_columns_handler_type(cols)
         | 
| 67 | 
            -
                  when :raise
         | 
| 68 | 
            +
                  when :raise, 'raise'
         | 
| 68 69 | 
             
                    raise DuplicateColumnError, message
         | 
| 69 | 
            -
                  when :warn
         | 
| 70 | 
            +
                  when :warn, 'warn'
         | 
| 70 71 | 
             
                    warn message
         | 
| 71 72 | 
             
                  end
         | 
| 72 73 | 
             
                end
         | 
| @@ -0,0 +1,78 @@ | |
| 1 | 
            +
            # frozen-string-literal: true
         | 
| 2 | 
            +
            #
         | 
| 3 | 
            +
            # The transaction_connection_validator extension automatically
         | 
| 4 | 
            +
            # retries a transaction on a connection if an disconnect error
         | 
| 5 | 
            +
            # is raised when sending the statement to begin a new
         | 
| 6 | 
            +
            # transaction, as long as the user has not already checked out
         | 
| 7 | 
            +
            # a connection.  This is safe to do because no other queries
         | 
| 8 | 
            +
            # have been issued on the connection, and no user-level code
         | 
| 9 | 
            +
            # is run before retrying.
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            # This approach to connection validation can be significantly
         | 
| 12 | 
            +
            # lower overhead than the connection_validator extension,
         | 
| 13 | 
            +
            # though it does not handle all cases handled by the
         | 
| 14 | 
            +
            # connection_validator extension.  However, it performs the
         | 
| 15 | 
            +
            # validation checks on every new transaction, so it will
         | 
| 16 | 
            +
            # automatically handle disconnected connections in some cases
         | 
| 17 | 
            +
            # where the connection_validator extension will not by default
         | 
| 18 | 
            +
            # (as the connection_validator extension only checks
         | 
| 19 | 
            +
            # connections if they have not been used in the last hour by
         | 
| 20 | 
            +
            # default).
         | 
| 21 | 
            +
            #
         | 
| 22 | 
            +
            # Related module: Sequel::TransactionConnectionValidator
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            #
         | 
| 25 | 
            +
            module Sequel
         | 
| 26 | 
            +
              module TransactionConnectionValidator
         | 
| 27 | 
            +
                class DisconnectRetry < DatabaseDisconnectError
         | 
| 28 | 
            +
                  # The connection that raised the disconnect error
         | 
| 29 | 
            +
                  attr_accessor :connection
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  # The underlying disconnect error, in case it needs to be reraised.
         | 
| 32 | 
            +
                  attr_accessor :database_error
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # Rescue disconnect errors raised when beginning a new transaction.  If there
         | 
| 36 | 
            +
                # is a disconnnect error, it should be safe to retry the transaction using a
         | 
| 37 | 
            +
                # new connection, as we haven't yielded control to the user yet.
         | 
| 38 | 
            +
                def transaction(opts=OPTS)
         | 
| 39 | 
            +
                  super
         | 
| 40 | 
            +
                rescue DisconnectRetry => e
         | 
| 41 | 
            +
                  if synchronize(opts[:server]){|conn| conn.equal?(e.connection)}
         | 
| 42 | 
            +
                    # If retrying would use the same connection, that means the
         | 
| 43 | 
            +
                    # connection was not removed from the pool, which means the caller has
         | 
| 44 | 
            +
                    # already checked out the connection, and retrying will not be successful.
         | 
| 45 | 
            +
                    # In this case, we can only reraise the exception.
         | 
| 46 | 
            +
                    raise e.database_error
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  num_retries ||= 0 
         | 
| 50 | 
            +
                  num_retries += 1
         | 
| 51 | 
            +
                  retry if num_retries < 5
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  raise e.database_error
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                private
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                # Reraise disconnect errors as DisconnectRetry so they can be retried.
         | 
| 59 | 
            +
                def begin_new_transaction(conn, opts)
         | 
| 60 | 
            +
                  super
         | 
| 61 | 
            +
                rescue Sequel::DatabaseDisconnectError, *database_error_classes => e
         | 
| 62 | 
            +
                  if e.is_a?(Sequel::DatabaseDisconnectError) || disconnect_error?(e, OPTS)
         | 
| 63 | 
            +
                    exception = DisconnectRetry.new(e.message)
         | 
| 64 | 
            +
                    exception.set_backtrace([])
         | 
| 65 | 
            +
                    exception.connection = conn
         | 
| 66 | 
            +
                    unless e.is_a?(Sequel::DatabaseError)
         | 
| 67 | 
            +
                      e = Sequel.convert_exception_class(e, database_error_class(e, OPTS))
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                    exception.database_error = e
         | 
| 70 | 
            +
                    raise exception
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  raise
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              Database.register_extension(:transaction_connection_validator, TransactionConnectionValidator)
         | 
| 78 | 
            +
            end
         | 
| @@ -3387,8 +3387,15 @@ module Sequel | |
| 3387 3387 | 
             
                      local_opts = ds.opts[:eager_graph][:local]
         | 
| 3388 3388 | 
             
                      limit_strategy = r.eager_graph_limit_strategy(local_opts[:limit_strategy])
         | 
| 3389 3389 |  | 
| 3390 | 
            -
                       | 
| 3391 | 
            -
             | 
| 3390 | 
            +
                      # SEQUEL6: remove and integrate the auto_restrict_eager_graph plugin
         | 
| 3391 | 
            +
                      if !r[:orig_opts].has_key?(:graph_conditions) && !r[:orig_opts].has_key?(:graph_only_conditions) && !r.has_key?(:graph_block) && !r[:allow_eager_graph]
         | 
| 3392 | 
            +
                        if r[:conditions] && !Sequel.condition_specifier?(r[:conditions])
         | 
| 3393 | 
            +
                          raise Error, "Cannot eager_graph association when :conditions specified and not a hash or an array of pairs.  Specify :graph_conditions, :graph_only_conditions, or :graph_block for the association.  Model: #{r[:model]}, association: #{r[:name]}"
         | 
| 3394 | 
            +
                        end
         | 
| 3395 | 
            +
             | 
| 3396 | 
            +
                        if r[:block] && !r[:graph_use_association_block]
         | 
| 3397 | 
            +
                          warn "eager_graph used for association when association given a block without graph options.  The block is ignored in this case.  This will result in an exception starting in Sequel 6.  Model: #{r[:model]}, association: #{r[:name]}"
         | 
| 3398 | 
            +
                        end
         | 
| 3392 3399 | 
             
                      end
         | 
| 3393 3400 |  | 
| 3394 3401 | 
             
                      ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>join_type || local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
         | 
    
        data/lib/sequel/model/base.rb
    CHANGED
    
    | @@ -1244,18 +1244,21 @@ module Sequel | |
| 1244 1244 | 
             
                    @errors ||= errors_class.new
         | 
| 1245 1245 | 
             
                  end 
         | 
| 1246 1246 |  | 
| 1247 | 
            +
                  EXISTS_SELECT_ = SQL::AliasedExpression.new(1, :one)
         | 
| 1248 | 
            +
                  private_constant :EXISTS_SELECT_
         | 
| 1249 | 
            +
             | 
| 1247 1250 | 
             
                  # Returns true when current instance exists, false otherwise.
         | 
| 1248 1251 | 
             
                  # Generally an object that isn't new will exist unless it has
         | 
| 1249 1252 | 
             
                  # been deleted.  Uses a database query to check for existence,
         | 
| 1250 1253 | 
             
                  # unless the model object is new, in which case this is always
         | 
| 1251 1254 | 
             
                  # false.
         | 
| 1252 1255 | 
             
                  #
         | 
| 1253 | 
            -
                  #   Artist[1].exists? # SELECT 1 FROM artists WHERE (id = 1)
         | 
| 1256 | 
            +
                  #   Artist[1].exists? # SELECT 1 AS one FROM artists WHERE (id = 1)
         | 
| 1254 1257 | 
             
                  #   # => true
         | 
| 1255 1258 | 
             
                  #   Artist.new.exists?
         | 
| 1256 1259 | 
             
                  #   # => false
         | 
| 1257 1260 | 
             
                  def exists?
         | 
| 1258 | 
            -
                    new? ? false : !this.get( | 
| 1261 | 
            +
                    new? ? false : !this.get(EXISTS_SELECT_).nil?
         | 
| 1259 1262 | 
             
                  end
         | 
| 1260 1263 |  | 
| 1261 1264 | 
             
                  # Ignore the model's setter method cache when this instances extends a module, as the
         | 
    
        data/lib/sequel/plugins/list.rb
    CHANGED
    
    | @@ -185,10 +185,13 @@ module Sequel | |
| 185 185 | 
             
                    end
         | 
| 186 186 |  | 
| 187 187 | 
             
                    # Set the value of the position_field to the maximum value plus 1 unless the
         | 
| 188 | 
            -
                    # position field already has a value.
         | 
| 188 | 
            +
                    # position field already has a value. If the list is empty, the position will
         | 
| 189 | 
            +
                    # be set to the model's +top_of_list+ value.
         | 
| 189 190 | 
             
                    def before_validation
         | 
| 190 191 | 
             
                      unless get_column_value(position_field)
         | 
| 191 | 
            -
                         | 
| 192 | 
            +
                        current_max = list_dataset.max(position_field)
         | 
| 193 | 
            +
                        value = current_max.nil? ? model.top_of_list : current_max.to_i + 1
         | 
| 194 | 
            +
                        set_column_value("#{position_field}=", value)
         | 
| 192 195 | 
             
                      end
         | 
| 193 196 | 
             
                      super
         | 
| 194 197 | 
             
                    end
         | 
    
        data/lib/sequel/version.rb
    CHANGED
    
    | @@ -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 =  | 
| 9 | 
            +
              MINOR = 77
         | 
| 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. | 
| 4 | 
            +
              version: 5.77.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: 2024- | 
| 11 | 
            +
            date: 2024-02-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bigdecimal
         | 
| @@ -223,6 +223,7 @@ extra_rdoc_files: | |
| 223 223 | 
             
            - doc/release_notes/5.74.0.txt
         | 
| 224 224 | 
             
            - doc/release_notes/5.75.0.txt
         | 
| 225 225 | 
             
            - doc/release_notes/5.76.0.txt
         | 
| 226 | 
            +
            - doc/release_notes/5.77.0.txt
         | 
| 226 227 | 
             
            - doc/release_notes/5.8.0.txt
         | 
| 227 228 | 
             
            - doc/release_notes/5.9.0.txt
         | 
| 228 229 | 
             
            files:
         | 
| @@ -327,6 +328,7 @@ files: | |
| 327 328 | 
             
            - doc/release_notes/5.74.0.txt
         | 
| 328 329 | 
             
            - doc/release_notes/5.75.0.txt
         | 
| 329 330 | 
             
            - doc/release_notes/5.76.0.txt
         | 
| 331 | 
            +
            - doc/release_notes/5.77.0.txt
         | 
| 330 332 | 
             
            - doc/release_notes/5.8.0.txt
         | 
| 331 333 | 
             
            - doc/release_notes/5.9.0.txt
         | 
| 332 334 | 
             
            - doc/schema_modification.rdoc
         | 
| @@ -515,6 +517,7 @@ files: | |
| 515 517 | 
             
            - lib/sequel/extensions/synchronize_sql.rb
         | 
| 516 518 | 
             
            - lib/sequel/extensions/thread_local_timezones.rb
         | 
| 517 519 | 
             
            - lib/sequel/extensions/to_dot.rb
         | 
| 520 | 
            +
            - lib/sequel/extensions/transaction_connection_validator.rb
         | 
| 518 521 | 
             
            - lib/sequel/extensions/virtual_row_method_block.rb
         | 
| 519 522 | 
             
            - lib/sequel/model.rb
         | 
| 520 523 | 
             
            - lib/sequel/model/associations.rb
         |