switchy_database 0.5.0

Switchy database package
# Raw SQL transition (local implementation status)

## SELECT and bulk UPSERT follow-up (2026-10-03)

* Actual source audit found ungated table interpolation in ordinary SELECT/find-first and bulk UPSERT on SQLx SQLite/MySQL/PostgreSQL and native PostgreSQL; UPSERT keys and SELECT projections also used legacy formatting. No-raw rendering now quotes exact identifiers with delimiter escaping; raw-on legacy rendering is retained. This does not certify other backend operations.
* `tests/bulk_upsert_boundary.rs` runs SQLite SQLx insert/conflict update and projected SELECT/find-first with delimiter-bearing table/key/value names; `tests/sqlite_open_policy.rs` proves typed opener missing-file no-create, independent immediate transaction contention, rollback release, close and read-only schema-write rejection. No raw feature, caller SQL or driver fixture was introduced. SQLite may successfully BEGIN IMMEDIATE on a read-only connection, so rejection is asserted at the actual write.
* Let F=`sqlite-rusqlite,sqlite-sqlx,mysql-sqlx,postgres-sqlx,postgres-raw,schema,cascade`. Observed passing: `cargo fmt -p switchy_database`; `cargo clippy -p switchy_database --no-default-features --features F --all-targets -- -D warnings` and F plus `raw-sql`; no-raw tests selected `bulk_upsert_boundary`, `sqlite_open_policy`, `connection_lifecycle`, `byte_length`, `typed_maintenance`, `usage_constraints`, `typed_joins`, `raw_boundary`, `select_projection_boundary`, `legacy_helper_boundary`; raw-on tests selected `bulk_upsert_boundary`, `sqlite_open_policy`, `legacy_helper_boundary`. `cargo test -p switchy_database --no-default-features --features F --doc` passed, also with raw-sql. Logs `/tmp/switchy-phase2-{off,on}-{clippy,tests,doc}.log`. The final projection/find-first test expansion also passed independently with `--features sqlite-sqlx,schema --test bulk_upsert_boundary` (`/tmp/switchy-bulk-off.log`).
* Passing production checks: `cargo check -p switchy --no-default-features --features database,database-sqlite-rusqlite`; `cargo check -p switchy_database_connection --no-default-features --features sqlite-rusqlite`; `cargo check -p switchy_schema --no-default-features`. These compile actual source, not just metadata. No manifest, lockfile or local patch changes in this slice.
* Initial delimiter regression failed on the still-unquoted SELECT after UPSERT succeeded; fixed and rerun. Initial opener fixture incorrectly reused a consumed transaction (compile failure) then incorrectly assumed read-only BEGIN fails (runtime failure); corrected to actual schema-write rejection. An attempted combined `--doc --test` invocation was rejected by Cargo; separate runs passed.
* Runtime evidence is SQLite Rusqlite/SQLx and existing Turso tests only. No live PostgreSQL/MySQL server validation or DuckDB execution; MySQL bulk UPSERT's existing PostgreSQL-shaped conflict syntax still requires separate correction/testing. Umbrella profiles, exhaustive boundary audit and Bcode actual-consumer integration are not certified by this slice.

## Legacy bulk UPDATE helper exclusion (2026-10-03)

* SQLx SQLite/MySQL/PostgreSQL and native PostgreSQL `update_multi` helpers and their private `update_chunk` generators are now compiled only with `raw-sql`, matching the existing Rusqlite policy. These legacy helpers accept fragment-shaped table inputs and are not called by the structured executor. Private structured UPSERT generators remain available; this change does not certify their rendering.
* Four no-raw compile-fail doctests reject importing the helpers; `tests/legacy_helper_boundary.rs` confirms all four imports remain available with raw enabled without executing caller SQL. Consumers should use `Database::update(...).value(...).execute(...)` (and transactions for multiple statements), not backend connection helpers. No feature activation or dependency change was added.
* Exact validation from the repository root: `cargo fmt -p switchy_database`; `cargo check -p switchy_database --no-default-features --features F`; `cargo clippy -p switchy_database --no-default-features --features F --all-targets -- -D warnings`; `cargo test -p switchy_database --no-default-features --features F --doc`; `cargo test -p switchy_database --no-default-features --features F --test legacy_helper_boundary --test sqlx_create_boundary`. Each command passed with F=`sqlite-sqlx,mysql-sqlx,postgres-sqlx,postgres-raw,schema` and with `,raw-sql` appended. Initial no-raw clippy failed on needless raw-string hashes in the new docs; fixed, then both strict clippy runs passed. `git diff --check` passed.
* Logs: `/tmp/switchy-helper-{off,on}-{check,clippy-final,doc-final,tests}.log`. No-raw docs: 25 ordinary and 13 compile-fail passed, 39 ignored; raw docs: 25 passed, 42 ignored. Runtime SQLite schema tests: 2 no-raw, 1 raw passed; raw helper compatibility test: 1 passed (no-raw target intentionally has zero tests; exclusion is doctest-owned).
* Partial prerequisite only: typed SELECT projections, aliases and GROUP BY remain missing. No new aggregate API was supplied. Full schema/query/transaction/forwarding audit, live PostgreSQL/MySQL tests, separate backend feature graphs, whole-workspace checks, and downstream integration remain unverified. Existing `identifier` no-raw semantics quote one exact name (dots are not qualification); `qualified_column` quotes components separately. Existing `byte_length` is intended to count UTF-8 bytes and preserve NULL, not characters; this helper slice did not change or freshly validate that behavior.

## Turso INSERT and CREATE names slice (2026-10-03)

* No-raw Turso single-row INSERT now delimits table and column names, including DEFAULT VALUES. CREATE TABLE now delimits its table and column names. Embedded double quotes are doubled; a dot is part of one exact identifier, not qualification. Raw-enabled compatibility remains unchanged. SQL generation stays private; no public API, dependency or feature activation was added.
* Consumers use `db.create_table(table).column(Column { name, ... })` and `db.insert(table).value(column, value)`. Added `tests/turso_insert_boundary.rs` tests exact quoted/dotted names, default insertion, ordinary insertion and rejected column-list injection without raw. This does not close other Turso schema or UPSERT paths.
* Observed PASS: `cargo fmt -p switchy_database`; `cargo test -p switchy_database --no-default-features --features turso,schema --test turso_insert_boundary` (2 tests); the same with `turso,schema,raw-sql` (1 test); `cargo check -p switchy_database --no-default-features --features turso,schema` and with `turso,schema,raw-sql`; `cargo clippy -p switchy_database --no-default-features --features turso,schema --all-targets -- -D warnings` and with `turso,schema,raw-sql`; `git diff --check`.
* `cargo test -p switchy_database --doc --no-default-features --features turso,schema` PASS: 25 ordinary plus 9 existing compile-fail tests, 39 ignored; log `/tmp/switchy-turso-boundary-doc.log`. These are existing exclusion tests, not new comprehensive coverage.
* Integration additionally quotes no-raw single/multi conflict-target UPSERT names and SELECT/find-row identifiers. New UPSERT regression passed (3 no-raw tests total); raw-on INSERT compatibility test passed. Both strict all-target clippy profiles and no-raw doctests passed; `/tmp/turso-integrate-*.log`. Initial regression exposed SELECT table interpolation, now corrected. ORDER BY parameter binding and remaining backend routes are still open.
* Initial test compilation failed on an incorrect value variant (corrected to Int64). Initial no-raw behavior test then exposed unquoted CREATE names; fixed and rerun successfully. Workspace-wide formatting/build/tests, other-backend runtime coverage and downstream integration were not run for this slice.
* Review gaps remain concrete: Turso UPSERT columns/table names, DuckDB INSERT plans and inline execution names, and SQLx MySQL INSERT table/unescaped key rendering still need closure. Typed SELECT projection/alias/grouping support remains absent; existing Min/ByteLength predicates do not substitute for projected aggregates. No Phase 1 completion claim.

## UPDATE assignment-key boundary slice (2026-10-03)

* Rusqlite, DuckDB, Turso and SQLx MySQL now render UPDATE assignment keys as exact delimited identifiers without `raw-sql`. Embedded delimiters are doubled; dots do not qualify names. The other three renderers already call their identifier formatter in this path. Raw-enabled compatibility is unchanged. This applies to shared SET construction, not a claim that every mutation path is closed.
* Use `db.update(table).value(column, value)` for assignment; the column is a name, not an assignment list. Added `tests/update_assignment_boundary.rs` verifies ordinary updates and rejects an assignment-list key without changing either stored column in no-raw mode. The same test verifies retained raw-on behavior. No public API or dependency feature activation was added.
* Commands below ran with `/nix/store/hjkfa9ja30bbqa47bl1121jx5ygzm0xx-rust-default-1.98.1/bin` prepended to PATH:
  * `cargo fmt -p switchy_database`: passed.
  * `cargo test -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade --test update_assignment_boundary`: passed, 1 test; repeated with `,raw-sql`: passed, 1 test.
  * `cargo clippy -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade --all-targets -- -D warnings`: passed; repeated with `,raw-sql`: passed.
  * `cargo check -p switchy_database --no-default-features --features sqlite-rusqlite,sqlite-sqlx,postgres-sqlx,mysql-sqlx,postgres-raw,turso,schema,cascade`: passed; repeated with `,raw-sql`: passed.
  * `cargo test -p switchy_database --doc --no-default-features --features sqlite-rusqlite,schema,cascade`: passed, including 9 compile-fail tests (existing coverage, not newly added).
* Logs: `/tmp/update-boundary-{off,on,clippy-off,clippy-on,matrix-off,matrix-on,doc}.log`. DuckDB compilation/runtime, server-backed runtime, full workspace validation, isolated forwarding graphs and complete helper/schema/mutation audit remain gaps. Typed aggregate projections/aliases/grouping are still missing; no Bcode or living-plan edits were made by this slice. Existing byte-length/qualified-column work is not newly implemented here.

**Incomplete boundary: do not treat a build without `raw-sql` as SQL-fragment-safe yet.**

## Rusqlite CREATE/DROP table integration slice (2026-10-03)

* Basic CREATE TABLE and DROP TABLE, plus manual CASCADE/RESTRICT drop execution, now use the existing feature-aware exact-identifier renderer. Raw-enabled legacy compatibility is retained. Other backends and ALTER TABLE remain incomplete.
* Added `tests/drop_table_boundary.rs`: ordinary names run raw-on/off; raw-off dotted, quoted and SQL-looking names are created and removed through default/restrict/cascade paths without removing a sentinel table. This does not prove cascade dependency ordering or all introspection names safe.
* Integration reran index, change-observation and connection-lifecycle tests alongside this test: four tests pass with `sqlite-rusqlite,schema,cascade`, and four with `raw-sql` appended. Four raw-exclusion doctests pass. Logs `/tmp/integration-boundary-{off,on,doc}.log`.
* `cargo fmt` passes using the installed complete Rust 1.97.1 toolchain. Strict no-raw all-target clippy fails on 11 existing `doc_markdown` diagnostics in database lib/SQLx SQLite; `/tmp/integration-boundary-clippy.log`. Earlier default PATH lacked fmt/clippy/rustdoc; using `/nix/store/5bpp3p8z8qn2shgw6nabk22gs1q68spw-rust-default-1.97.1/bin` restored tools, not a lint waiver.

* Follow-up: the 11 database Rustdoc diagnostics and five newly exposed database_connection diagnostics are corrected. `cargo fmt --package switchy_database --package switchy_database_connection` and `cargo clippy -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade --all-targets -- -D warnings` pass using that toolchain (`/tmp/sql-iteration2-clippy.log`). No-raw `byte_length` and `drop_table_boundary` tests also pass (2 tests, `/tmp/sql-iteration2-tests.log`). Other backend profiles and full boundary closure remain unverified.

## CREATE/DROP INDEX boundary slice (2026-10-03)

* All seven backend index renderers now escape delimiter characters in column names. No-raw index and table names are exact quoted identifiers; dots do not qualify names and column strings cannot express functions or ordering. Existing raw-on name compatibility remains in the six legacy unquoted renderers; DuckDB retains its always-quoted names with corrected escaping. MySQL DROP INDEX now separates the index name from ON with whitespace.
* Consumers use `schema::create_index(name).table(table).column(column).unique(true)` and `schema::drop_index(name, table)`. These are schema identifiers, not typed query projections. No feature activation or public raw API was added.
* Added `tests/index_boundary.rs`: unique-index behavior and removal pass raw-on/off; no-raw SQL-looking, dotted and delimiter-bearing index names remain literal. An ordering-looking column is rejected rather than executed as an expression.
* PASS: `cargo fmt`; `git diff --check`; `cargo test -p switchy_database --no-default-features --features sqlite-rusqlite,schema --test index_boundary` and the same with `,raw-sql` (one test each). Initial attempts failed to compile the new fixture because `.unique()` requires a bool; corrected to `.unique(true)` before passing runs.
* PASS: `cargo clippy -p switchy_database --no-default-features --features sqlite-rusqlite,schema --all-targets -- -D warnings` and the same with `,raw-sql`.
* PASS: `cargo check -p switchy_database --no-default-features --features sqlite-rusqlite,sqlite-sqlx,postgres-sqlx,postgres-raw,mysql-sqlx,turso,schema` and the same with `,raw-sql`.
* PASS: `cargo test -p switchy_database --doc --no-default-features --features sqlite-rusqlite,schema -- lib.rs` (four existing compile-fail exclusions passed). No new exclusion test was necessary for this private renderer change; exclusion coverage is not a complete audit.
* Logs: `/tmp/switchy-index-{fmt,off,on,clippy-off,clippy-on,matrix-off,matrix-on,doc}.log`.
* Gaps: DuckDB compilation/runtime, non-Rusqlite index runtime behavior, complete schema/query/connection/transaction/forwarder audit, aggregates/grouping/typed projections and aliases, and downstream integration remain unverified or unimplemented. DROP TABLE and ALTER TABLE still contain interpolation routes outside this slice. This is not Phase 1 completion.

## Schema key identifier slice (2026-10-03)

* CREATE TABLE primary-key and legacy foreign-key components now use escaped exact identifiers without `raw-sql` in all seven renderers. Raw-on legacy rendering is retained. `primary_key(name)` is one column; `foreign_key((column, table))` references the target table's primary key. A target such as `parent(id)` is literally that table name, not SQL. Explicit referenced-column and composite-key APIs remain missing.
* Added `tests/schema_key_boundary.rs`: ordinary primary-key uniqueness and foreign-key construction run raw-on/off; no-raw tests reject primary-key fragment syntax and inspect SQLite's stored DDL to prove the reference target is quoted. This is behavioral output testing, not repository-source matching.
* PASS: `cargo fmt`; `git diff --check`; `cargo test -p switchy_database --no-default-features --features sqlite-rusqlite,schema --test schema_key_boundary` and the same with `,raw-sql` (one test each). Initial test failed because `get_table_info` cannot decode the NULL referenced-column field of an implicit-primary-key reference; the final test now also verifies `get_table_info` resolves the implicit referenced primary-key column. Integration fixed the NULL decoding defect in the Rusqlite backend by resolving the foreign-key sequence against primary-key ordinals; absent targets fail closed with InvalidSchema. Other backends' implicit-reference introspection remains unverified.
* PASS: `cargo check -p switchy_database --no-default-features --features sqlite-rusqlite,sqlite-sqlx,postgres-sqlx,postgres-raw,mysql-sqlx,turso,schema` and the same with `,raw-sql`. `cargo check -p switchy_database --no-default-features --features duckdb,schema` passes with ten dead-code warnings; adding `,raw-sql` passes cleanly. Runtime behavior outside SQLite is not established.
* PASS: `cargo clippy -p switchy_database --all-targets --no-default-features --features sqlite-rusqlite,schema -- -D warnings` and the same with `,raw-sql`; focused clippy using `--test schema_key_boundary` also passes both modes. DuckDB strict lint is not established.
* PASS: `cargo test -p switchy_database --doc --no-default-features --features sqlite-rusqlite,schema`: 25 ordinary tests and seven existing compile-fail tests pass, 39 ignored. An earlier `-- 'compile_fail'` filter ran zero tests and is not exclusion evidence. No new compile-exclusion surface was introduced by this slice.
* PASS: `cargo test -p switchy_database --no-default-features --features sqlite-rusqlite,schema --test byte_length --test qualified_columns --test subquery_boundary --test typed_joins` (five tests); `cargo check -p switchy_database_connection --no-default-features --features sqlite-rusqlite`; `cargo check -p switchy --no-default-features --features database-sqlite-rusqlite,database-schema`.
* This is not Phase 1 completion: other CREATE TABLE names, ALTER/index/drop/dependency-discovery interpolation, complete helper/transaction/forwarder auditing, typed aggregates/grouping/aliases/conditional projections, and downstream integration remain. No Bcode or living-plan edits were made by this slice; pre-existing changes were retained.

## Nested SELECT boundary slice (2026-10-03)

* Nested `SelectQuery` expressions now quote their table identifier in all seven renderers without `raw-sql`; rusqlite, DuckDB, Turso and MySQL also quote their projection identifiers instead of joining caller strings as SQL. Integration subsequently corrected the remaining three projection formatters as recorded below. Raw-enabled legacy rendering is preserved.
* Integration review corrected the retained nested projection formatters: SQLx SQLite passed strings through unchanged, and both Postgres formatters failed to escape embedded quotes. All seven nested renderers now use exact escaped no-raw projections, with legacy raw-on rendering retained. The shared behavioral fixture runs on Rusqlite and SQLx SQLite and rejects arithmetic, embedded-quote fragments and implicit dot qualification. Postgres runtime remains unverified.
* No-raw strings denote exact identifiers, not qualification or expressions. Standalone `*` retains wildcard semantics. Use `qualified_column(table, column)` for typed qualification where an expression is accepted. This does not add typed projection aliases, aggregates or grouping.
* `tests/subquery_boundary.rs` uses only structured fixtures and proves arithmetic-looking projections are not executed, table fragments are rejected, ordinary nested selection works and the table survives. An initial assertion using `"7"` was corrected to `"3 + 4"`: SQLite can coerce its double-quoted string fallback to an integer, so the former was not a valid injection test.
* Verified: `cargo fmt`; `git diff --check`; no-raw nested-select/join/byte-length/qualified-column tests (4 passed); raw-on join/byte-length/qualified-column tests (3 passed); strict all-target database clippy in both modes with `sqlite-rusqlite,schema,cascade`; checks in both modes with `sqlite-rusqlite,sqlite-sqlx,postgres-sqlx,postgres-raw,mysql-sqlx,turso,schema,cascade`; existing lib doctests (8 passed, 26 ignored) and raw exclusion doctests (4 passed).
* Still unverified: DuckDB compilation/runtime, server backend runtime behavior, full upstream workspace and forwarding-crate boundary completeness. Top-level projection/mutation/schema interpolation, aggregates/grouping/aliases and complete lifecycle/helper audit remain open; this slice is not Phase 1 completion.

## Typed JOIN boundary slice (2026-10-03)

* `query::join_columns(table, qualified_column(table, column), qualified_column(table, column), left)` supplies equality joins through `SelectQuery::joins`. `left = true` selects LEFT JOIN. Table and column components are exact quoted identifiers in both raw modes; embedded dots are literal characters, not qualification. All seven backend renderers use this representation.
* `Join::on` now has type `JoinCondition`, not `&str`. `JoinCondition::Raw(String)`, `join`, `left_join`, and the single-string select join methods exist only with `raw-sql`. Raw-enabled callers constructing `Join` directly must wrap existing predicates explicitly. No feature activation was added.
* This is NOT full structured-input safety: projections, base table names, mutation/schema inputs and savepoint names still require audit/hardening. Aggregate/grouping/alias projections remain missing. Existing byte-length and qualified-column work was preserved rather than reimplemented.
* PASS: `cargo fmt`; `git diff --check`; `cargo check -p switchy_database --no-default-features`; `cargo check -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade` (also with `,raw-sql`).
* PASS in both raw modes: `cargo test -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade --test typed_joins --test byte_length --test qualified_columns` (3 tests each); `cargo clippy -p switchy_database --all-targets --no-default-features --features sqlite-rusqlite,schema,cascade -- -D warnings`. Raw-on adds `,raw-sql` to the features argument. Initial clippy failures in existing join unit tests were corrected and these final commands passed.
* PASS: `cargo test -p switchy_database --doc --no-default-features --features sqlite-rusqlite,schema,cascade -- JoinCondition` (3 compile-exclusion doctests).
* PASS in both raw modes: `cargo check -p switchy_database --no-default-features --features sqlite-sqlx,postgres-sqlx,postgres-raw,mysql-sqlx,turso,schema,cascade` (raw-on adds `,raw-sql`). No live server-backed execution or DuckDB build was performed.
* PASS: `cargo check -p switchy_database_connection --no-default-features --features sqlite-rusqlite`; `cargo check -p switchy --no-default-features --features database-sqlite-rusqlite,database-schema`.
* Evidence logs: `/tmp/switchy-join-final-{test-off,test-on,clippy-off,clippy-on,matrix-off,matrix-on,doc}.log`, `/tmp/switchy-join-{connection,umbrella,backendless}.log`. Full workspace and downstream integration are unverified. Bcode and the living plan were not edited.

## Integration

* `switchy_database` defaults include `raw-sql`. Consumers disabling defaults must explicitly request it to retain existing arbitrary SQL calls.
* `switchy_database_connection/raw-sql` forwards to the database feature and is default-enabled. Backend features do not enable it.
* The umbrella defaults include `database-raw-sql` and `database-connection-raw-sql`. Both use weak dependency forwarding: they do not independently activate a database dependency. Enable `database` / `database-connection` (or an appropriate backend feature) separately.
* Without `raw-sql`, `Database::{exec_raw,query_raw,exec_raw_params,query_raw_params}`, including access through transactions/savepoints, are absent. Decorator implementations must conditionally compile those methods with a matching consumer feature, or remove them in a no-raw-only consumer. Ordinary structured methods are unchanged.
* Without `raw-sql`, `switchy_schema` directory/embedded discovery and checksums remain available, but executing nonempty SQL migrations returns the typed `MigrationError::RawSqlDisabled` error before database dispatch. Existing empty/no-content no-op behavior is retained. Discovery features do not implicitly enable raw execution.
* `query::Literal`, `literal`, literal conversions and `ExpressionType::Literal`, plus `Executable for String/&str`, are absent without the feature.
* SQLx SQLite/Postgres `get_connection` is only public with `raw-sql`. Backend-internal access and generated SQL execution remain private and available when needed.
* `query::identifier` expressions in no-raw builds denote **one exact identifier**, quoted for the backend. A dot is part of the name, not qualification. Existing raw-enabled expression rendering is preserved. Do not move projections, aliases or SQL functions into identifier strings to migrate callers.
* `postgres-raw` continues to name a backend, not raw-SQL permission. `schema` and `cascade` do not imply `raw-sql`.
* Eventual removal from defaults requires a compatibility release; not performed here.

## Remaining audit scope

This is a partial implementation, not a certified complete raw-off boundary. Existing typed index, join, subquery, mutation, schema and lifecycle slices supersede the original blanket absence claims. The 2026-10-03 follow-up below found additional SELECT and bulk UPSERT gaps, demonstrating that earlier slice results did not cover all executors. Continue auditing other mutation/schema renderers and backend helpers; do not infer coverage from names or feature declarations. `SqlInterval` is numeric structured data, not a free-form string.

The current Rusqlite implementation provides leased connection-affine deferred/immediate/exclusive transactions, rollback on drop, affected-row counts, busy/locked classification and close refusal while leases remain. `database_connection::open_sqlite_rusqlite` accepts explicit read-only/no-create access, URI policy, busy timeout, foreign keys and nonzero pool size. Consumers must select these explicitly rather than the legacy five-connection/10ms initializer. Typed integer CHECK and unique constraints exist. Consumer integration and full backend parity remain separate requirements; these capabilities are not permission to add fragments or generic pragma APIs.

## Observed validation

Commands run from the MoosicBox root:

* `cargo fmt --all`: passed.
* `cargo check -p switchy_database --no-default-features --features sqlite-rusqlite,schema,cascade` and same with `,raw-sql`: passed.
* `cargo clippy -p switchy_database --lib --no-default-features --features sqlite-rusqlite,schema,cascade -- -D warnings` and same with `,raw-sql`: passed after fixing explicit statement/connection release in moved raw helpers.
* `cargo check -p switchy_database --no-default-features --features sqlite-sqlx,postgres-sqlx,mysql-sqlx,postgres-raw,schema,cascade`: passed with dead-code warnings; not strict-clean.
* `cargo check -p switchy_database --no-default-features --features turso,schema,cascade`: passed with warnings.
* `cargo check -p switchy_database_connection --no-default-features --features sqlite-rusqlite`: passed (a then-observed unused helper was subsequently gated).
* `cargo check -p switchy --no-default-features --features database-sqlite-rusqlite,database-schema`: passed.
* `cargo test -p switchy_database --test raw_boundary --no-default-features --features sqlite-rusqlite,schema,cascade`: one SQL-looking identifier behavior test passed. Dev dependencies activate additional backends but not raw-sql.
* `cargo test -p switchy_database --doc --no-default-features --features sqlite-rusqlite,schema,cascade -- 'lib.rs'`: 8 ordinary tests and 4 compile-fail exclusion tests passed; 26 ignored and 33 filtered.
* `cargo test -p switchy_database --lib --no-default-features --features sqlite-rusqlite,schema,cascade,raw-sql rusqlite::tests`: 17 passed, 325 filtered.
* Strict `--all-targets` clippy, both feature-on/off: **failed**. Dev dependencies expand the backend graph; moved backend methods expose significant-drop-tightening lints and no-raw builds retain unused helpers. No-raw existing raw-based test suites still need feature gating or typed fixtures. These are blocking, not waived.
* DuckDB build, server-backed runtime tests, complete workspace build/test/clippy, and downstream integration were not verified.

Logs from this execution are `/tmp/switchy-{check,on,off,matrix,turso,connection,umbrella,test,doc,tests-on,clippy-on,clippy-off,all-clippy,all-clippy-off}.log`; temporary logs are evidence pointers, not durable CI artifacts.