Repository navigation
5.0.0 release prep - #32
Merged
Merged
Conversation
A package that depends on another by branch can't be resolved by a version-pinned consumer, so 5.0.0 needs CRUD's release. Resolves to CRUD 3.0.0 (swift-log 1.15.1). No Package.resolved is committed (*.resolved is ignored). 53/53 tests pass against postgres:17 with -warnings-as-errors in debug and release on Xcode 27 (Swift 6.4), Xcode 26.3 (Swift 6.2.4), and Linux swift:6.2-noble / swift:6.4-noble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Modeled on Perfect-CRUD's workflow. Linux runs Swift 6.2 and 6.4 in the swift:X-noble container with libpq-dev and a postgres:17 service (health checked), and runs the live tests with PG_TESTS=1 PGUSER=postgres. The tests connect with host=localhost, which PGHOST can't override, so the job sets libpq's PGHOSTADDR to the service's address; that mechanism was checked locally (Linux containers reaching a separate postgres:17 container through PGHOSTADDR), not on GitHub. macOS runs Xcode 26.0.1 and 26.6 on macos-26 with Homebrew libpq and PKG_CONFIG_PATH (Swift 6.2's SwiftPM doesn't find the keg-only libpq without it); there's no server there, so the live tests skip. No iOS job: libpq is a host system library and the package declares only macOS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…...) The values were pasted into the libpq conninfo string unquoted, so a password (or database, host or user name) containing a space made the string unparseable, and a value such as "x sslmode=disable" added a connection option of its own. Each value is now single-quoted with \ and ' backslash-escaped, as libpq's conninfo syntax requires. The behaviour is unchanged since 4.0.0 for values without spaces, quotes or backslashes. ConnectionInfoTests parses the result with libpq's PQconninfoParse (no server needed) and, with PG_TESTS=1, connects with a password containing a space. Without the fix 4 of the 5 tests fail; plainValues passes on both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Install snippet uses from: "5.0.0" (was branch: "main" with a "no tagged releases" note). - Requirements: Linux is supported and CI-tested; the old text called it implicit and not guaranteed. Badges list macOS 12+ and Linux. - libpq setup: Homebrew's libpq is keg-only; Swift 6.2's SwiftPM doesn't find it without PKG_CONFIG_PATH (checked with Xcode 26.3: 'libpq-fe.h' file not found), Swift 6.4's does. - A usage example, and what the CRUD backend doesn't support: Dynamic select (throws once a row comes back), affectedRows (always 0), insertedID (nil) and transaction isolation levels (ignored). The example and each of these were checked against postgres:17 from a scratch consumer package. - Testing: PG_TESTS, the databases the tests drop, and PGPORT / PGHOSTADDR for other servers. - A "Migrating from 4.x" section and the legacy branch pointer (legacy is the 4.0.0 commit). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Most of them return early and count as passed rather than skipping; only SubTableCreateOrderLiveTests uses .enabled(if:). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checks for the crash patterns found in the Perfect-SQLite review. None
of them applies here, so there's no code change:
- The connector doesn't implement nextDynamicRow(), so Dynamic select
(and execute(DynamicSQL) returning rows) throws CRUD's
CRUDSQLExeError once a row comes back; no DynamicRow is built, so
columns differing only by case (SELECT 1 AS a, 2 AS "A") can't hit
DynamicRow.init's duplicate-key trap. An empty result returns empty.
- DynamicSQL with allowsMultipleStatements: true throws: PQexecParams
takes one statement ("cannot insert multiple commands into a prepared
statement") and neither statement runs. Without the flag, CRUD's
guard throws CRUDSQLGenError.
- Unsigned values are bound as decimal text, with no Int conversion:
.uint(UInt64.max) stores exactly in a numeric column and gets a
server error (not a trap) for a bigint one; .uinteger/.uinteger64/
32/16/8 at their maximums round-trip.
- affectedRows is 0 and insertedID nil for mutations.
62/62 pass against postgres:17 with -warnings-as-errors in debug and
release on Xcode 27, Xcode 26.3, and Linux swift:6.2-noble and
swift:6.4-noble.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Perfect-CRUD 3.0.0's DatabaseConnectionPool, transactionAsync,
sqlAsync, insertAsync, fetchAll and the other async entry points require
a Sendable configuration, so none of them compiled with this connector.
Its only stored property is a PGConnection, which is Sendable.
PoolAndAsyncTests (live, skipped without PG_TESTS=1) runs a pool with a
transactionAsync round trip, a rolled-back transactionAsync, insertAsync,
fetchAll, firstAsync, and 20 concurrent pooled inserts. Without the
conformance the test target doesn't compile ("type
'PostgresDatabaseConfiguration' does not conform to the 'Sendable'
protocol").
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both _insert variants read instances[0] before checking the count, so returning(insert: []) and returning(_:insert: []) trapped with "Index out of range". They now return [] without touching the database. returningInsertEmptyArray (live) covers the whole-row and key-path forms, with and without setKeys/ignoreKeys; it crashes the test process without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With every key ignored, the whole-row form generated INSERT INTO "t" () VALUES () RETURNING *, a syntax error in PostgreSQL; the key-path form already used DEFAULT VALUES. Both now do. emptyInsert (live) now checks the key-path form's returned default and the whole-row form for one row and for several; without the fix it fails with 'syntax error at or near ")"'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
46 live tests began with 'guard pgEnabled else { return }', so without
PG_TESTS=1 they reported as passed. PerfectPostgreSQLTests (and its
QuoteIdentifierTests extension), PGConnectionParameterTests,
PGConnectionConcurrencyTests and DynamicAPITests now carry a suite-level
.enabled(if: pgTestsEnabled) trait and the guards are gone, so without a
server they show as skipped. The two server-free tests that lived in
those suites moved to their own suites so they still run: dateFormat
(DateFormatTests) and quoteIdentifierDoublesEmbeddedQuotes
(QuoteIdentifierUnitTests).
Without a server: 64 tests, 9 run and pass, the rest skipped. With
postgres:17: 64/64 pass.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dynamic select/execute throw only after the statement has run (and committed under autocommit), so a retried INSERT ... RETURNING through execute inserts twice. - PGConnection's lock doesn't cover CRUD's Database.transaction / transactionAsync, which send BEGIN and COMMIT/ROLLBACK as separate calls; a Database used for transactions mustn't be shared between tasks. Points at the pool, which now works (the configuration is Sendable). Drops "there's no async/await API". - Known limitations: NUL in a String, bytea_output = escape, NULL into a non-optional Int/String, millisecond Dates, and CRUD 3.0.0's trap for a Codable UInt/UInt64 above Int.max. - Reconcile fails with "must be owner" only when it needs to alter a table the role doesn't own. - Migration: the quoted connection parameters, including options that were appended inside a value; swift-log covers only the connector's own diagnostic, CRUD still logs through CRUDLogging. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.0.1 fixes four crashes in 3.0.0 reachable from public API, including a Codable UInt/UInt64 above Int.max trapping in CRUD's encoder (now bound as unsigned). Tests pass against 3.0.1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release prep for Perfect-PostgreSQL 5.0.0, the first release since 4.0.0 (2020). It requires Perfect-CRUD
from: "3.0.1".Fixes:
PostgresDatabaseConfiguration(database:host:port:username:password:)pasted values into the conninfo string unquoted. A password containing a space failed, and a value likex sslmode=disableinjected its own options. Values are now single-quoted per libpq's rules.PostgresDatabaseConfigurationisSendable. Before, CRUD'sDatabaseConnectionPooland async methods didn't compile with this connector, though the README advertised them.returning(insert: [])returns[]instead of trapping.returning(insert:)with every key ignored usesDEFAULT VALUES. It used to be a syntax error.Other changes:
PG_TESTS=1; they used to silently count as passes.Database.transactionisn't covered byPGConnection's lock, so use the pool rather than sharing oneDatabaseacross tasks.Testing
64/64 live against PostgreSQL 17, with warnings as errors:
Re-run live on Perfect-CRUD 3.0.1 after the pin change.
Three adversarial reviews. The final one checked:
🤖 Generated with Claude Code