Skip to content

Conversation

iamjpotts
Copy link
Contributor

@iamjpotts iamjpotts commented Aug 2, 2025

Does your PR solve an issue?

Similar to #3957, allows more flexibility with passing references as bind parameters to query! macros when using the Any driver.

This is the first of two prs, after which Query::bind and Query::try_bind argument lifetimes will be relaxed to be consistent across the drivers. The second pr adds a test which is a compile-time check of the new lifetime allowances for arguments. That test will not compile with just this pr.

Second of the two prs:
#3960

Is this a breaking change?

Yes:

  • removes lifetime parameters from structs that are a part of the public api for the Any driver
  • changes enum variants for AnyValueKind

@iamjpotts iamjpotts force-pushed the jp/any-arg-lifetime branch 2 times, most recently from 4b8535d to babd18d Compare August 2, 2025 15:53
@iamjpotts iamjpotts force-pushed the jp/any-arg-lifetime branch 2 times, most recently from 58b46a2 to 3217e7e Compare August 11, 2025 01:13
@iamjpotts iamjpotts force-pushed the jp/any-arg-lifetime branch 2 times, most recently from b1320b0 to c8c85e7 Compare August 19, 2025 22:01
@iamjpotts iamjpotts marked this pull request as ready for review August 19, 2025 22:19
@iamjpotts iamjpotts force-pushed the jp/any-arg-lifetime branch 2 times, most recently from a327b23 to 58fdeca Compare August 22, 2025 12:28
Signed-off-by: Joshua Potts <8704475+iamjpotts@users.noreply.github.com>
@iamjpotts iamjpotts force-pushed the jp/any-arg-lifetime branch from 58fdeca to 255ea48 Compare August 27, 2025 23:47
@joeydewaal
Copy link
Contributor

Just as a note:
To implement something like #875, you'd have to defer the encoding of the arguments until your in the driver. One way to do that is to store the arguments in a Vec<&dyn Encode>. Which is something we could do now since we have a lifetime in ArgumentBuffer.

(There are pro's and con's ofcourse, it'd save a copy here and here but all bind calls would require a reference.)

@iamjpotts
Copy link
Contributor Author

Just as a note: To implement something like #875, you'd have to defer the encoding of the arguments until your in the driver. One way to do that is to store the arguments in a Vec<&dyn Encode>. Which is something we could do now since we have a lifetime in ArgumentBuffer.

(There are pro's and con's ofcourse, it'd save a copy here and here but all bind calls would require a reference.)

One of the design choices of the crate is for the query! and query_file! macros to have semantics similar to println! and format! - meaning you can provide a variable name or expression as a parameter, but not have to explicitly borrow it. The implementation of the query! and query_file! macros always borrows the parameters.

That works with the postgres flavor in sqlx 0.8 because its implementation of Arguments<'_> does not have a lifetime (and thus has the static lifetime). It does not currently work with all of the drivers in 0.8.x, since some of them implement Arguments<'_> with a struct having a lifetime parameter.

When a driver's Arguments implementation has a lifetime, that lifetime is the 'q lifetime on Query and its bind method (used by the code generated by the macros). For postgres, 'q == 'static.

impl<'q, DB: Database> Query<'q, DB, <DB as Database>::Arguments<'q>> {
/// Bind a value for use with this SQL query.
///
/// If the number of times this is called does not match the number of bind parameters that
/// appear in the query (`?` for most SQL flavors, `$1 .. $N` for Postgres) then an error
/// will be returned when this query is executed.
///
/// There is no validation that the value is of the type expected by the query. Most SQL
/// flavors will perform type coercion (Postgres will return a database error).
///
/// If encoding the value fails, the error is stored and later surfaced when executing the query.
pub fn bind<T: 'q + Encode<'q, DB> + Type<DB>>(mut self, value: T) -> Self {

So the opposite is actually the case for named parameter support - to preserve println! similar usage, instead of borrowing the parameter with something like Vec<&dyn Encode>, the parameter has to be either a) immediately encoded into an owned driver-specific buffer for drivers supporting named parameters, or b) the parameter value has to be copied, cloned, or otherwise turned into an owned value with a 'static lifetime.

@abonander abonander merged commit 54a0492 into launchbadge:main Sep 12, 2025
104 checks passed
@iamjpotts iamjpotts deleted the jp/any-arg-lifetime branch September 12, 2025 23:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants