* fix(mysql): validate parameter count for prepared statements
Add validation to ensure the number of provided parameters matches the
expected count for MySQL prepared statements.
This prevents protocol errors by returning an error if the counts do not match before sending
the statement for execution.
* refactor(mysql): use err_protocol macro for error creation
Replace direct Error::Protocol(format!()) calls with err_protocol!
macro in MySQL connection executor.
* test(mysql): add parameter count validation tests
- Add test for too few parameters provided to query
- Add test for too many parameters provided to query
- Add test for parameters provided when none expected
- All tests verify Error::Protocol is returned for mismatches
Covers cases for issue #3774 parameter validation fix.
* feat: create `sqlx.toml` format
* feat: add support for ignored_chars config to sqlx_core::migrate
* chore: test ignored_chars with `U+FEFF` (ZWNBSP/BOM)
https://en.wikipedia.org/wiki/Byte_order_mark
* refactor: make `Config` always compiled
simplifies usage while still making parsing optional for less generated code
* refactor: add origin information to `Column`
* feat(macros): implement `type_override` and `column_override` from `sqlx.toml`
* refactor(sqlx.toml): make all keys kebab-case, create `macros.preferred-crates`
* feat: make macros aware of `macros.preferred-crates`
* feat: make `sqlx-cli` aware of `database-url-var`
* feat: teach macros about `migrate.table-name`, `migrations-dir`
* feat: teach macros about `migrate.ignored-chars`
* chore: delete unused source file `sqlx-cli/src/migration.rs`
* feat: teach `sqlx-cli` about `migrate.defaults`
* feat: teach `sqlx-cli` about `migrate.migrations-dir`
* feat: teach `sqlx-cli` about `migrate.table-name`
* feat: introduce `migrate.create-schemas`
* WIP feat: create multi-tenant database example
* fix(postgres): don't fetch `ColumnOrigin` for transparently-prepared statements
* feat: progress on axum-multi-tenant example
* feat(config): better errors for mislabeled fields
* WIP feat: filling out axum-multi-tenant example
* feat: multi-tenant example
No longer Axum-based because filling out the request routes would have distracted from the purpose of the example.
* chore(ci): test multi-tenant example
* fixup after merge
* fix(ci): enable `sqlx-toml` in CLI build for examples
* fix: CI, README for `multi-tenant`
* fix: clippy warnings
* fix: multi-tenant README
* fix: sequential versioning inference for migrations
* fix: migration versioning with explicit overrides
* fix: only warn on ambiguous crates if the invocation relies on it
* fix: remove unused imports
* fix: doctest
* fix: `sqlx mig add` behavior and tests
* fix: restore original type-checking order
* fix: deprecation warning in `tests/postgres/macros.rs`
* feat: create postgres/multi-database example
* fix: examples/postgres/multi-database
* fix: cargo fmt
* chore: add tests for config `migrate.defaults`
* fix: sqlx-cli/tests/add.rs
* feat(cli): add `--config` override to all relevant commands
* chore: run `sqlx mig add` test with `RUST_BACKTRACE=1`
* fix: properly canonicalize config path for `sqlx mig add` test
* fix: get `sqlx mig add` test passing
* fix(cli): test `migrate.ignored-chars`, fix bugs
* feat: create `macros.preferred-crates` example
* fix(examples): use workspace `sqlx`
* fix: examples
* fix(sqlite): unexpected feature flags in `type_checking.rs`
* fix: run `cargo fmt`
* fix: more example fixes
* fix(ci): preferred-crates setup
* fix(examples): enable default-features for workspace `sqlx`
* fix(examples): issues in `preferred-crates`
* chore: adjust error message for missing param type in `query!()`
* doc: mention new `sqlx.toml` configuration
* chore: add `CHANGELOG` entry
Normally I generate these when cutting the release, but I wanted to take time to editorialize this one.
* doc: fix new example titles
* refactor: make `sqlx-toml` feature non-default, improve errors
* refactor: eliminate panics in `Config` read path
* chore: remove unused `axum` dependency from new examples
* fix(config): restore fallback to default config for macros
* chore(config): remove use of `once_cell` (to match `main`)
Previously, `TextRow::decode_with` would read a length-encoded field size
and attempt to advance the buffer by that amount. If the server sent a
malformed packet containing a length value larger than the remaining data
in the buffer, the call to `buf.advance(size)` would panic.
eg:
```
thread 'main' panicked at /home/user/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.10.1/src/bytes.rs:711:9:
cannot advance past remaining: 8590116092 <= 0
stack backtrace:
0: 0x56119b657e00 - <std::sys::backtrace::BacktraceLock::print::DisplayBacktrace as core::fmt::Display>::fmt::h6d42cc84fc840290
1: 0x56119b67edd3 - core::fmt::write::h5af61a909e3ec64d
2: 0x56119b653ee3 - std::io::Write::write_fmt::h5a7b54aa6e4a315d
3: 0x56119b657c52 - std::sys::backtrace::BacktraceLock::print::h555579e7396c26ac
4: 0x56119b658cef - std::panicking::default_hook::{{closure}}::h9128866118196224
5: 0x56119b658b5a - std::panicking::default_hook::h52e9e7314e0255f6
6: 0x56119b659712 - std::panicking::rust_panic_with_hook::h541791bcc774ef34
7: 0x56119b65949a - std::panicking::begin_panic_handler::{{closure}}::h6479a2f0137c7d19
8: 0x56119b658319 - std::sys::backtrace::__rust_end_short_backtrace::ha04e7c0fc61ded91
9: 0x56119b65912d - rust_begin_unwind
10: 0x56119b67c390 - core::panicking::panic_fmt::h5764ee7030b7a73d
11: 0x56119b572b18 - <sqlx_mysql::protocol::text::row::TextRow as sqlx_core::io::decode::ProtocolDecode<&[sqlx_mysql::column::MySqlColumn]>>::decode_with::h17ac8b44140b5469
12: 0x56119b42df1f - sqlx_mysql::connection::executor::<impl sqlx_mysql::connection::MySqlConnection>::run::{{closure}}::{{closure}}::{{closure}}::h4874a0f73925d55a
```
This commit introduces a bounds check immediately after reading the field length from a packet.
This panic condition was specifically observed when executing a TiDB
`BATCH ON ... DELETE` statement via `pool.execute()`. It sends an OK packet immediately followed by
a full result set describing the batch status (column defs, row data, EOF).
Observed TiDB response sequence for `BATCH DML` via `COM_QUERY`:
1. OK Packet (seq=1, `SERVER_MORE_RESULTS_EXISTS` = false)
2. Column Count Packet (seq=1, non-standard, protocol violation)
3. Column Definition Packet (seq=2)
4. Column Definition Packet (seq=3)
5. Text Row Data Packet (seq=4)
6. EOF Packet (seq=5, `SERVER_MORE_RESULTS_EXISTS` = false)
This differs from standard MySQL DML response (OK/ERR packet only) and
causes `sqlx` using `execute()` to attempt parsing the unexpected result
set packets after the initial OK packet.
* feat: Implement `get_transaction_depth` for drivers
* test: Verify `get_transaction_depth()` on postgres
* Refactor: `TransactionManager` delegation without BC
SQLite implementation is currently WIP
* Fix: Avoid breaking changes on `AnyConnectionBackend`
* Refactor: Remove verbose `SqliteConnection` typing
* Feat: Implementation for SQLite
I have included `AtomicUsize` in `WorkerSharedState`. Ideally, it is not desirable to execute `load` and `fetch_add` in two separate steps, but we decided to allow it here since there is only one thread writing. To prevent writing from other threads, the field itself was made private, and a getter method was provided with `pub(crate)`.
* Refactor: Same approach for `cached_statements_size`
ref: a66787d36d62876b55475ef2326d17bade817aed
* Fix: Add missing `is_in_transaction` for backend
* Doc: Remove verbose "synchronously" word
* Fix: Remove useless `mut` qualifier
* feat: add Connection::begin_with
This patch completes the plumbing of an optional statement from these methods to
`TransactionManager::begin` without any validation of the provided statement.
There is a new `Error::InvalidSavePoint` which is triggered by any attempt to
call `Connection::begin_with` when we are already inside of a transaction.
* feat: add Pool::begin_with and Pool::try_begin_with
* feat: add Error::BeginFailed and validate that custom "begin" statements are successful
* chore: add tests of Error::BeginFailed
* chore: add tests of Error::InvalidSavePointStatement
* chore: test begin_with works for all SQLite "BEGIN" statements
* chore: improve comment on Connection::begin_with
* feat: add default impl of `Connection::begin_with`
This makes the new method a non-breaking change.
* refactor: combine if statement + unwrap_or_else into one match
* feat: use in-memory SQLite DB to avoid conflicts across tests run in parallel
* feedback: remove public wrapper for sqlite3_txn_state
Move the wrapper directly into the test that uses it instead.
* fix: cache Status on MySqlConnection
* fix: compilation errors
* fix: format
* fix: postgres test
* refactor: delete `Connection::get_transaction_depth`
* fix: tests
---------
Co-authored-by: mpyw <ryosuke_i_628@yahoo.co.jp>
Co-authored-by: Duncan Fairbanks <duncanfairbanks6@gmail.com>
* feat(mysql): support configuring the timezone via url
* test: add test case for mysql with timezone
---------
Co-authored-by: lo <lo@los-MacBook-Pro.local>
* impl AnyQueryResult for Sqlite and MySQL
* fix MySQL AnyQueryResult
* fix MySQL AnyQueryResult
* fix manifest
* rewrite `use` and address implementation concerns
* Fixed some rust docs intra-doc non functioning links
* Minor tweaks
* Added warning for MSSQL not being functional yet
* Fixed requested changes
* Readded missing time
* Aligned table
* Make encode and encode_by_ref fallible
This only changes the trait for now and makes it compile, calling .expect() on all users. Those will be removed in a later commit.
* PgNumeric: Turn TryFrom Decimal to an infallible From
* Turn panics in Encode implementations into errors
* Add Encode error analogous to the Decode error
* Propagate decode errors through Arguments::add
This pushes the panics one level further to mostly bind calls. Those will also be removed later.
* Only check argument encoding at the end
* Use Result in Query internally
* Implement query_with functions in terms of _with_result
* Surface encode errors when executing a query.
* Remove remaining panics in AnyConnectionBackend implementations
* PostgreSQL BigDecimal: Return encode error immediately
* Arguments: Add len method to report how many arguments were added
* Query::bind: Report which argument failed to encode
* IsNull: Add is_null method
* MySqlArguments: Replace manual bitmap code with NullBitMap helper type
* Roll back buffer in MySqlArguments if encoding fails
* Roll back buffer in SqliteArguments if encoding fails
* Roll back PgArgumentBuffer if encoding fails
When using the 'Any' driver with MySQL backend, fetch_optional
does not return the connection to the pool if no results
are returned from the query. This is due to not all of the packets
being read from the underlying stream.
This fix continues to read result packets from the stream until they
have all been exhausted (just like the normal MySql drivers
implementation of fetch_optional). In general, a better refactoring would
be to call the MySQL fetch_optional code in the Any driver, rather than
re-implementing and duplicating code.
Also clarifies the handling of `TIME` (we never realized it's used for both time-of-day and signed intervals) and adds appropriate impls for `std::time::Duration`, `time::Duration`, `chrono::TimeDelta`
* HasValueRef, HasArguments, HasStatement -> Database GATs
replace the associated types from the generic traits
`HasValueRef<'r>`, `HasArguments<'q>` and `HasStatement<'q>`
with generic associated types in `Database`
* fixup after rebase
---------
Co-authored-by: Austin Bonander <austin.bonander@gmail.com>