Skip to content

Conversation

staticlibs
Copy link
Collaborator

This PR adds new optional params argument to mysql_query and mysql_execute functions that allows to pass query parameters to an underlying MySQL prepared statement (that was added in #156).

Parameters are specified as a STRUCT, that can be created inline using row() function:

SELECT * from mysql_query('s', 'SELECT CONCAT(?, ?) a', params=row('foo', 'bar'))
----
foobar

When the whole DuckDB SQL statement, that contains mysql_query() function, is used with PREPARE + EXECUTE (for example, from Python or Java client), then the external client-provided parameters will be forwarded to MySQL:

PREPARE p1 as SELECT * from mysql_query('s', 'SELECT CONCAT(?, ?) a', params=row(?, ?))

EXECUTE p1('foo', 'bar')
----
foobar

EXECUTE p1('baz', 'boo')
----
bazboo

DEALLOCATE p1

In current implementation the statement is re-prepared (re-sent to MySQL server) every time when EXECUTE is called.

The following parameter types are supported: integers, FLOAT, DOUBLE, DATE, TIME, TIMESTAMP, TIMESTAMP_TZ, VARCHAR.

DECIMAL parameters are currently not supported, they can only be specified as strings on API level, so casts to/from VARCHAR can be used instead.

Only positional parameters are supported - STRUCT field names are ignored.

Testing: new tests added for mysql_query and mysql_execute fuctions.

This PR adds new optional `params` argument to `mysql_query` and
`mysql_execute` functions that allows to pass query parameters to an
underlying MySQL prepared statement (that was added in duckdb#156).

Parameters are specified as a `STRUCT`, that can be created inline using
`row()` function:

```sql
SELECT * from mysql_query('s', 'SELECT CONCAT(?, ?) a', params=row('foo', 'bar'))
----
foobar
```

When the whole DuckDB SQL statement, that contains `mysql_query()`
function, is used with `PREPARE` + `EXECUTE` (for example, from Python
or Java client), then the external client-provided parameters will be
forwarded to MySQL:

```sql
PREPARE p1 as SELECT * from mysql_query('s', 'SELECT CONCAT(?, ?) a', params=row(?, ?))

EXECUTE p1('foo', 'bar')
----
foobar

EXECUTE p1('baz', 'boo')
----
bazboo

DEALLOCATE p1
```

In current implementation the statement is re-prepared (re-sent to MySQL
server) every time when `EXECUTE` is called.

The following parameter types are supported: integers, `FLOAT`,
`DOUBLE`, `DATE`, `TIME`, `TIMESTAMP`, `TIMESTAMP_TZ`, `VARCHAR`.

`DECIMAL` parameters are currently not supported, they can only be
specified as strings on API level, so casts to/from `VARCHAR` can be
used instead.

Only positional parameters are supported - `STRUCT` field names are
ignored.

Testing: new tests added for `mysql_query` and `mysql_execute` fuctions.
@Mytherin Mytherin merged commit 2af8a98 into duckdb:main Sep 26, 2025
16 checks passed
@Mytherin
Copy link
Contributor

Thanks!

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.

2 participants