Skip to content

Add merge to Arguments#3652

Closed
dgagn wants to merge 3 commits intolaunchbadge:mainfrom
dgagn:feature/merge-arguments
Closed

Add merge to Arguments#3652
dgagn wants to merge 3 commits intolaunchbadge:mainfrom
dgagn:feature/merge-arguments

Conversation

@dgagn
Copy link

@dgagn dgagn commented Dec 22, 2024

Add merge to Arguments

Currently, there is no convenient way to merge two sets of query builder arguments.

Why?

In my use case, I need to combine arguments from multiple queries, but there's no existing method to do this.

Here is one of my use case

I am building a custom QueryBuilder that would like to take Arguments as a parameter, but can't because of the limitation of the add method on the trait.

I would like something like :

macro_rules! binding {
    [$($arg:expr),* $(,)?] => {{
        let mut args = <Postgres as sqlx::Database>::Arguments::default();
        $(
            args.add($arg).expect("failed to add binding");
        )*
        args
    }};
}

CustomBuilder::new()
    .select_raw("price * ? as price_tax, ? as name", binding![1.2, "test"])
    .from("products")
    .where_raw("price > ?", binding![10])
    // ...

fn select_raw_expr_bindings<T, B>(mut self, columns: T, bindings: B) -> Self
where
    T: Into<String>,
    B: Arguments<'q>,
{
    self.ensure_bindings();
    self.bindings
        .as_mut()
        .expect("bindings should be initialized")
        .merge(bindings); // Merge here
    self.columns = ColumnExpr::Raw(columns.into());
    self
}

But, this is what I have at the moment :

pub struct SelectBuilder<'q> {
    columns: ColumnExpr<'q>,
    table: Ident<'q>,
    bindings: Option<<Postgres as Database>::Arguments<'q>>,
    where_node: Option<Node<'q>>,
    // ...
}

// ...

fn select_raw_expr<T, B>(mut self, columns: T, bindings: B) -> Self
where
    T: Into<String>,
    B: IntoIterator,
    B::Item: 'q + sqlx::Encode<'q, Postgres> + sqlx::Type<Postgres>,
{
    self.ensure_bindings();
    for binding in bindings {
        self.bindings
          .as_mut()
          .expect("bindings should be initialized")
          .add(value)
          .expect("failed to add value to bindings");
    }
    self.columns = ColumnExpr::Raw(columns.into());
    self
}

What I have has a significant limitation; it requires all bindings in the iterator to be of the same type. For example, [1, "test"] would not work because it combines different types (integer and str) in the same collection.

Introducing a merge function would allow developers to combine multiple sets of Arguments.

Here is another method for which I need to wait for merge to be accepted.

pub fn where_subquery<C, F>(mut self, column: C, operator: Operator, subquery_fn: F) -> Self
where
    C: Into<Ident<'q>>,
    F: FnOnce(SelectFromBuilder) -> SelectBuilder<'q>,
{
    let (query, bindings) = subquery_fn(SelectFromBuilder).into_parts();
    if let Some(bindings) = bindings {
        self.ensure_bindings();
        // TODO: wait for merge to be accepted for subqueries
        todo!()
    } else {
        self.where_raw_expr(
            format!("{} {} ({})", column.into().format(), operator, query),
            None::<Vec<&str>>,
        )
    }
}

Thank you

@dgagn dgagn changed the title Merge arguments Add merge to Arguments Dec 22, 2024
@dgagn
Copy link
Author

dgagn commented Apr 30, 2025

@abonander could you review please?

@abonander
Copy link
Collaborator

I get to PRs when I can. Pinging me only fills up my notifications.

Comment on lines +152 to +153
self.buffer.patches.extend(other.buffer.patches);
self.buffer.type_holes.extend(other.buffer.type_holes);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not going to work as expected. These contain offsets into the encoded data which need to be adjusted.

@cody-why

This comment was marked as spam.

@abonander
Copy link
Collaborator

Closing due to inactivity and unaddressed feedback. Feel free to open a new PR if you get back to this.

@abonander abonander closed this Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants