Skip to content

Named parameters#421

Open
adespawn wants to merge 3 commits intoscylladb:mainfrom
adespawn:named-parameters
Open

Named parameters#421
adespawn wants to merge 3 commits intoscylladb:mainfrom
adespawn:named-parameters

Conversation

@adespawn
Copy link
Copy Markdown
Contributor

@adespawn adespawn commented Mar 26, 2026

This PR introduces support for named parameters in prepared (queries/statements). By reusing handling logic (code in utils.js), I aim to keep the API compatibility with DSx driver.

At a later point, we can have a discussion about whether we want to still accept case-insensitive parameters, or do we want to enforce case sensitivity.

This does not fully close​ #99, as the DSx driver had support for named parameters in unprepared (queries/statements) in some special cases (when type hints were used in a specific way). Such support will be added in the following PRs.

This class aims to replace the current mess of types that were used
for representing prepared statement information across the JS code.

This will be useful in the next commit(s) that will introduce named parameters.
@adespawn adespawn mentioned this pull request Mar 27, 2026
@adespawn adespawn requested a review from Copilot March 27, 2026 10:28
@adespawn adespawn marked this pull request as ready for review March 27, 2026 10:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for named parameters for prepared statements by retrieving prepared variable metadata (types + variable names) from the Rust layer and reusing the existing parameter-adaptation logic in lib/utils.js, aligning behavior with the DataStax Node.js driver.

Changes:

  • Re-enabled/added integration tests covering named parameters for prepared execute() and prepared batch().
  • Updated Rust prepareStatement to return (type, variableName) pairs and introduced PreparedInfo on the JS side to hold prepared query metadata.
  • Wired named-parameter detection/adaptation into prepared execution paths (including concurrent execution).

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/integration/supported/client-execute-prepared-tests.js Re-enables prepared named-parameter integration tests.
test/integration/supported/client-batch-tests.js Re-enables batch named-parameter integration tests.
src/session.rs Changes prepare_statement to return type + variable name tuples to JS.
src/requests/request.rs Extracts variable names alongside types from prepared metadata.
lib/utils.js Adapts named parameters using PreparedInfo (types + column names).
lib/prepared.js New PreparedInfo wrapper to build prepared metadata from Rust prepareStatement().
lib/new-utils.js Adds isNamedParameters() helper for consistent validation/erroring.
lib/concurrent/index.js Updates concurrent executor to cache/use PreparedInfo.
lib/client.js Integrates PreparedInfo and named-param adaptation into prepared execution and paging paths.
Comments suppressed due to low confidence (1)

lib/client.js:733

  • #rustyBatch() can still receive params as an object (the public batch() signature allows (Array|Object)?), but when shouldBePrepared is false those objects are passed directly into encodeParams(), which expects an array (params.length) and will throw a low-level TypeError. Add the same validation used in execute()/#rustyPaged() (e.g., reuse isNamedParameters() or explicitly throw ArgumentError when params is a non-array object and prepare is not enabled) to fail fast with a clear error message.
                typeof element === "string" ? element : element.query;
            let params = element.params || [];
            let types;

            if (!statement) {
                throw new errors.ArgumentError(`Invalid query at index ${i}`);
            }

            if (shouldBePrepared) {
                let prepared = preparedCache.getElement(statement);
                if (!prepared) {
                    prepared = await PreparedInfo.create(
                        statement,
                        this.rustClient,
                    );
                    preparedCache.storeElement(statement, prepared);
                }
                types = prepared.types;
                statement = prepared.query;

                if (params && !Array.isArray(params)) {
                    params = utils.adaptNamedParamsPrepared(params, prepared);
                }
            } else {
                types = hints[i] || [];
            }

            if (params) {
                params = encodeParams(types, params, this.#encoder);
            }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

This commit introduces support for named parameters in prepared statements.
The desired behavior is based on DSx integration tests:

When an object is passed as params instead of an array, the driver
maps parameter names to positional indices using column metadata
from prepared info. Lookup is case-insensitive; extra properties not
matching any column are silently ignored. Supported in execute(),
eachRow()/stream() (paged), and batch() with { prepare: true }.
@adespawn adespawn self-assigned this Mar 27, 2026
@adespawn adespawn requested review from nikagra and wprzytula March 27, 2026 12:50
@adespawn adespawn modified the milestone: GA Mar 27, 2026
@wprzytula
Copy link
Copy Markdown
Contributor

I'd prefer to review this only after @nikagra. Is this OK?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants