compat: session/transaction rewrites + real MySQL/PG error codes + CI - #4
Merged
Merged
Conversation
Adds a first CI workflow (fmt / clippy -D warnings / test on ubuntu-latest) and the fixes that were needed to make it green today. Compiler + clippy hygiene - Drop unused sqlparser::Expr import in translate/mysql.rs - Drop dead DONE_MORE constant in tds/token.rs - Remove unread PreparedStmt.param_count in mysql/handler.rs - Collapse redundant closures on pgwire portal parameter extraction - Fix manual case-insensitive cmp, manual strip, useless conversion, single-match, and too-many-args lints across the workspace - extract_where_value / trim_offset in metadata.rs marked as WIP scaffolding (underscored / #[allow(dead_code)]) rather than removed -- they are part of an in-progress WHERE-clause extraction rework Session / transaction compatibility (litewire-translate) - START TRANSACTION [READ ONLY|READ WRITE|WITH CONSISTENT SNAPSHOT] -> BEGIN - BEGIN [WORK|TRANSACTION [name]] -> BEGIN (fixes PDO::beginTransaction) - COMMIT / ROLLBACK [WORK|TRANSACTION [name]] normalized - ROLLBACK TRANSACTION TO [SAVEPOINT] name rewritten to ROLLBACK TO SAVEPOINT - SAVEPOINT / RELEASE SAVEPOINT / ROLLBACK TO SAVEPOINT verified passthrough - SET autocommit = 1|ON|TRUE|0|OFF|FALSE -> noop (with WARN on 0/OFF/FALSE since litewire does not emulate MySQL implicit transactions) - SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL ... -> noop with debug log - SET @@[session|global.]var forms routed to their plain-name handling - LOCK TABLES / UNLOCK TABLES -> noop with warn - LAST_INSERT_ID() -> last_insert_rowid(); ROW_COUNT() -> changes() - DATABASE() / VERSION() / USER() / CURRENT_USER() / SESSION_USER() / SYSTEM_USER() / CONNECTION_ID() -> constant projections that match the values used by the @@variable metadata fast path - SQL_CALC_FOUND_ROWS / FOUND_ROWS() intentionally NOT implemented -- would require session state; documented as a known gap. Error-code fidelity - New litewire-mysql::error_map: classifies backend error strings to real MySQL codes: SQLITE_BUSY -> 1205, unique/PK -> 1062 (23000), FK -> 1452 (23000), readonly -> 1290, else 1105. - New litewire-postgres::error_map: unique -> 23505, FK -> 23503, not-null -> 23502, check -> 23514, busy -> 55P03, readonly -> 25006, else XX000. - Both classifiers unit-tested. Prepared-statement cap - Per-connection cap of 1024 prepared statements; overflow returns MySQL error 1461 (ER_MAX_PREPARED_STMT_COUNT_REACHED). Protects the server against clients that never send COM_STMT_CLOSE. Cast safety - Route affected_rows / last_insert_id through .max(0) + TryFrom rather than reinterpret-casting negative i64 into u64. README truth pass - Replace unverified "Tested with WordPress/Laravel/..." with an accurate Compatibility section: mysql_e2e covers the wire protocol end-to-end; postgres/tds are wire-compatible for basic CRUD; TDS marked experimental (auth simplified, no SSL). Note that postgres+tds require build-time features. All flag names verified against crates/litewire/src/main.rs.
5 tasks
CI formats this repo standalone with stable rustfmt defaults; local checkouts nested under other projects were inheriting a parent rustfmt.toml and disagreeing with CI. Pin the config in-repo so both always match.
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
-D warnings/ test onubuntu-latest).-D warningspasses.Base branch:
main. The follow-upperf/translate-cache-and-preparebranches from this one.Changes
CI (
.github/workflows/ci.yml)Three jobs on GitHub-hosted
ubuntu-latest: rustfmt check, clippy-D warnings, workspace tests. Usesdtolnay/rust-toolchain@stable+Swatinem/rust-cache@v2.Warning cleanup
sqlparser::Exprimport intranslate/mysql.rs.DONE_MOREconst intds/token.rs.PreparedStmt.param_countfield.pgwireportal parameter extractions.manual_ignore_case_cmp,manual_strip,useless_conversion,single_match, and onetoo_many_arguments(annotated in place — the token writer's arity is inherent to the TDS packet layout).metadata::extract_where_value+ thetrim_offsetlocal are the owner's WIP scaffolding; kept in place with#[allow(dead_code)]and a_prefix, per the audit note.Session / transaction compat (
litewire-translate)Handled textually before the sqlparser step so cross-dialect grammar quirks don't matter:
START TRANSACTION [READ ONLY | READ WRITE | WITH CONSISTENT SNAPSHOT]->BEGIN. This is the concrete fix forPDO::beginTransaction().BEGIN TRANSACTION [name]->BEGIN(name stripped -- SQLite has no named transactions).COMMIT WORK/COMMIT TRANSACTION [name]->COMMIT.ROLLBACK WORK/ROLLBACK TRANSACTION [name]->ROLLBACK.ROLLBACK TRANSACTION TO [SAVEPOINT] name->ROLLBACK TO SAVEPOINT name.SAVEPOINT/RELEASE SAVEPOINT/ROLLBACK TO SAVEPOINTverified passthrough via new tests.SET autocommit = 1|ON|true-> noop withdebug!.SET autocommit = 0|OFF|false-> noop withwarn!(litewire does not emulate MySQL's implicit-transaction mode, and half-emulating it via BEGIN would give worse semantics than a visible warning).SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL ...-> noop (SQLite is effectively serializable).SET @@x,SET @@session.x,SET @@global.xnormalized to their plain-name form so downstream matching works.LOCK TABLES/UNLOCK TABLES-> noop withwarn!(SQLite gives file-level locking only; documenting rather than silently faking).Function rewrites (
litewire-translate::common)LAST_INSERT_ID()->last_insert_rowid(). The 2-arg MySQL form (LAST_INSERT_ID(expr)sets a session value) is intentionally left to fail loudly at SQLite arity check rather than silently changing semantics.ROW_COUNT()->changes().DATABASE()/SCHEMA()->'main'.VERSION()->'8.0.0-litewire'(matches the@@versionmetadata fast path).USER()/CURRENT_USER()/SESSION_USER()/SYSTEM_USER()->'root@localhost'.CONNECTION_ID()->0.FOUND_ROWS()/SQL_CALC_FOUND_ROWS-- both need session state (per-connection row-count carry-over) that the current handler doesn't track.Error-code fidelity
litewire-mysql::error_mapclassifies backend error strings into real MySQL codes:SQLITE_BUSY/SQLITE_LOCKED-> 1205ER_LOCK_WAIT_TIMEOUT(HY000).SQLITE_CONSTRAINT_UNIQUE/PRIMARYKEY-> 1062ER_DUP_ENTRY(23000).SQLITE_CONSTRAINT_FOREIGNKEY-> 1452ER_NO_REFERENCED_ROW_2(23000).SQLITE_READONLY-> 1290ER_OPTION_PREVENTS_STATEMENT(HY000).ER_UNKNOWN_ERRORwith the raw text. SQLSTATE is derived fromErrorKind::sqlstate()byopensrv-mysql-- the SQLSTATE field onMysqlErroris retained (test-only, gated by#[cfg_attr(not(test), allow(dead_code))]) to pin those mappings in unit tests.litewire-postgres::error_map:Prepared-statement cap
Per-connection cap of 1024. Overflow returns MySQL 1461 (
ER_MAX_PREPARED_STMT_COUNT_REACHED) with the standard message. Trivial affected-rows / last-insert-id cast fixes routed through.max(0)+TryFromrather thani64 as u64.README truth pass
mysql_e2e.rsexercises the wire protocol end-to-end; PG/TDS are wire-compatible for CRUD only; TDS marked experimental (auth simplified, no SSL). Called out the--features postgres,tdsbuild-time gate on the multi-frontend command.crates/litewire/src/main.rs: they were already correct (--mysql-listen,--postgres-listen,--tds-listen,--hrana-listen) -- no--pg-listentypo existed. Left them alone.docs/sql-translation.mdisn't linked from anywhere in the current README; the sole link (docs/architecture.md) does exist. No stale doc-link removal needed.TOP n->LIMIT nis already implemented (tds::rewrite_top_to_limit) and tested; the README's claim is accurate.Test plan
cargo test --workspace-- 271 passing (172 translate lib incl. all new session/transaction tests, 25 mysql lib incl. error_map, 23 postgres lib incl. error_map, 20 tds lib, 21 in-process mysql_e2e wire tests, 9 translate integration insidelitewire, 23 backend, 1 doctest). 0 failures.cargo clippy --workspace --all-targets -- -D warnings-- clean.cargo fmt --all -- --check-- clean (reformatted the tree so CI can enforce it going forward; that's the bulk of the diff).