From 6149c98abcaeb0a0c01d2781c9293d2b3f534ee5 Mon Sep 17 00:00:00 2001 From: Jun Lee Date: Tue, 7 Jan 2025 16:19:29 +0000 Subject: [PATCH 1/3] Adding information on D1PreparedStatement object. --- src/content/docs/d1/worker-api/d1-database.mdx | 3 ++- src/content/docs/d1/worker-api/prepared-statements.mdx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/content/docs/d1/worker-api/d1-database.mdx b/src/content/docs/d1/worker-api/d1-database.mdx index e3b0ebe834f1e4e..7cd658c3901653f 100644 --- a/src/content/docs/d1/worker-api/d1-database.mdx +++ b/src/content/docs/d1/worker-api/d1-database.mdx @@ -35,7 +35,8 @@ const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bin #### Return values -- None. +- D1PreparedStatement: + - An object which only contains methods `bind`,`run`, `raw`, and `first`. #### Guidance diff --git a/src/content/docs/d1/worker-api/prepared-statements.mdx b/src/content/docs/d1/worker-api/prepared-statements.mdx index 89e0f0065effaaa..9eda8f4bf4ffee7 100644 --- a/src/content/docs/d1/worker-api/prepared-statements.mdx +++ b/src/content/docs/d1/worker-api/prepared-statements.mdx @@ -23,7 +23,7 @@ const returnValue = await stmt.run(); - None. -#### Return value +#### Return values - D1Result: - An object containing the success status, a meta object, and an array of objects containing the query results. From 3728197492e5073fb10632c389a121fb5ebd5c1c Mon Sep 17 00:00:00 2001 From: Jun Lee Date: Tue, 7 Jan 2025 16:56:41 +0000 Subject: [PATCH 2/3] Relocating `bind` documentation, tweaking docs to accommodate this change. --- .../docs/d1/worker-api/d1-database.mdx | 54 +------------- .../d1/worker-api/prepared-statements.mdx | 73 +++++++++++++++++++ 2 files changed, 75 insertions(+), 52 deletions(-) diff --git a/src/content/docs/d1/worker-api/d1-database.mdx b/src/content/docs/d1/worker-api/d1-database.mdx index 7cd658c3901653f..431ea64db8eec05 100644 --- a/src/content/docs/d1/worker-api/d1-database.mdx +++ b/src/content/docs/d1/worker-api/d1-database.mdx @@ -36,61 +36,11 @@ const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bin #### Return values - D1PreparedStatement: - - An object which only contains methods `bind`,`run`, `raw`, and `first`. + - An object which only contains methods. The methods are: [`bind`](/d1/worker-api/prepared-statements/#bind), [`run`](/d1/worker-api/prepared-statements/#run), [`raw`](/d1/worker-api/prepared-statements/#raw), and [`first`](/d1/worker-api/prepared-statements/#first). #### Guidance -- D1 follows the [SQLite convention](https://www.sqlite.org/lang_expr.html#varparam) for prepared statements parameter binding. Currently, D1 only supports Ordered (`?NNNN`) and Anonymous (`?`) parameters. In the future, D1 will support named parameters as well. - - | Syntax | Type | Description | - | ------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | `?NNN` | Ordered | A question mark followed by a number `NNN` holds a spot for the `NNN`-th parameter. `NNN` must be between `1` and `SQLITE_MAX_VARIABLE_NUMBER` | - | `?` | Anonymous | A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. If this means the parameter number is greater than `SQLITE_MAX_VARIABLE_NUMBER`, it is an error. This parameter format is provided for compatibility with other database engines. But because it is easy to miscount the question marks, the use of this parameter format is discouraged. Programmers are encouraged to use one of the symbolic formats below or the `?NNN` format above instead. | - - To bind a parameter, use the `.bind` method. - - Order and anonymous examples: - - ```js - const stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(""); - ``` - - ```js - const stmt = db - .prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?") - .bind("Alfreds Futterkiste", 1); - ``` - - ```js - const stmt = db - .prepare("SELECT * FROM Customers WHERE CompanyName = ?2 AND CustomerId = ?1") - .bind(1, "Alfreds Futterkiste"); - ``` - -#### Static statements - -D1 API supports static statements. Static statements are SQL statements where the variables have been hard coded. When writing a static statement, you manually type the variable within the statement string. - -:::note -The recommended approach is to bind parameters to create a prepared statement (which are precompiled objects used by the database) to run the SQL. Prepared statements lead to faster overall execution and prevent SQL injection attacks. -::: - -Example of a prepared statement with dynamically bound value: - -```js -const someVariable = `Bs Beverages`; -const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable); -// A variable (someVariable) will replace the placeholder '?' in the query. -// `stmt` is a prepared statement. -``` - -Example of a static statement: - -```js -const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = Bs Beverages"); -// "Bs Beverages" is hard-coded into the query. -// `stmt` is a static statement. -``` +- Preparing a query statement typically involves using the `bind` method to dynamically bind any required parameters into the statement. Refer to the [`bind` method documentation](/d1/worker-api/prepared-statements/#bind). ### `batch()` diff --git a/src/content/docs/d1/worker-api/prepared-statements.mdx b/src/content/docs/d1/worker-api/prepared-statements.mdx index 9eda8f4bf4ffee7..d54cf6c3740b7be 100644 --- a/src/content/docs/d1/worker-api/prepared-statements.mdx +++ b/src/content/docs/d1/worker-api/prepared-statements.mdx @@ -11,6 +11,79 @@ This chapter documents the various ways you can run and retrieve the results of ## Methods +### `bind()` + +Binds a parameter to the prepared statement. + +```js +const someVariable = `Bs Beverages`; +const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable); +``` + +#### Parameter + +- Variable: + - The variable to be appended into the prepared statement. See [guidance](#guidance) below. + +#### Return values + +- D1PreparedStatement: + - A `D1PreparedStatement` where the input parameter has been included in the statement. + +#### Guidance + +- D1 follows the [SQLite convention](https://www.sqlite.org/lang_expr.html#varparam) for prepared statements parameter binding. Currently, D1 only supports Ordered (`?NNNN`) and Anonymous (`?`) parameters. In the future, D1 will support named parameters as well. + + | Syntax | Type | Description | + | ------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | `?NNN` | Ordered | A question mark followed by a number `NNN` holds a spot for the `NNN`-th parameter. `NNN` must be between `1` and `SQLITE_MAX_VARIABLE_NUMBER` | + | `?` | Anonymous | A question mark that is not followed by a number creates a parameter with a number one greater than the largest parameter number already assigned. If this means the parameter number is greater than `SQLITE_MAX_VARIABLE_NUMBER`, it is an error. This parameter format is provided for compatibility with other database engines. But because it is easy to miscount the question marks, the use of this parameter format is discouraged. Programmers are encouraged to use one of the symbolic formats below or the `?NNN` format above instead. | + + To bind a parameter, use the `.bind` method. + + Order and anonymous examples: + + ```js + const stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(""); + ``` + + ```js + const stmt = db + .prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?") + .bind("Alfreds Futterkiste", 1); + ``` + + ```js + const stmt = db + .prepare("SELECT * FROM Customers WHERE CompanyName = ?2 AND CustomerId = ?1") + .bind(1, "Alfreds Futterkiste"); + ``` + +#### Static statements + +D1 API supports static statements. Static statements are SQL statements where the variables have been hard coded. When writing a static statement, you manually type the variable within the statement string. + +:::note +The recommended approach is to bind parameters to create a prepared statement (which are precompiled objects used by the database) to run the SQL. Prepared statements lead to faster overall execution and prevent SQL injection attacks. +::: + +Example of a prepared statement with dynamically bound value: + +```js +const someVariable = `Bs Beverages`; +const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable); +// A variable (someVariable) will replace the placeholder '?' in the query. +// `stmt` is a prepared statement. +``` + +Example of a static statement: + +```js +const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = Bs Beverages"); +// "Bs Beverages" is hard-coded into the query. +// `stmt` is a static statement. +``` + ### `run()` Runs the prepared query (or queries) and returns results. The returned results includes metadata. From 82a3cf6fd99b558dda252d63185733f3277877c3 Mon Sep 17 00:00:00 2001 From: Jun Lee Date: Tue, 7 Jan 2025 17:13:29 +0000 Subject: [PATCH 3/3] Adding an example in-situ for convenience for readers. --- .../docs/d1/worker-api/d1-database.mdx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/content/docs/d1/worker-api/d1-database.mdx b/src/content/docs/d1/worker-api/d1-database.mdx index 431ea64db8eec05..1896c447bc95331 100644 --- a/src/content/docs/d1/worker-api/d1-database.mdx +++ b/src/content/docs/d1/worker-api/d1-database.mdx @@ -36,11 +36,28 @@ const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bin #### Return values - D1PreparedStatement: - - An object which only contains methods. The methods are: [`bind`](/d1/worker-api/prepared-statements/#bind), [`run`](/d1/worker-api/prepared-statements/#run), [`raw`](/d1/worker-api/prepared-statements/#raw), and [`first`](/d1/worker-api/prepared-statements/#first). + - An object which only contains methods. Refer to [Prepared statement methods](/d1/worker-api/prepared-statements/). #### Guidance -- Preparing a query statement typically involves using the `bind` method to dynamically bind any required parameters into the statement. Refer to the [`bind` method documentation](/d1/worker-api/prepared-statements/#bind). +You can use the `bind` method to dynamically bind a value into the query statement, as shown below. + +- Example of a static statement without using `bind`: + + ```js + const stmt = db + .prepare("SELECT * FROM Customers WHERE CompanyName = Alfreds Futterkiste AND CustomerId = 1") + ``` + +- Example of an ordered statement using `bind`: + + ```js + const stmt = db + .prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?") + .bind("Alfreds Futterkiste", 1); + ``` + +Refer to the [`bind` method documentation](/d1/worker-api/prepared-statements/#bind) for more information. ### `batch()`