postgrejs 3.8.0 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -1
- package/README.md +50 -0
- package/connection/connection.d.ts +14 -2
- package/connection/connection.js +63 -11
- package/connection/intl-connection.d.ts +164 -6
- package/connection/intl-connection.js +558 -37
- package/connection/pool.d.ts +30 -6
- package/connection/pool.js +22 -3
- package/connection/prepared-statement.js +22 -2
- package/data-type-map.d.ts +16 -0
- package/data-type-map.js +56 -12
- package/data-types/circle-type.js +5 -2
- package/data-types/classes/geometric.d.ts +49 -7
- package/data-types/classes/geometric.js +59 -11
- package/data-types/classes/interval.d.ts +40 -16
- package/data-types/classes/interval.js +68 -40
- package/data-types/classes/numeric.d.ts +6 -0
- package/data-types/classes/numeric.js +8 -0
- package/data-types/classes/range.d.ts +6 -1
- package/data-types/classes/range.js +6 -1
- package/data-types/date-type.js +2 -2
- package/data-types/interval-type.js +1 -1
- package/data-types/money-type.d.ts +38 -0
- package/data-types/money-type.js +212 -0
- package/data-types/numeric-type.d.ts +2 -0
- package/data-types/numeric-type.js +22 -11
- package/data-types/temporal-types.d.ts +19 -0
- package/data-types/temporal-types.js +520 -0
- package/data-types/timestamp-type.js +2 -2
- package/data-types/timestamptz-type.js +2 -2
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/interfaces/data-mapping-options.d.ts +126 -4
- package/interfaces/database-connection-params.d.ts +32 -5
- package/interfaces/query-options.d.ts +32 -0
- package/interfaces/script-execute-options.d.ts +32 -0
- package/interfaces/transaction-options.d.ts +27 -0
- package/interfaces/transaction-options.js +1 -0
- package/package.json +1 -1
- package/protocol/database-error.d.ts +15 -0
- package/protocol/database-error.js +19 -0
- package/protocol/frontend.js +1 -1
- package/protocol/pg-socket.js +7 -10
- package/util/array-leaf.d.ts +10 -0
- package/util/array-leaf.js +22 -0
- package/util/connection-config.js +11 -1
- package/util/date-style.d.ts +47 -0
- package/util/date-style.js +123 -0
- package/util/decimal-as-string.d.ts +11 -0
- package/util/decimal-as-string.js +30 -0
- package/util/fetch-as-string.d.ts +33 -0
- package/util/fetch-as-string.js +122 -0
- package/util/get-parsers.js +18 -1
- package/util/parse-datetime.d.ts +4 -3
- package/util/parse-datetime.js +34 -9
- package/util/resolve-column-formats.d.ts +5 -11
- package/util/resolve-column-formats.js +28 -24
- package/util/row-decoder.d.ts +24 -4
- package/util/row-decoder.js +25 -10
- package/util/sql-tag.js +2 -1
- package/util/stringify-for-sql.js +6 -5
- package/util/temporal.d.ts +47 -0
- package/util/temporal.js +61 -0
- package/util/transaction-command.d.ts +7 -0
- package/util/transaction-command.js +32 -0
- package/util/unspecified-param.d.ts +18 -8
- package/util/unspecified-param.js +22 -14
package/connection/pool.d.ts
CHANGED
|
@@ -5,16 +5,21 @@ import type { QueryResult } from '../interfaces/query-result.js';
|
|
|
5
5
|
import type { ScriptExecuteOptions } from '../interfaces/script-execute-options.js';
|
|
6
6
|
import type { ScriptResult } from '../interfaces/script-result.js';
|
|
7
7
|
import type { StatementPrepareOptions } from '../interfaces/statement-prepare-options.js';
|
|
8
|
+
import type { TransactionOptions } from '../interfaces/transaction-options.js';
|
|
8
9
|
import { SafeEventEmitter } from '../safe-event-emitter.js';
|
|
9
10
|
import { QueryRequest } from '../util/sql-tag.js';
|
|
10
11
|
import { Connection, type NotificationCallback } from './connection.js';
|
|
11
12
|
import { IntlConnection } from './intl-connection.js';
|
|
12
13
|
import type { PreparedStatement } from './prepared-statement.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated `pipeline` is part of `QueryOptions` and
|
|
16
|
+
* `ScriptExecuteOptions` now, so every connection takes it too. Kept as
|
|
17
|
+
* an alias of that one field so the exported type still means what it
|
|
18
|
+
* did.
|
|
19
|
+
*/
|
|
20
|
+
export type PoolPipelineOptions = Pick<QueryOptions, 'pipeline'>;
|
|
21
|
+
export type PoolQueryOptions = QueryOptions;
|
|
22
|
+
export type PoolScriptExecuteOptions = ScriptExecuteOptions;
|
|
18
23
|
/**
|
|
19
24
|
* One pooled connection the pipelined path is currently borrowing.
|
|
20
25
|
*
|
|
@@ -93,7 +98,7 @@ export declare class Pool extends SafeEventEmitter {
|
|
|
93
98
|
* is free to pick a different connection, and a transaction lives on
|
|
94
99
|
* one. This is the way to get several statements onto the same one.
|
|
95
100
|
*/
|
|
96
|
-
transaction<T>(fn: (connection: Connection) => Promise<T
|
|
101
|
+
transaction<T>(fn: (connection: Connection) => Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
97
102
|
prepare(sql: string, options?: StatementPrepareOptions): Promise<PreparedStatement>;
|
|
98
103
|
release(connection: Connection): Promise<void>;
|
|
99
104
|
listen(channel: string, callback: NotificationCallback): Promise<void>;
|
|
@@ -113,6 +118,25 @@ export declare class Pool extends SafeEventEmitter {
|
|
|
113
118
|
* the connection had no query in flight to reject.
|
|
114
119
|
*/
|
|
115
120
|
protected _onConnectionDestroyed(intlCon: IntlConnection): void;
|
|
121
|
+
/**
|
|
122
|
+
* Whether a one-shot query may share a pooled connection with the
|
|
123
|
+
* queries already in flight on it.
|
|
124
|
+
*
|
|
125
|
+
* **Opt-in**, per call or with `pipeline: true` on the pool. It is
|
|
126
|
+
* worth asking for - `max` stops being a ceiling on concurrent
|
|
127
|
+
* queries and becomes one on connections, and a burst of 500 through
|
|
128
|
+
* a pool of 10 measured 12ms against 29ms - but it is not the default,
|
|
129
|
+
* because it moves the query onto a connection other callers are
|
|
130
|
+
* using and session state there stops being the caller's own.
|
|
131
|
+
*
|
|
132
|
+
* The exclusions below are not policy, they are statements that need a
|
|
133
|
+
* connection to themselves for longer than the call takes to resolve:
|
|
134
|
+
* a cursor reads from a portal afterwards, a transaction spans later
|
|
135
|
+
* statements, a COPY holds the connection mid-stream, `autoCommit:
|
|
136
|
+
* false` says a transaction is being managed by hand, and an
|
|
137
|
+
* `AbortSignal` cancels by tearing down whatever the connection is
|
|
138
|
+
* doing - which, shared, is not only this query.
|
|
139
|
+
*/
|
|
116
140
|
protected _canPipeline(pipeline: boolean | undefined, sql: string, autoCommit: boolean | undefined, signal: AbortSignal | undefined): boolean;
|
|
117
141
|
/**
|
|
118
142
|
* Picks the pooled connection a pipelined query should ride on, or
|
package/connection/pool.js
CHANGED
|
@@ -272,10 +272,10 @@ export class Pool extends SafeEventEmitter {
|
|
|
272
272
|
* is free to pick a different connection, and a transaction lives on
|
|
273
273
|
* one. This is the way to get several statements onto the same one.
|
|
274
274
|
*/
|
|
275
|
-
async transaction(fn) {
|
|
275
|
+
async transaction(fn, options) {
|
|
276
276
|
const connection = await this.acquire();
|
|
277
277
|
try {
|
|
278
|
-
return await connection.transaction(fn);
|
|
278
|
+
return await connection.transaction(fn, options);
|
|
279
279
|
}
|
|
280
280
|
finally {
|
|
281
281
|
await this.release(connection);
|
|
@@ -361,8 +361,27 @@ export class Pool extends SafeEventEmitter {
|
|
|
361
361
|
// connection that could not be created stays unambiguous.
|
|
362
362
|
this.emit('error', reason);
|
|
363
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* Whether a one-shot query may share a pooled connection with the
|
|
366
|
+
* queries already in flight on it.
|
|
367
|
+
*
|
|
368
|
+
* **Opt-in**, per call or with `pipeline: true` on the pool. It is
|
|
369
|
+
* worth asking for - `max` stops being a ceiling on concurrent
|
|
370
|
+
* queries and becomes one on connections, and a burst of 500 through
|
|
371
|
+
* a pool of 10 measured 12ms against 29ms - but it is not the default,
|
|
372
|
+
* because it moves the query onto a connection other callers are
|
|
373
|
+
* using and session state there stops being the caller's own.
|
|
374
|
+
*
|
|
375
|
+
* The exclusions below are not policy, they are statements that need a
|
|
376
|
+
* connection to themselves for longer than the call takes to resolve:
|
|
377
|
+
* a cursor reads from a portal afterwards, a transaction spans later
|
|
378
|
+
* statements, a COPY holds the connection mid-stream, `autoCommit:
|
|
379
|
+
* false` says a transaction is being managed by hand, and an
|
|
380
|
+
* `AbortSignal` cancels by tearing down whatever the connection is
|
|
381
|
+
* doing - which, shared, is not only this query.
|
|
382
|
+
*/
|
|
364
383
|
_canPipeline(pipeline, sql, autoCommit, signal) {
|
|
365
|
-
return (pipeline === true &&
|
|
384
|
+
return ((pipeline != null ? pipeline : this.config.pipeline === true) &&
|
|
366
385
|
!signal &&
|
|
367
386
|
this._pipelineMaxQueries > 1 &&
|
|
368
387
|
this._pipelineMaxConnections > 0 &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DataTypeOIDs } from '../constants.js';
|
|
1
2
|
import { GlobalTypeMap } from '../data-type-map.js';
|
|
2
3
|
import { Protocol } from '../protocol/protocol.js';
|
|
3
4
|
import { SafeEventEmitter } from '../safe-event-emitter.js';
|
|
@@ -5,6 +6,7 @@ import { withAbortSignal } from '../util/abort-signal.js';
|
|
|
5
6
|
import { getParsers } from '../util/get-parsers.js';
|
|
6
7
|
import { resolveColumnFormats } from '../util/resolve-column-formats.js';
|
|
7
8
|
import { resolveRowType } from '../util/row-decoder.js';
|
|
9
|
+
import { isTransactionCommand, refusesSavepoint, } from '../util/transaction-command.js';
|
|
8
10
|
import { wrapRowDescription } from '../util/wrap-row-description.js';
|
|
9
11
|
import { Cursor } from './cursor.js';
|
|
10
12
|
import { getIntlConnection } from './intl-connection.js';
|
|
@@ -51,6 +53,9 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
51
53
|
}
|
|
52
54
|
async execute(options = {}) {
|
|
53
55
|
const intlCon = getIntlConnection(this.connection);
|
|
56
|
+
// Folded in here rather than deeper: a cursor keeps these options
|
|
57
|
+
// and decodes its own rows with them long after this call is over.
|
|
58
|
+
options = intlCon.withDefaults(options);
|
|
54
59
|
if (options.signal)
|
|
55
60
|
return withAbortSignal(options.signal, () => intlCon.cancel(), () => this._executeWithTransaction(options));
|
|
56
61
|
return this._executeWithTransaction(options);
|
|
@@ -108,6 +113,7 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
108
113
|
throw new Error('executeBatch() cannot return a cursor - a batch runs every set to ' +
|
|
109
114
|
'completion under one Sync, so there is no portal left to fetch from');
|
|
110
115
|
const intlCon = getIntlConnection(this.connection);
|
|
116
|
+
options = intlCon.withDefaults(options);
|
|
111
117
|
if (!paramSets.length)
|
|
112
118
|
return { results: [], totalRowsAffected: 0 };
|
|
113
119
|
if (options.signal)
|
|
@@ -153,7 +159,17 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
153
159
|
*/
|
|
154
160
|
async _withTransaction(options = {}, fn, canInlineSavepoint = false) {
|
|
155
161
|
const intlCon = getIntlConnection(this.connection);
|
|
156
|
-
|
|
162
|
+
// See Connection._query(): a money parameter is written as an int64
|
|
163
|
+
// of minor units, so the server's scale has to be known before the
|
|
164
|
+
// Bind goes out.
|
|
165
|
+
if (this.paramTypes?.includes(DataTypeOIDs.money) ||
|
|
166
|
+
this.paramTypes?.includes(DataTypeOIDs._money) ||
|
|
167
|
+
// And before any of this statement's own money columns are read:
|
|
168
|
+
// a cursor and a batch both decode inside the message loop, where
|
|
169
|
+
// there is no longer anywhere to ask from.
|
|
170
|
+
intlCon.needsMoneyFormat(this._fields, options))
|
|
171
|
+
await intlCon.ensureMoneyFormat();
|
|
172
|
+
const transactionCommand = isTransactionCommand(this.sql);
|
|
157
173
|
let beginFirst = false;
|
|
158
174
|
let commitLast = false;
|
|
159
175
|
const autoCommit = options?.autoCommit;
|
|
@@ -170,7 +186,11 @@ export class PreparedStatement extends SafeEventEmitter {
|
|
|
170
186
|
await intlCon.execute('BEGIN');
|
|
171
187
|
// See IntlConnection.execute()'s own rollbackOnError for why
|
|
172
188
|
// intlCon.inTransaction goes first here but last in the checks below.
|
|
173
|
-
const rollbackOnError =
|
|
189
|
+
const rollbackOnError =
|
|
190
|
+
// See IntlConnection.execute(): `SET TRANSACTION` keeps the
|
|
191
|
+
// implicit BEGIN and loses only the savepoint, which PostgreSQL
|
|
192
|
+
// refuses to let it run inside.
|
|
193
|
+
!refusesSavepoint(this.sql) &&
|
|
174
194
|
intlCon.inTransaction &&
|
|
175
195
|
(options?.rollbackOnError ?? intlCon.config.rollbackOnError ?? true);
|
|
176
196
|
// When `fn` can put the savepoint on the wire itself, SAVEPOINT and
|
package/data-type-map.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { DataType } from './interfaces/data-type.js';
|
|
2
2
|
import type { OID } from './types.js';
|
|
3
3
|
export declare class DataTypeMap {
|
|
4
|
+
protected _inferScalars: DataType[];
|
|
5
|
+
protected _inferArrays: DataType[];
|
|
4
6
|
private _itemsByOID;
|
|
5
7
|
private _items;
|
|
6
8
|
/**
|
|
@@ -17,6 +19,20 @@ export declare class DataTypeMap {
|
|
|
17
19
|
constructor(other?: DataTypeMap);
|
|
18
20
|
get(oid: OID): DataType;
|
|
19
21
|
register(dataTypes: DataType | DataType[]): void;
|
|
22
|
+
/**
|
|
23
|
+
* The two lists determine() actually walks, newest-registered first.
|
|
24
|
+
*
|
|
25
|
+
* A value is either an array or it is not, so half of `_items` can
|
|
26
|
+
* never match it - and the half that can is the smaller one: of 127
|
|
27
|
+
* registered types, a plain number used to be tested against 22 and
|
|
28
|
+
* skipped past 105. Rebuilt on registration, which happens at startup
|
|
29
|
+
* and hardly ever again, so the walk itself reads a list that is
|
|
30
|
+
* already only what it needs.
|
|
31
|
+
*
|
|
32
|
+
* A type that is not inferrable is left out of both: determine() may
|
|
33
|
+
* never pick it, however well its isType matches.
|
|
34
|
+
*/
|
|
35
|
+
protected _rebuildInferenceLists(): void;
|
|
20
36
|
determine(value: any): OID;
|
|
21
37
|
}
|
|
22
38
|
export declare const GlobalTypeMap: DataTypeMap;
|
package/data-type-map.js
CHANGED
|
@@ -21,6 +21,7 @@ import { ArrayJsonPathType, JsonPathType } from './data-types/jsonpath-type.js';
|
|
|
21
21
|
import { ArrayLineType, LineType } from './data-types/line-type.js';
|
|
22
22
|
import { ArrayLsegType, LsegType } from './data-types/lseg-type.js';
|
|
23
23
|
import { ArrayMacaddr8Type, ArrayMacaddrType, Macaddr8Type, MacaddrType, } from './data-types/macaddr-type.js';
|
|
24
|
+
import { ArrayMoneyType, MoneyType } from './data-types/money-type.js';
|
|
24
25
|
import { ArrayNumericType, NumericType } from './data-types/numeric-type.js';
|
|
25
26
|
import { ArrayOidType, OidType } from './data-types/oid-type.js';
|
|
26
27
|
import { ArrayOidVectorType, OidVectorType, } from './data-types/oid-vector-type.js';
|
|
@@ -38,7 +39,10 @@ import { ArrayTsQueryType, ArrayTsVectorType, TsQueryType, TsVectorType, } from
|
|
|
38
39
|
import { ArrayUuidType, UuidType } from './data-types/uuid-type.js';
|
|
39
40
|
import { ArrayVarcharType, VarcharType } from './data-types/varchar-type.js';
|
|
40
41
|
import { ArrayCidType, ArrayXid8Type, ArrayXidType, CidType, Xid8Type, XidType, } from './data-types/xid-type.js';
|
|
42
|
+
import { arrayLeaf } from './util/array-leaf.js';
|
|
41
43
|
export class DataTypeMap {
|
|
44
|
+
_inferScalars = [];
|
|
45
|
+
_inferArrays = [];
|
|
42
46
|
_itemsByOID = {};
|
|
43
47
|
_items = [];
|
|
44
48
|
/**
|
|
@@ -56,6 +60,11 @@ export class DataTypeMap {
|
|
|
56
60
|
if (other instanceof DataTypeMap) {
|
|
57
61
|
this._items = [...other._items];
|
|
58
62
|
this._itemsByOID = { ...other._itemsByOID };
|
|
63
|
+
// Shared, not copied: they are rebuilt wholesale by register(),
|
|
64
|
+
// so a copy that registers nothing never diverges and one that
|
|
65
|
+
// does gets its own pair then.
|
|
66
|
+
this._inferScalars = other._inferScalars;
|
|
67
|
+
this._inferArrays = other._inferArrays;
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
get(oid) {
|
|
@@ -71,6 +80,37 @@ export class DataTypeMap {
|
|
|
71
80
|
else
|
|
72
81
|
this._items.push(t);
|
|
73
82
|
}
|
|
83
|
+
this._rebuildInferenceLists();
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The two lists determine() actually walks, newest-registered first.
|
|
87
|
+
*
|
|
88
|
+
* A value is either an array or it is not, so half of `_items` can
|
|
89
|
+
* never match it - and the half that can is the smaller one: of 127
|
|
90
|
+
* registered types, a plain number used to be tested against 22 and
|
|
91
|
+
* skipped past 105. Rebuilt on registration, which happens at startup
|
|
92
|
+
* and hardly ever again, so the walk itself reads a list that is
|
|
93
|
+
* already only what it needs.
|
|
94
|
+
*
|
|
95
|
+
* A type that is not inferrable is left out of both: determine() may
|
|
96
|
+
* never pick it, however well its isType matches.
|
|
97
|
+
*/
|
|
98
|
+
_rebuildInferenceLists() {
|
|
99
|
+
const scalars = [];
|
|
100
|
+
const arrays = [];
|
|
101
|
+
let i;
|
|
102
|
+
let t;
|
|
103
|
+
// Built back to front, so index 0 is the newest registration and the
|
|
104
|
+
// walk runs forward - which is the direction a JS array is fastest
|
|
105
|
+
// to read and the one that needs no length arithmetic per step.
|
|
106
|
+
for (i = this._items.length - 1; i >= 0; i--) {
|
|
107
|
+
t = this._items[i];
|
|
108
|
+
if (t.inferrable === false)
|
|
109
|
+
continue;
|
|
110
|
+
(t.elementsOID ? arrays : scalars).push(t);
|
|
111
|
+
}
|
|
112
|
+
this._inferScalars = scalars;
|
|
113
|
+
this._inferArrays = arrays;
|
|
74
114
|
}
|
|
75
115
|
determine(value) {
|
|
76
116
|
if (value == null)
|
|
@@ -94,21 +134,22 @@ export class DataTypeMap {
|
|
|
94
134
|
'it at the call site (`new BindParam(oid, value)`)');
|
|
95
135
|
}
|
|
96
136
|
}
|
|
137
|
+
// An array is typed from the first value inside it that is actually
|
|
138
|
+
// a value: `value[0]` answers `_int2vector` for [[1, 2], [3, 4]],
|
|
139
|
+
// because the first element is itself an array and a vector is the
|
|
140
|
+
// one registered type an array of numbers matches, and answers
|
|
141
|
+
// nothing at all for [null, 2, 3].
|
|
97
142
|
const valueIsArray = Array.isArray(value);
|
|
143
|
+
const candidates = valueIsArray ? this._inferArrays : this._inferScalars;
|
|
144
|
+
const v = valueIsArray ? arrayLeaf(value) : value;
|
|
145
|
+
// Newest-registered first, so a later registration of the same OID
|
|
146
|
+
// wins - see _rebuildInferenceLists() for how the order is kept.
|
|
147
|
+
const l = candidates.length;
|
|
98
148
|
let i;
|
|
99
149
|
let t;
|
|
100
|
-
for (i =
|
|
101
|
-
t =
|
|
102
|
-
|
|
103
|
-
// same OID wins - and a type marked `inferrable: false` is never
|
|
104
|
-
// picked here at all, however well `isType` matches.
|
|
105
|
-
if (t.inferrable === false)
|
|
106
|
-
continue;
|
|
107
|
-
if (valueIsArray) {
|
|
108
|
-
if (t.elementsOID && t.isType(value[0]))
|
|
109
|
-
return t.oid;
|
|
110
|
-
}
|
|
111
|
-
else if (!t.elementsOID && t.isType(value))
|
|
150
|
+
for (i = 0; i < l; i++) {
|
|
151
|
+
t = candidates[i];
|
|
152
|
+
if (t.isType(v))
|
|
112
153
|
return t.oid;
|
|
113
154
|
}
|
|
114
155
|
return DataTypeOIDs.unknown;
|
|
@@ -121,6 +162,9 @@ GlobalTypeMap.register([JsonbType, ArrayJsonbType]);
|
|
|
121
162
|
GlobalTypeMap.register([JsonType, ArrayJsonType]);
|
|
122
163
|
GlobalTypeMap.register([BoolType, ArrayBoolType]);
|
|
123
164
|
GlobalTypeMap.register([NumericType, ArrayNumericType]);
|
|
165
|
+
// Registered after numeric and not inferrable: a JavaScript number is
|
|
166
|
+
// never money by shape, and the type is reached by naming it.
|
|
167
|
+
GlobalTypeMap.register([MoneyType, ArrayMoneyType]);
|
|
124
168
|
GlobalTypeMap.register([Float4Type, ArrayFloat4Type]);
|
|
125
169
|
GlobalTypeMap.register([Float8Type, ArrayFloat8Type]);
|
|
126
170
|
GlobalTypeMap.register([Int2Type, ArrayInt2Type]);
|
|
@@ -8,13 +8,16 @@ export const CircleType = {
|
|
|
8
8
|
name: 'circle',
|
|
9
9
|
oid: DataTypeOIDs.circle,
|
|
10
10
|
jsType: 'Circle',
|
|
11
|
+
// isType() accepts a plain object as well as a Circle, and that object
|
|
12
|
+
// may spell the radius either way - hence Circle.radiusOf() rather
|
|
13
|
+
// than the property.
|
|
11
14
|
encodeText(v) {
|
|
12
|
-
return `<(${v.x},${v.y}),${v
|
|
15
|
+
return `<(${v.x},${v.y}),${Circle.radiusOf(v)}>`;
|
|
13
16
|
},
|
|
14
17
|
encodeBinary(buf, v) {
|
|
15
18
|
buf.writeDoubleBE(v.x);
|
|
16
19
|
buf.writeDoubleBE(v.y);
|
|
17
|
-
buf.writeDoubleBE(v
|
|
20
|
+
buf.writeDoubleBE(Circle.radiusOf(v));
|
|
18
21
|
},
|
|
19
22
|
decodeBinary(v, offset = 0) {
|
|
20
23
|
return new Circle(v.readDoubleBE(offset), v.readDoubleBE(offset + 8), v.readDoubleBE(offset + 16));
|
|
@@ -5,19 +5,46 @@ export declare class Point {
|
|
|
5
5
|
constructor(x?: number, y?: number);
|
|
6
6
|
/** As PostgreSQL prints it, so it casts back through `::point`. */
|
|
7
7
|
toString(): string;
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
10
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
11
|
+
* client decoded can be handed straight to one.
|
|
12
|
+
*/
|
|
13
|
+
toPostgres(): string;
|
|
9
14
|
static isPointLike(v: any): boolean;
|
|
10
15
|
}
|
|
11
16
|
/** A `circle`: a centre and a radius. */
|
|
12
17
|
export declare class Circle {
|
|
13
18
|
x: number;
|
|
14
19
|
y: number;
|
|
15
|
-
|
|
16
|
-
constructor(x?: number, y?: number,
|
|
20
|
+
radius: number;
|
|
21
|
+
constructor(x?: number, y?: number, radius?: number);
|
|
22
|
+
/**
|
|
23
|
+
* The radius under the name this client used up to 3.9. `pg` spells it
|
|
24
|
+
* `radius`, and a value decoded here should be usable wherever one of
|
|
25
|
+
* its own is, so `radius` is what the property is now - but `r` was a
|
|
26
|
+
* released name, so it stays as an accessor onto the same number
|
|
27
|
+
* rather than silently reading back undefined.
|
|
28
|
+
*
|
|
29
|
+
* @deprecated use `radius`
|
|
30
|
+
*/
|
|
31
|
+
get r(): number;
|
|
32
|
+
set r(value: number);
|
|
17
33
|
/** As PostgreSQL prints it, so it casts back through `::circle`. */
|
|
18
34
|
toString(): string;
|
|
19
|
-
|
|
35
|
+
/**
|
|
36
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
37
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
38
|
+
* client decoded can be handed straight to one.
|
|
39
|
+
*/
|
|
40
|
+
toPostgres(): string;
|
|
20
41
|
static isCircleLike(v: any): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The radius of anything isCircleLike() accepts: a Circle, the plain
|
|
44
|
+
* `{x, y, radius}` object `pg` hands back, or the `{x, y, r}` that was
|
|
45
|
+
* this client's own shape before the classes existed.
|
|
46
|
+
*/
|
|
47
|
+
static radiusOf(v: any): number;
|
|
21
48
|
}
|
|
22
49
|
/**
|
|
23
50
|
* Two corners, which is how both `box` and `lseg` are carried - and why
|
|
@@ -32,7 +59,12 @@ declare abstract class TwoPoints {
|
|
|
32
59
|
x2: number;
|
|
33
60
|
y2: number;
|
|
34
61
|
constructor(x1?: number, y1?: number, x2?: number, y2?: number);
|
|
35
|
-
|
|
62
|
+
/**
|
|
63
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
64
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
65
|
+
* client decoded can be handed straight to one.
|
|
66
|
+
*/
|
|
67
|
+
toPostgres(): string;
|
|
36
68
|
static isTwoPointsLike(v: any): boolean;
|
|
37
69
|
}
|
|
38
70
|
/** A `box`: a rectangle given by two opposite corners. */
|
|
@@ -61,7 +93,12 @@ export declare class Line {
|
|
|
61
93
|
constructor(a?: number, b?: number, c?: number);
|
|
62
94
|
/** As PostgreSQL prints it, so it casts back through `::line`. */
|
|
63
95
|
toString(): string;
|
|
64
|
-
|
|
96
|
+
/**
|
|
97
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
98
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
99
|
+
* client decoded can be handed straight to one.
|
|
100
|
+
*/
|
|
101
|
+
toPostgres(): string;
|
|
65
102
|
static isLineLike(v: any): boolean;
|
|
66
103
|
}
|
|
67
104
|
/**
|
|
@@ -77,7 +114,12 @@ declare abstract class PointList {
|
|
|
77
114
|
x: number;
|
|
78
115
|
y: number;
|
|
79
116
|
})[]);
|
|
80
|
-
|
|
117
|
+
/**
|
|
118
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
119
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
120
|
+
* client decoded can be handed straight to one.
|
|
121
|
+
*/
|
|
122
|
+
toPostgres(): string;
|
|
81
123
|
protected join(): string;
|
|
82
124
|
}
|
|
83
125
|
/**
|
|
@@ -27,7 +27,12 @@ export class Point {
|
|
|
27
27
|
toString() {
|
|
28
28
|
return `(${this.x},${this.y})`;
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
/**
|
|
31
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
32
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
33
|
+
* client decoded can be handed straight to one.
|
|
34
|
+
*/
|
|
35
|
+
toPostgres() {
|
|
31
36
|
return this.toString();
|
|
32
37
|
}
|
|
33
38
|
/* c8 ignore next 3 */
|
|
@@ -42,17 +47,37 @@ export class Point {
|
|
|
42
47
|
export class Circle {
|
|
43
48
|
x;
|
|
44
49
|
y;
|
|
45
|
-
|
|
46
|
-
constructor(x = 0, y = 0,
|
|
50
|
+
radius;
|
|
51
|
+
constructor(x = 0, y = 0, radius = 0) {
|
|
47
52
|
this.x = x;
|
|
48
53
|
this.y = y;
|
|
49
|
-
this.
|
|
54
|
+
this.radius = radius;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The radius under the name this client used up to 3.9. `pg` spells it
|
|
58
|
+
* `radius`, and a value decoded here should be usable wherever one of
|
|
59
|
+
* its own is, so `radius` is what the property is now - but `r` was a
|
|
60
|
+
* released name, so it stays as an accessor onto the same number
|
|
61
|
+
* rather than silently reading back undefined.
|
|
62
|
+
*
|
|
63
|
+
* @deprecated use `radius`
|
|
64
|
+
*/
|
|
65
|
+
get r() {
|
|
66
|
+
return this.radius;
|
|
67
|
+
}
|
|
68
|
+
set r(value) {
|
|
69
|
+
this.radius = value;
|
|
50
70
|
}
|
|
51
71
|
/** As PostgreSQL prints it, so it casts back through `::circle`. */
|
|
52
72
|
toString() {
|
|
53
|
-
return `<(${this.x},${this.y}),${this.
|
|
54
|
-
}
|
|
55
|
-
|
|
73
|
+
return `<(${this.x},${this.y}),${this.radius}>`;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
77
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
78
|
+
* client decoded can be handed straight to one.
|
|
79
|
+
*/
|
|
80
|
+
toPostgres() {
|
|
56
81
|
return this.toString();
|
|
57
82
|
}
|
|
58
83
|
static isCircleLike(v) {
|
|
@@ -60,7 +85,15 @@ export class Circle {
|
|
|
60
85
|
Object.keys(v).length === 3 &&
|
|
61
86
|
isNum(v.x) &&
|
|
62
87
|
isNum(v.y) &&
|
|
63
|
-
isNum(v.r));
|
|
88
|
+
(isNum(v.radius) || isNum(v.r)));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The radius of anything isCircleLike() accepts: a Circle, the plain
|
|
92
|
+
* `{x, y, radius}` object `pg` hands back, or the `{x, y, r}` that was
|
|
93
|
+
* this client's own shape before the classes existed.
|
|
94
|
+
*/
|
|
95
|
+
static radiusOf(v) {
|
|
96
|
+
return v.radius ?? v.r;
|
|
64
97
|
}
|
|
65
98
|
}
|
|
66
99
|
/**
|
|
@@ -81,7 +114,12 @@ class TwoPoints {
|
|
|
81
114
|
this.x2 = x2;
|
|
82
115
|
this.y2 = y2;
|
|
83
116
|
}
|
|
84
|
-
|
|
117
|
+
/**
|
|
118
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
119
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
120
|
+
* client decoded can be handed straight to one.
|
|
121
|
+
*/
|
|
122
|
+
toPostgres() {
|
|
85
123
|
return this.toString();
|
|
86
124
|
}
|
|
87
125
|
static isTwoPointsLike(v) {
|
|
@@ -129,7 +167,12 @@ export class Line {
|
|
|
129
167
|
toString() {
|
|
130
168
|
return `{${this.a},${this.b},${this.c}}`;
|
|
131
169
|
}
|
|
132
|
-
|
|
170
|
+
/**
|
|
171
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
172
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
173
|
+
* client decoded can be handed straight to one.
|
|
174
|
+
*/
|
|
175
|
+
toPostgres() {
|
|
133
176
|
return this.toString();
|
|
134
177
|
}
|
|
135
178
|
static isLineLike(v) {
|
|
@@ -152,7 +195,12 @@ class PointList {
|
|
|
152
195
|
constructor(points = []) {
|
|
153
196
|
this.points = points.map(p => p instanceof Point ? p : new Point(p.x, p.y));
|
|
154
197
|
}
|
|
155
|
-
|
|
198
|
+
/**
|
|
199
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
200
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
201
|
+
* client decoded can be handed straight to one.
|
|
202
|
+
*/
|
|
203
|
+
toPostgres() {
|
|
156
204
|
return this.toString();
|
|
157
205
|
}
|
|
158
206
|
join() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** The fields an Interval is built from
|
|
1
|
+
/** The fields an Interval is built from; it keeps the ones that have a value. */
|
|
2
2
|
export interface IntervalFields {
|
|
3
3
|
years?: number;
|
|
4
4
|
months?: number;
|
|
@@ -18,20 +18,29 @@ export interface IntervalFields {
|
|
|
18
18
|
* zone, can add one to a timestamp. Anything here that answered "how many
|
|
19
19
|
* milliseconds is this" would have to invent those lengths.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
21
|
+
* It carries the fields that have a value and no others, which is what
|
|
22
|
+
* the wire format carries too - three quantities, and a zero among them
|
|
23
|
+
* is not a field:
|
|
22
24
|
*
|
|
23
25
|
* ```ts
|
|
24
26
|
* const iv = new Interval({ days: 1, hours: 2 });
|
|
25
|
-
* iv
|
|
27
|
+
* Object.keys(iv); // ['days', 'hours']
|
|
28
|
+
* iv.minutes; // undefined
|
|
26
29
|
* String(iv); // '1 day 02:00:00'
|
|
27
30
|
* iv.toISOString(); // 'P0Y0M1DT2H0M0S'
|
|
28
31
|
* ```
|
|
29
32
|
*
|
|
30
|
-
* The field names are `pg`'s (`postgres-interval`), so code
|
|
31
|
-
* reads the same values from the same places
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
33
|
+
* The field names and the shape are `pg`'s (`postgres-interval`), so code
|
|
34
|
+
* ported from it reads the same values from the same places and a
|
|
35
|
+
* `JSON.stringify` of a row says the same thing. The difference is that
|
|
36
|
+
* this has a `toString()` - `pg`'s object gives `[object Object]` in a log
|
|
37
|
+
* line - and a `toPostgres()`, so the value can be sent back.
|
|
38
|
+
*
|
|
39
|
+
* The fields are optional, so `iv.hours + 1` does not compile without
|
|
40
|
+
* saying what an absent one means (`(iv.hours ?? 0) + 1`). That is the
|
|
41
|
+
* point: which fields a value has depends on the value, not on the type,
|
|
42
|
+
* and the older shape - every field present and 0 - hid that behind
|
|
43
|
+
* numbers nobody wrote.
|
|
35
44
|
*
|
|
36
45
|
* `milliseconds` carries the sub-second part and can be fractional, since
|
|
37
46
|
* PostgreSQL stores microseconds: `interval '0.000001 seconds'` is
|
|
@@ -40,17 +49,27 @@ export interface IntervalFields {
|
|
|
40
49
|
* A negative interval carries the sign on each field that has one, the way
|
|
41
50
|
* the server prints it: `interval '-1 day -2 hours'` is
|
|
42
51
|
* `{ days: -1, hours: -2 }`.
|
|
52
|
+
*
|
|
53
|
+
* `toPostgres()` is `pg`'s convention for "write yourself back", so a
|
|
54
|
+
* value read here can be passed to any encoder that follows it - this
|
|
55
|
+
* client's own parameter path never needed it, since it knows the class.
|
|
43
56
|
*/
|
|
44
57
|
export declare class Interval implements IntervalFields {
|
|
45
|
-
years
|
|
46
|
-
months
|
|
47
|
-
days
|
|
48
|
-
hours
|
|
49
|
-
minutes
|
|
58
|
+
years?: number;
|
|
59
|
+
months?: number;
|
|
60
|
+
days?: number;
|
|
61
|
+
hours?: number;
|
|
62
|
+
minutes?: number;
|
|
50
63
|
/** Whole seconds; the sub-second part is in `milliseconds`. */
|
|
51
|
-
seconds
|
|
64
|
+
seconds?: number;
|
|
52
65
|
/** The sub-second part, fractional down to a microsecond. */
|
|
53
|
-
milliseconds
|
|
66
|
+
milliseconds?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Keeps the fields that have a value. A zero is not one: it is what
|
|
69
|
+
* every field of every interval would otherwise be filled with, and
|
|
70
|
+
* `{ days: 1 }` says what `interval '1 day'` is far better than the
|
|
71
|
+
* same thing plus six zeroes nobody wrote.
|
|
72
|
+
*/
|
|
54
73
|
constructor(fields?: IntervalFields);
|
|
55
74
|
/**
|
|
56
75
|
* Builds one from the three quantities the wire format carries: a signed
|
|
@@ -69,5 +88,10 @@ export declare class Interval implements IntervalFields {
|
|
|
69
88
|
toString(): string;
|
|
70
89
|
/** The interval as an ISO 8601 duration. */
|
|
71
90
|
toISOString(): string;
|
|
72
|
-
|
|
91
|
+
/**
|
|
92
|
+
* The literal PostgreSQL reads back, for an encoder that asks the value
|
|
93
|
+
* how to write itself - `pg`'s convention, and the reason a value this
|
|
94
|
+
* client decoded can be handed straight to one.
|
|
95
|
+
*/
|
|
96
|
+
toPostgres(): string;
|
|
73
97
|
}
|