Skip to content

9.46.0

Choose a tag to compare

@jeremydmiller jeremydmiller released this 19 Oct 18:34
· 18 commits to master since this release

Four fixes. Three are cases where Weasel reported or did the wrong thing while every check said the schema was fine; the fourth reached anyone publishing trimmed or natively compiled. See the 9.46 notes.

Nothing public was removed and no signature changed. One member was added to Migrator, with a default implementation, so existing subclasses keep working.

PostgreSQL

  • A half-built concurrent partitioned index can be finished (#718, contributed by @lahma). A concurrent index on a partitioned table that stopped partway through — a uniqueness violation, a cancelled build, a process that died between a build and its attach — could never be finished. Weasel already read the invalid parent as drift and rebuilt it by dropping it first, but dropping a partitioned index removes only the children attached to it, and the child of the partition the run stopped at was never attached. So the rebuild asked for the same name again and failed with 42P07: relation "…" already exists, on every run, because nothing ever removed the leftover. Each partition's step now begins with a DROP INDEX CONCURRENTLY IF EXISTS for that child, so a database stuck in this state finishes the index on its next apply.

  • Advisory lock holders are read from the current database only (#719 / #725). AdvisoryLock.FindHolderAsync queried pg_locks without scoping it to a database. An advisory lock is taken on the acquiring session's database — two databases on one server hold the same id independently, and pg_try_advisory_lock for an id a neighbour holds returns true — while pg_locks is server-wide. So the read reported a lock as held, with a pid and an application name, for a lock this node could have taken. Database-per-tenant deployments and parallel test lanes share a server and reuse lock ids, so they hit it by construction. Weasel.SqlServer never had this; its equivalent read already filtered on DB_ID().

Firebird

  • A catalog read that raced a rewrite is read again (#723 / #728). Firebird keeps a view's, routine's and trigger's source in a BLOB, and a catalog row carries only the BLOB's id; the client fetches the blob in a later round trip. A concurrent CREATE OR ALTER replaces the record version the id came from, and the blob can be collected before that fetch — BLOB not found, error 335544382, for something no reader did wrong. It is a read failure, not a statement failure, which is why Firebird's existing statement retry never covered it: a statement never produces this error. Migrator gained IsConcurrentIntrospectionFailure and SchemaMigration.DetermineAsync(conn, migrator, …) now re-reads the whole set, up to three attempts with a jittered backoff. Every other provider answers false, so nothing else changes.

Weasel.Core

  • No more trim warning (#724, contributed by @lahma). MultiCommandDataReader.GetFieldType(int) overrode DbDataReader.GetFieldType(int) without repeating the base method's [return: DynamicallyAccessedMembers(…)], so a trimmed or natively published application that keeps the type reported IL2093 — surfacing as IL2104: Assembly 'Weasel.Core' produced trim warnings. Any application running a compiled batch through CommandBuilderExtensions.ExecuteReaderAsync keeps it, whichever database it talks to. Found through Quartz.NET's trim canary (quartznet/quartznet#4129).

What changes for you

  • Generated PostgreSQL DDL for a concurrent index on a partitioned table carries new statements — a DROP INDEX CONCURRENTLY IF EXISTS <schema>.<child>; per partition. Update expected text if you assert on it. Nothing changes for a non-partitioned index, or a partitioned index built non-concurrently.
  • AdvisoryLock.FindHolderAsync returns null where it used to name a holder in another database. That answer was wrong, but tooling that treated any non-null result as "someone holds this" will now correctly see the lock as free.
  • Migrator has a new virtual, IsConcurrentIntrospectionFailure(Exception), defaulting to false. Existing subclasses compile and behave exactly as before.
  • A Firebird migration may make up to three introspection attempts instead of one. Anything that is not BLOB not found still surfaces on the first attempt.

Two internal CI fixes also landed with no effect on the packages: #720 removed a Postgres matrix leg that tested nothing, and #721 put Weasel.CommandLine.Tests into a workflow — it had been run by none.