Skip to content

Commit 5e96066

Browse files
authored
Merge pull request #85 from malthe/result-rework
Query result iterator now returns objects
2 parents db1ec02 + a0cc337 commit 5e96066

10 files changed

+170
-202
lines changed

CHANGES.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
In next release ...
2+
3+
- The iterator methods now return reified representations of the query result
4+
(i.e. objects), carrying the generic type parameter specified for the query
5+
(#83).
6+
7+
- The result rows now extend the array type, providing `get` and `reify` methods.
8+
This separates the query results interface into an iterator interface (providing
9+
objects) and a result interface (providing rows and column names).
10+
111
1.5.0 (2023-12-06)
212
------------------
313

README.md

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ $ npm install ts-postgres@latest
2020
* Multiple queries can be sent at once (pipeline)
2121
* Extensible value model
2222
* Hybrid query result object
23-
* Iterable (synchronous or asynchronous; one row at a time)
24-
* Promise-based
25-
* Streaming
23+
* Iterable (synchronous or asynchronous; one object at a time)
24+
* Rows and column names
25+
* Streaming data directly into a socket
2626

2727
See the [documentation](https://malthe.github.io/ts-postgres/) for a complete reference.
2828

@@ -50,9 +50,9 @@ async function main() {
5050
['world']
5151
);
5252

53-
for await (const row of result) {
53+
for await (const obj of result) {
5454
// 'Hello world!'
55-
console.log(row.get('message'));
55+
console.log(obj.message);
5656
}
5757
} finally {
5858
await client.end();
@@ -118,10 +118,9 @@ const query = new Query(
118118
const result = await client.execute<Greeting>(query);
119119
```
120120

121-
If the row type is omitted, it defaults to `Record<string, any>`, but
122-
providing a type ensures that the row values are typed, both when
123-
accessed via the `get` method or if the row is mapped to a record
124-
using the `map` method.
121+
If the object type is omitted, it defaults to `Record<string, any>`, but
122+
providing a type ensures that the object values are typed, both when
123+
accessed via the iterator or record interface (see below).
125124

126125
### Passing query parameters
127126

@@ -139,7 +138,7 @@ different ways:
139138
```typescript
140139
import { DataType } from 'ts-postgres';
141140
const result = await client.query(
142-
"select $1 || ' bottles of beer'", [99], [DataType.Int4]
141+
"SELECT $1 || ' bottles of beer'", [99], [DataType.Int4]
143142
);
144143
```
145144

@@ -150,30 +149,39 @@ should be used.
150149

151150
### Iterator interface
152151

153-
Whether we're operating on a stream or an already waited for result set, the iterator interface provides the most high-level row interface. This also applies when using the _spread_ operator:
152+
The query result can be iterated over, either asynchronously, or after being awaited. The returned objects are reified representations of the result rows, provided as _objects_ of the generic type parameter specified for the query (optional, it defaults to `Record<string, any>`).
153+
154+
To extract all objects from the query result, you can use the _spread_ operator:
154155

155156
```typescript
156-
const rows = [...result];
157+
const result = await client.query("SELECT generate_series(0, 9) AS i");
158+
const objects = [...result];
157159
```
158160

159-
Each row provides direct access to values through its ``data`` attribute, but we can also get a value by name using the ``get(name)`` method.
161+
The asynchronous await syntax around for-loops is another option:
160162

161163
```typescript
162-
for (const row of rows) {
163-
console.log('The number is: ' + row.get('i')); // 1, 2, 3, ...
164+
const result = client.query(...);
165+
for await (const obj of result) {
166+
console.log('The number is: ' + obj.i); // 1, 2, 3, ...
164167
}
165168
```
166-
Note that values are polymorphic and need to be explicitly cast to a concrete type such as ``number`` or ``string``.
167169

168170
### Result interface
169171

170-
This interface is available on the already waited for result object. It makes data available in the ``rows`` attribute as an array of arrays (of values).
172+
The awaited result object provides an interface based on rows and column names.
173+
171174
```typescript
172175
for (const row of result.rows) {
176+
// Using the array indices:
173177
console.log('The number is: ' + row[0]); // 1, 2, 3, ...
178+
179+
// Using the column name:
180+
console.log('The number is: ' + row.get('i')); // 1, 2, 3, ...
174181
}
175182
```
176-
This is the most efficient way to work with result data. Column names are available as the ``names`` attribute of a result.
183+
184+
Column names are available via the ``names`` property.
177185

178186
### Streaming
179187

@@ -208,8 +216,8 @@ You can prepare a query and subsequently execute it multiple times. This is also
208216
const statement = await client.prepare(
209217
`SELECT 'Hello ' || $1 || '!' AS message`
210218
);
211-
for await (const row of statement.execute(['world'])) {
212-
console.log(row.get('message')); // 'Hello world!'
219+
for await (const object of statement.execute(['world'])) {
220+
console.log(object.message); // 'Hello world!'
213221
}
214222
```
215223
When the prepared statement is no longer needed, it should be closed to release the resource.

package-lock.json

Lines changed: 1 addition & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
"singleQuote": true
6666
},
6767
"devDependencies": {
68-
"@types/jest": "^29.5.8",
68+
"@jest/globals": "^29.7.0",
6969
"@types/node": "^18.15.3",
7070
"@typescript-eslint/eslint-plugin": "^6.10.0",
7171
"@typescript-eslint/parser": "^6.10.0",

src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ type Event = (
118118
type CloseHandler = () => void;
119119

120120
interface RowDataHandler {
121-
callback: DataHandler<any[]>,
121+
callback: DataHandler,
122122
streams: Record<string, Writable>,
123123
}
124124

0 commit comments

Comments
 (0)