Skip to content

Commit 4880d8f

Browse files
committed
Fleshing out the API docs in more detail.
1 parent c89fc37 commit 4880d8f

File tree

2 files changed

+113
-55
lines changed

2 files changed

+113
-55
lines changed

src/content/docs/d1/worker-api/prepare-a-statement.mdx

Lines changed: 92 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@ import { Type, MetaInfo, Details } from "~/components";
99

1010
You can execute queries on your D1 database through SQL query statements. To do this, you need to follow these steps:
1111

12-
1. Prepare your query statement.
13-
2. If appliable, bind variables into your statement.
14-
3. Execute your query.
12+
1. Prepare your query statement (including binding variables into the statement).
13+
2. Execute your query.
14+
15+
This chapter documents how to prepare a statement and how to execute them.
1516

1617
## TypeScript support
1718

1819
D1 Worker Bindings API is fully-typed via the `@cloudflare/workers-types` package, and also supports [generic types](https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-types) as part of its TypeScript API. A generic type allows you to provide an optional _type parameter_ so that a function understands the type of the data it is handling.
1920

20-
When using the [query statement methods](#query-statement-methods) `stmt.all()`, `stmt.raw()` and `stmt.first()`, you can provide a type representing each database row. D1's API will [return the result object](#return-object) with the correct type.
21+
When using the [query statement methods](#query-statement-methods) `stmt.run()`, `stmt.raw()` and `stmt.first()`, you can provide a type representing each database row. D1's API will [return the result object](#return-object) with the correct type.
2122

22-
For example, providing an `OrderRow` type as a type parameter to `stmt.all()` will return a typed `Array<OrderRow>` object instead of the default `Record<string, unknown>` type:
23+
For example, providing an `OrderRow` type as a type parameter to `stmt.run()` will return a typed `Array<OrderRow>` object instead of the default `Record<string, unknown>` type:
2324

2425
```ts
2526
// Row definition
@@ -32,14 +33,16 @@ type OrderRow = {
3233
// Elsewhere in your application
3334
const result = await env.MY_DB.prepare(
3435
"SELECT Id, CustomerName, OrderDate FROM [Order] ORDER BY ShippedDate DESC LIMIT 100",
35-
).all<OrderRow>();
36+
).run<OrderRow>();
3637
```
3738

3839
## Methods
3940

4041
### `db.prepare()`
4142

42-
Prepares a query statement statement. D1 API supports both prepared and static statements.
43+
Prepares a query statement to be later executed.
44+
45+
D1 API supports both prepared and static statements.
4346

4447
- Prepared statements are SQL statements where the variables are dynamically determined. When writing a prepared statement, you insert variables into placeholders within the statement string.
4548
- 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.
@@ -51,19 +54,18 @@ The recommended approach is to use prepared statements (which are precompiled ob
5154
Example of a prepared statement with dynamically bound value:
5255

5356
```js
54-
// Dynamically generate the value to use.
55-
const someVariable = "John Doe";
56-
const stmt = db.prepare("SELECT * FROM users WHERE name = ?1").bind(someVariable);
57-
// A variable (someVariable) will replace the placeholder '?1' in the query.
57+
const someVariable = `Bs Beverages`;
58+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
59+
// A variable (someVariable) will replace the placeholder '?' in the query.
5860
// `stmt` is a prepared statement.
5961
```
6062

6163
Example of a static statement:
6264

6365
```js
64-
const stmt = db.prepare('SELECT * FROM users WHERE name = "John Doe"');
65-
// "John Doe" is hard-coded into the query.
66-
// `stmt` will also be a prepared statement.
66+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = Bs Beverages");
67+
// "Bs Beverages" is hard-coded into the query.
68+
// `stmt` is a static statement.
6769
```
6870

6971
#### Parameters
@@ -73,8 +75,7 @@ const stmt = db.prepare('SELECT * FROM users WHERE name = "John Doe"');
7375

7476
#### Return values
7577

76-
- <code>queryResult</code>:
77-
- The result of the SQL query.
78+
- None.
7879

7980
#### Guidance
8081

@@ -96,33 +97,36 @@ const stmt = db.prepare('SELECT * FROM users WHERE name = "John Doe"');
9697
Order and anonymous examples:
9798

9899
```js
99-
const stmt = db.prepare("SELECT * FROM users WHERE name = ?").bind("John Doe");
100+
const stmt = db.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind("");
100101
```
101102

102103
```js
103104
const stmt = db
104-
.prepare("SELECT * FROM users WHERE name = ? AND age = ?")
105-
.bind("John Doe", 41);
105+
.prepare("SELECT * FROM Customers WHERE CompanyName = ? AND CustomerId = ?")
106+
.bind("Alfreds Futterkiste", 1);
106107
```
107108

108109
```js
109110
const stmt = db
110-
.prepare("SELECT * FROM users WHERE name = ?2 AND age = ?1")
111-
.bind(41, "John Doe");
111+
.prepare("SELECT * FROM Customers WHERE CompanyName = ?2 AND CustomerId = ?1")
112+
.bind(1, "Alfreds Futterkiste");
112113
```
113114

114115
### `db.batch()`
115116

116-
Batching sends multiple SQL statements inside a single call to the database. This can have a huge performance impact as it reduces latency from network round trips to D1. D1 operates in auto-commit. Our implementation guarantees that each statement in the list will execute and commit, sequentially, non-concurrently.
117+
Sends multiple SQL statements inside a single call to the database. This can have a huge performance impact as it reduces latency from network round trips to D1. D1 operates in auto-commit. Our implementation guarantees that each statement in the list will execute and commit, sequentially, non-concurrently.
117118

118119
Batched statements are [SQL transactions](https://www.sqlite.org/lang_transaction.html). If a statement in the sequence fails, then an error is returned for that specific statement, and it aborts or rolls back the entire sequence.
119120

120121
To send batch statements, provide `.batch()` a list of prepared statements and get the results in the same order.
121122

122123
```js
123-
await db.batch([
124-
db.prepare("UPDATE users SET name = ?1 WHERE id = ?2").bind("John", 17),
125-
db.prepare("UPDATE users SET age = ?1 WHERE id = ?2").bind(35, 19),
124+
const companyName1 = `Bs Beverages`;
125+
const companyName2 = `Around the Horn`;
126+
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
127+
const batchResult = await env.DB.batch([
128+
stmt.bind(companyName1),
129+
stmt.bind(companyName2)
126130
]);
127131
```
128132

@@ -140,35 +144,73 @@ await db.batch([
140144
<Details header="Example of return values" open={false}>
141145

142146
```js
143-
const rows = await db.batch([
144-
db.prepare("SELECT * FROM users WHERE name = ?1").bind("John"),
145-
db.prepare("SELECT * FROM users WHERE name = ?1").bind("Anthony")
147+
const companyName1 = `Bs Beverages`;
148+
const companyName2 = `Around the Horn`;
149+
const stmt = await env.DB.batch([
150+
env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName1),
151+
env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`).bind(companyName2)
146152
]);
147-
```
148-
```js
149-
console.log(rows[0].results);
153+
return Response.json(stmt)
150154
```
151155
```js output
152156
[
153157
{
154-
name: "John Clemente",
155-
age: 42,
156-
},
157-
{
158-
name: "John Davis",
159-
age: 37,
158+
"success": true,
159+
"meta": {
160+
"served_by": "miniflare.db",
161+
"duration": 0,
162+
"changes": 0,
163+
"last_row_id": 0,
164+
"changed_db": false,
165+
"size_after": 8192,
166+
"rows_read": 4,
167+
"rows_written": 0
168+
},
169+
"results": [
170+
{
171+
"CustomerId": 11,
172+
"CompanyName": "Bs Beverages",
173+
"ContactName": "Victoria Ashworth"
174+
},
175+
{
176+
"CustomerId": 13,
177+
"CompanyName": "Bs Beverages",
178+
"ContactName": "Random Name"
179+
}
180+
]
160181
},
161-
]
182+
{
183+
"success": true,
184+
"meta": {
185+
"served_by": "miniflare.db",
186+
"duration": 0,
187+
"changes": 0,
188+
"last_row_id": 0,
189+
"changed_db": false,
190+
"size_after": 8192,
191+
"rows_read": 4,
192+
"rows_written": 0
193+
},
194+
"results": [
195+
{
196+
"CustomerId": 4,
197+
"CompanyName": "Around the Horn",
198+
"ContactName": "Thomas Hardy"
199+
}
200+
]
201+
}
202+
]
162203
```
163204
```js
164-
console.log(rows[1].results);
205+
console.log(stmt[1].results);
165206
```
166207
```js output
167208
[
168209
{
169-
name: "Anthony Hopkins",
170-
age: 66,
171-
},
210+
"CustomerId": 4,
211+
"CompanyName": "Around the Horn",
212+
"ContactName": "Thomas Hardy"
213+
}
172214
]
173215
```
174216
</Details>
@@ -178,9 +220,14 @@ console.log(rows[1].results);
178220
- You can construct batches reusing the same prepared statement:
179221

180222
```js
181-
const stmt = db.prepare("SELECT * FROM users WHERE name = ?1");
182-
183-
const rows = await db.batch([stmt.bind("John"), stmt.bind("Anthony")]);
223+
const companyName1 = `Bs Beverages`;
224+
const companyName2 = `Around the Horn`;
225+
const stmt = env.DB.prepare(`SELECT * FROM Customers WHERE CompanyName = ?`);
226+
const batchResult = await env.DB.batch([
227+
stmt.bind(companyName1),
228+
stmt.bind(companyName2)
229+
]);
230+
return Response.json(batchResult);
184231
```
185232

186233
### `db.exec()`

src/content/docs/d1/worker-api/run-a-statement.mdx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import { Type, MetaInfo, Details } from "~/components";
99

1010
## Description
1111

12-
After preparing a query statement, you can run and retrieve the results of the query.
12+
You can execute queries on your D1 database through SQL query statements. To do this, you need to follow these steps:
13+
14+
1. Prepare your query statement (including binding variables into the statement).
15+
2. Execute your query.
16+
17+
This chapter documents the various ways you can run and retrieve the results of a query after you have prepared your statement.
1318

1419
## Methods
1520

@@ -173,7 +178,7 @@ const values = await stmt.first();
173178
#### Parameters
174179

175180
- <code>columnName</code>: <Type text="String"/> <MetaInfo text="Optional"/>
176-
- Specify a `columnName` to return the value from a specific column in the first row of the query result.
181+
- Specify a `columnName` to return a value from a specific column in the first row of the query result.
177182
- None.
178183
- Do not pass a parameter to obtain all columns from the first row.
179184

@@ -190,23 +195,29 @@ const values = await stmt.first();
190195
Get all the columns from the first row:
191196

192197
```js
193-
const stmt = db.prepare("SELECT COUNT(*) AS total FROM users");
194-
const values = await stmt.first();
195-
console.log(values);
198+
const someVariable = `Bs Beverages`;
199+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
200+
const returnValue = await stmt.first();
201+
return Response.json(returnValue)
196202
```
197203
```js output
198-
{ total: 50 }
204+
{
205+
"CustomerId": 11,
206+
"CompanyName": "Bs Beverages",
207+
"ContactName": "Victoria Ashworth"
208+
}
199209
```
200210

201211
Get a specific column from the first row:
202212

203213
```js
204-
const stmt = db.prepare("SELECT COUNT(*) AS total FROM users");
205-
const total = await stmt.first("total");
206-
console.log(total);
214+
const someVariable = `Bs Beverages`;
215+
const stmt = env.DB.prepare("SELECT * FROM Customers WHERE CompanyName = ?").bind(someVariable);
216+
const returnValue = await stmt.first(CustomerId);
217+
return Response.json(returnValue)
207218
```
208219
```js output
209-
50 // NEED CONFIRMING
220+
11
210221
```
211222
</Details>
212223

0 commit comments

Comments
 (0)