@molecule/api-database-duckdb 0.0.0-stage → 1.1.1
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/LICENSE +202 -0
- package/README.md +772 -2
- package/dist/browser-guard.d.ts +2 -0
- package/dist/browser-guard.d.ts.map +1 -0
- package/dist/browser-guard.js +19 -0
- package/dist/browser-guard.js.map +1 -0
- package/dist/capabilities.d.ts +30 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +48 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/index.d.ts +115 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +169 -0
- package/dist/index.js.map +1 -0
- package/dist/instances.d.ts +73 -0
- package/dist/instances.d.ts.map +1 -0
- package/dist/instances.js +117 -0
- package/dist/instances.js.map +1 -0
- package/dist/lifecycle.d.ts +22 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +45 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/migrator.d.ts +74 -0
- package/dist/migrator.d.ts.map +1 -0
- package/dist/migrator.js +172 -0
- package/dist/migrator.js.map +1 -0
- package/dist/pool.d.ts +40 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +273 -0
- package/dist/pool.js.map +1 -0
- package/dist/queue.d.ts +48 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +98 -0
- package/dist/queue.js.map +1 -0
- package/dist/secrets.d.ts +16 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +25 -0
- package/dist/secrets.js.map +1 -0
- package/dist/sql-dialect.d.ts +92 -0
- package/dist/sql-dialect.d.ts.map +1 -0
- package/dist/sql-dialect.js +309 -0
- package/dist/sql-dialect.js.map +1 -0
- package/dist/store.d.ts +18 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +335 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/utilities.d.ts +119 -0
- package/dist/utilities.d.ts.map +1 -0
- package/dist/utilities.js +246 -0
- package/dist/utilities.js.map +1 -0
- package/package.json +87 -4
package/dist/queue.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIFO lock over the pool's single DuckDB connection.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Serializes every use of ONE DuckDB connection.
|
|
8
|
+
*
|
|
9
|
+
* All connections from one instance share one database, and DuckDB detects
|
|
10
|
+
* conflicting writes across connections of one instance as transaction
|
|
11
|
+
* conflicts — an interactive `BEGIN` … `COMMIT` interleaved with writes from
|
|
12
|
+
* another connection fails the transaction. So this pool uses ONE connection
|
|
13
|
+
* (the sqlite bond's model): plain `query()` calls hold it for one statement;
|
|
14
|
+
* `connect()` and `transaction()` hold it until they are released, so a
|
|
15
|
+
* transaction's `BEGIN` → … → `COMMIT`/`ROLLBACK` runs alone.
|
|
16
|
+
*
|
|
17
|
+
* Waiting is bounded: a waiter that cannot get the lock within its timeout is
|
|
18
|
+
* removed from the queue and rejected with an error naming the likely cause
|
|
19
|
+
* (code holding a connection while calling the pool), instead of hanging forever.
|
|
20
|
+
*/
|
|
21
|
+
export declare class ConnectionLock {
|
|
22
|
+
private locked;
|
|
23
|
+
private holder;
|
|
24
|
+
private waiters;
|
|
25
|
+
/**
|
|
26
|
+
* Number of callers currently waiting for the lock.
|
|
27
|
+
*
|
|
28
|
+
* @returns The queue length.
|
|
29
|
+
*/
|
|
30
|
+
get waiting(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the lock is currently held.
|
|
33
|
+
*
|
|
34
|
+
* @returns `true` when held.
|
|
35
|
+
*/
|
|
36
|
+
get isLocked(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Waits for the lock in FIFO order. The returned release function MUST be
|
|
39
|
+
* called exactly once; extra calls are ignored.
|
|
40
|
+
*
|
|
41
|
+
* @param purpose - What the caller will do with the lock (`'query'`,
|
|
42
|
+
* `'connect()'`, `'transaction()'`), used in the timeout message.
|
|
43
|
+
* @param timeoutMillis - Maximum wait; `0` or less waits forever.
|
|
44
|
+
* @returns A release function.
|
|
45
|
+
*/
|
|
46
|
+
acquire(purpose: string, timeoutMillis: number): Promise<() => void>;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,OAAO,CAAmC;IAElD;;;;OAIG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;CAiDrE"}
|
package/dist/queue.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FIFO lock over the pool's single DuckDB connection.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Serializes every use of ONE DuckDB connection.
|
|
8
|
+
*
|
|
9
|
+
* All connections from one instance share one database, and DuckDB detects
|
|
10
|
+
* conflicting writes across connections of one instance as transaction
|
|
11
|
+
* conflicts — an interactive `BEGIN` … `COMMIT` interleaved with writes from
|
|
12
|
+
* another connection fails the transaction. So this pool uses ONE connection
|
|
13
|
+
* (the sqlite bond's model): plain `query()` calls hold it for one statement;
|
|
14
|
+
* `connect()` and `transaction()` hold it until they are released, so a
|
|
15
|
+
* transaction's `BEGIN` → … → `COMMIT`/`ROLLBACK` runs alone.
|
|
16
|
+
*
|
|
17
|
+
* Waiting is bounded: a waiter that cannot get the lock within its timeout is
|
|
18
|
+
* removed from the queue and rejected with an error naming the likely cause
|
|
19
|
+
* (code holding a connection while calling the pool), instead of hanging forever.
|
|
20
|
+
*/
|
|
21
|
+
export class ConnectionLock {
|
|
22
|
+
locked = false;
|
|
23
|
+
holder = null;
|
|
24
|
+
waiters = [];
|
|
25
|
+
/**
|
|
26
|
+
* Number of callers currently waiting for the lock.
|
|
27
|
+
*
|
|
28
|
+
* @returns The queue length.
|
|
29
|
+
*/
|
|
30
|
+
get waiting() {
|
|
31
|
+
return this.waiters.length;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether the lock is currently held.
|
|
35
|
+
*
|
|
36
|
+
* @returns `true` when held.
|
|
37
|
+
*/
|
|
38
|
+
get isLocked() {
|
|
39
|
+
return this.locked;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Waits for the lock in FIFO order. The returned release function MUST be
|
|
43
|
+
* called exactly once; extra calls are ignored.
|
|
44
|
+
*
|
|
45
|
+
* @param purpose - What the caller will do with the lock (`'query'`,
|
|
46
|
+
* `'connect()'`, `'transaction()'`), used in the timeout message.
|
|
47
|
+
* @param timeoutMillis - Maximum wait; `0` or less waits forever.
|
|
48
|
+
* @returns A release function.
|
|
49
|
+
*/
|
|
50
|
+
acquire(purpose, timeoutMillis) {
|
|
51
|
+
let released = false;
|
|
52
|
+
const release = () => {
|
|
53
|
+
if (released)
|
|
54
|
+
return;
|
|
55
|
+
released = true;
|
|
56
|
+
this.holder = null;
|
|
57
|
+
const next = this.waiters.shift();
|
|
58
|
+
if (next) {
|
|
59
|
+
next.grant();
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
this.locked = false;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
if (!this.locked) {
|
|
66
|
+
this.locked = true;
|
|
67
|
+
this.holder = purpose;
|
|
68
|
+
return Promise.resolve(release);
|
|
69
|
+
}
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
let timer;
|
|
72
|
+
const waiter = {
|
|
73
|
+
grant: () => {
|
|
74
|
+
if (timer !== undefined)
|
|
75
|
+
clearTimeout(timer);
|
|
76
|
+
this.locked = true;
|
|
77
|
+
this.holder = purpose;
|
|
78
|
+
resolve(release);
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
this.waiters.push(waiter);
|
|
82
|
+
if (timeoutMillis > 0) {
|
|
83
|
+
timer = setTimeout(() => {
|
|
84
|
+
const index = this.waiters.indexOf(waiter);
|
|
85
|
+
if (index === -1)
|
|
86
|
+
return;
|
|
87
|
+
this.waiters.splice(index, 1);
|
|
88
|
+
reject(new Error(`DuckDB: a ${purpose} waited ${timeoutMillis} ms for the pool's single ` +
|
|
89
|
+
`connection, which is held by an open ${this.holder ?? 'operation'}. This pool ` +
|
|
90
|
+
`serializes everything on one connection: release() a connect()ed connection and ` +
|
|
91
|
+
`commit()/rollback() a transaction before calling the pool or the store again, and ` +
|
|
92
|
+
`run every statement of a transaction on its own query().`));
|
|
93
|
+
}, timeoutMillis);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,cAAc;IACjB,MAAM,GAAG,KAAK,CAAA;IACd,MAAM,GAAkB,IAAI,CAAA;IAC5B,OAAO,GAAiC,EAAE,CAAA;IAElD;;;;OAIG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAA;IAC5B,CAAC;IAED;;;;OAIG;IACH,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAA;IACpB,CAAC;IAED;;;;;;;;OAQG;IACH,OAAO,CAAC,OAAe,EAAE,aAAqB;QAC5C,IAAI,QAAQ,GAAG,KAAK,CAAA;QACpB,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,IAAI,QAAQ;gBAAE,OAAM;YACpB,QAAQ,GAAG,IAAI,CAAA;YACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;YAClB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;YACjC,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,KAAK,EAAE,CAAA;YACd,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;YACrB,CAAC;QACH,CAAC,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;YAClB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAA;YACrB,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACjC,CAAC;QAED,OAAO,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACjD,IAAI,KAAgD,CAAA;YACpD,MAAM,MAAM,GAAG;gBACb,KAAK,EAAE,GAAS,EAAE;oBAChB,IAAI,KAAK,KAAK,SAAS;wBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;oBAC5C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;oBAClB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAA;oBACrB,OAAO,CAAC,OAAO,CAAC,CAAA;gBAClB,CAAC;aACF,CAAA;YACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACzB,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;gBACtB,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;oBACtB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;oBAC1C,IAAI,KAAK,KAAK,CAAC,CAAC;wBAAE,OAAM;oBACxB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;oBAC7B,MAAM,CACJ,IAAI,KAAK,CACP,aAAa,OAAO,WAAW,aAAa,4BAA4B;wBACtE,wCAAwC,IAAI,CAAC,MAAM,IAAI,WAAW,cAAc;wBAChF,kFAAkF;wBAClF,oFAAoF;wBACpF,0DAA0D,CAC7D,CACF,CAAA;gBACH,CAAC,EAAE,aAAa,CAAC,CAAA;YACnB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DuckDB secret definitions — self-registered at import time so the
|
|
3
|
+
* runtime secrets registry (`@molecule/api-secrets`) can drive boot-time
|
|
4
|
+
* configuration reports and actionable "not configured" errors.
|
|
5
|
+
*
|
|
6
|
+
* Content is derived MECHANICALLY from this package's mlcl registry secrets
|
|
7
|
+
* entry (label/instructions/setupUrl/example) via the fleet formula, so
|
|
8
|
+
* packages sharing a key register byte-identical definitions and
|
|
9
|
+
* registration order never matters.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { SecretDefinition } from '@molecule/api-secrets';
|
|
14
|
+
/** Secret definitions required by the DuckDB database bond. */
|
|
15
|
+
export declare const databaseDuckdbSecretDefinitions: SecretDefinition[];
|
|
16
|
+
//# sourceMappingURL=secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAG7D,+DAA+D;AAC/D,eAAO,MAAM,+BAA+B,EAAE,gBAAgB,EAS7D,CAAA"}
|
package/dist/secrets.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DuckDB secret definitions — self-registered at import time so the
|
|
3
|
+
* runtime secrets registry (`@molecule/api-secrets`) can drive boot-time
|
|
4
|
+
* configuration reports and actionable "not configured" errors.
|
|
5
|
+
*
|
|
6
|
+
* Content is derived MECHANICALLY from this package's mlcl registry secrets
|
|
7
|
+
* entry (label/instructions/setupUrl/example) via the fleet formula, so
|
|
8
|
+
* packages sharing a key register byte-identical definitions and
|
|
9
|
+
* registration order never matters.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import { registerSecrets } from '@molecule/api-secrets';
|
|
14
|
+
/** Secret definitions required by the DuckDB database bond. */
|
|
15
|
+
export const databaseDuckdbSecretDefinitions = [
|
|
16
|
+
{
|
|
17
|
+
key: 'DUCKDB_PATH',
|
|
18
|
+
description: 'DuckDB database path — Filesystem path of the DuckDB database file (created on first run), or :memory:.',
|
|
19
|
+
required: false,
|
|
20
|
+
example: './data/app.duckdb',
|
|
21
|
+
default: './data/app.duckdb',
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
registerSecrets(databaseDuckdbSecretDefinitions);
|
|
25
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAEvD,+DAA+D;AAC/D,MAAM,CAAC,MAAM,+BAA+B,GAAuB;IACjE;QACE,GAAG,EAAE,aAAa;QAClB,WAAW,EACT,yGAAyG;QAC3G,QAAQ,EAAE,KAAK;QACf,OAAO,EAAE,mBAAmB;QAC5B,OAAO,EAAE,mBAAmB;KAC7B;CACF,CAAA;AAED,eAAe,CAAC,+BAA+B,CAAC,CAAA"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The slice of SQL lexing and DDL parsing this bond needs to translate, or
|
|
3
|
+
* refuse, PostgreSQL-dialect migrations without changing their behaviour.
|
|
4
|
+
*
|
|
5
|
+
* It lives in the bond because it IS the bond's translation responsibility: a
|
|
6
|
+
* provider that cannot accept a construct as written has to read the statement
|
|
7
|
+
* well enough to rewrite it faithfully or to refuse it. It is deliberately not a
|
|
8
|
+
* general requirement analyser — that decision (which constructs a selection
|
|
9
|
+
* needs, and whether the selected provider can honour them) is compilation work
|
|
10
|
+
* and lives in `mlcl/src/lib/sql-requirements.ts`, shared by every harness.
|
|
11
|
+
*
|
|
12
|
+
* The rules preserved from that shared analysis: a semicolon ends a statement
|
|
13
|
+
* only outside a string literal, a quoted identifier, a dollar-quoted body and a
|
|
14
|
+
* comment; keywords are matched against a mask that blanks comment and literal
|
|
15
|
+
* CONTENT while keeping every offset, so slicing the mask addresses the same
|
|
16
|
+
* characters in the original; and a construct written inside a comment or a
|
|
17
|
+
* string is never mistaken for a real one.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/** One SQL statement located in a migration file. */
|
|
22
|
+
export interface SqlStatement {
|
|
23
|
+
/** Statement text, including its trailing semicolon when it has one. */
|
|
24
|
+
text: string;
|
|
25
|
+
/** 0-based offset of the statement's first character in the source. */
|
|
26
|
+
start: number;
|
|
27
|
+
/** 0-based offset just past the statement's last character. */
|
|
28
|
+
end: number;
|
|
29
|
+
}
|
|
30
|
+
/** A `CREATE INDEX` statement split into the parts the translator rewrites. */
|
|
31
|
+
export interface ParsedCreateIndex {
|
|
32
|
+
/** Whether the statement declares a UNIQUE index. */
|
|
33
|
+
unique: boolean;
|
|
34
|
+
/** Statement text through the opening parenthesis, with any `USING <method>` removed. */
|
|
35
|
+
prefix: string;
|
|
36
|
+
/** The original column-list text between the outer parentheses. */
|
|
37
|
+
columns: string;
|
|
38
|
+
/** The original text after the closing parenthesis (contains the `WHERE` clause when partial). */
|
|
39
|
+
afterClose: string;
|
|
40
|
+
/** The predicate after `WHERE`, or `null` for a non-partial index. */
|
|
41
|
+
predicate: string | null;
|
|
42
|
+
/** The original text after the predicate (normally `;`), or `null` for a non-partial index. */
|
|
43
|
+
afterPredicate: string | null;
|
|
44
|
+
/** Any index options between the closing parenthesis and `WHERE` (`WITH`, `INCLUDE`), trimmed. */
|
|
45
|
+
optionsBeforeWhere: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Split a migration file into statements, keeping each statement's exact text
|
|
49
|
+
* and offsets.
|
|
50
|
+
*
|
|
51
|
+
* A semicolon ends a statement only outside a single-quoted string, a
|
|
52
|
+
* double-quoted identifier, a dollar-quoted body, a line comment and a block
|
|
53
|
+
* comment. The returned text includes the trailing semicolon; concatenating
|
|
54
|
+
* every `text` reproduces the input byte for byte.
|
|
55
|
+
*
|
|
56
|
+
* @param sql - The migration file's SQL.
|
|
57
|
+
* @returns The statements in source order.
|
|
58
|
+
*/
|
|
59
|
+
export declare const splitSqlStatements: (sql: string) => SqlStatement[];
|
|
60
|
+
/**
|
|
61
|
+
* Split a column list at its top-level commas.
|
|
62
|
+
*
|
|
63
|
+
* A comma inside a function call (`lower(a, b)`) or a string literal does not
|
|
64
|
+
* split — the same masking the statement splitter uses keeps offsets aligned.
|
|
65
|
+
*
|
|
66
|
+
* @param columns - Text between a `CREATE INDEX` statement's outer parentheses.
|
|
67
|
+
* @returns Each column/expression text, trimmed.
|
|
68
|
+
*/
|
|
69
|
+
export declare const splitSqlColumns: (columns: string) => string[];
|
|
70
|
+
/**
|
|
71
|
+
* Parse a `CREATE [UNIQUE] INDEX` statement into the parts this bond rewrites.
|
|
72
|
+
*
|
|
73
|
+
* Returns `null` for any other statement. The returned slices are taken from the
|
|
74
|
+
* ORIGINAL text, so a translator can rebuild the statement without losing the
|
|
75
|
+
* author's casing or quoting.
|
|
76
|
+
*
|
|
77
|
+
* @param statement - One statement from {@link splitSqlStatements}.
|
|
78
|
+
* @returns The parsed index, or `null` when the statement is not a `CREATE INDEX`.
|
|
79
|
+
*/
|
|
80
|
+
export declare const parseCreateIndexStatement: (statement: string) => ParsedCreateIndex | null;
|
|
81
|
+
/**
|
|
82
|
+
* Every unsupported foreign-key referential action in one statement, in source
|
|
83
|
+
* order and normalized (`ON DELETE CASCADE`).
|
|
84
|
+
*
|
|
85
|
+
* A construct inside a comment or a string literal is ignored: those carry no
|
|
86
|
+
* constraint. `NO ACTION` and `RESTRICT` do not match — DuckDB accepts them.
|
|
87
|
+
*
|
|
88
|
+
* @param statement - One statement from {@link splitSqlStatements}.
|
|
89
|
+
* @returns The normalized actions, e.g. `['ON DELETE CASCADE']`.
|
|
90
|
+
*/
|
|
91
|
+
export declare const referentialActionsIn: (statement: string) => string[];
|
|
92
|
+
//# sourceMappingURL=sql-dialect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-dialect.d.ts","sourceRoot":"","sources":["../src/sql-dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,qDAAqD;AACrD,MAAM,WAAW,YAAY;IAC3B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAA;IACZ,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,MAAM,EAAE,OAAO,CAAA;IACf,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAA;IACd,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAA;IACf,kGAAkG;IAClG,UAAU,EAAE,MAAM,CAAA;IAClB,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,+FAA+F;IAC/F,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,kGAAkG;IAClG,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAeD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,MAAM,KAAG,YAAY,EAwE5D,CAAA;AA6FD;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,KAAG,MAAM,EAgBvD,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GAAI,WAAW,MAAM,KAAG,iBAAiB,GAAG,IAyCjF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,MAAM,EAW9D,CAAA"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The slice of SQL lexing and DDL parsing this bond needs to translate, or
|
|
3
|
+
* refuse, PostgreSQL-dialect migrations without changing their behaviour.
|
|
4
|
+
*
|
|
5
|
+
* It lives in the bond because it IS the bond's translation responsibility: a
|
|
6
|
+
* provider that cannot accept a construct as written has to read the statement
|
|
7
|
+
* well enough to rewrite it faithfully or to refuse it. It is deliberately not a
|
|
8
|
+
* general requirement analyser — that decision (which constructs a selection
|
|
9
|
+
* needs, and whether the selected provider can honour them) is compilation work
|
|
10
|
+
* and lives in `mlcl/src/lib/sql-requirements.ts`, shared by every harness.
|
|
11
|
+
*
|
|
12
|
+
* The rules preserved from that shared analysis: a semicolon ends a statement
|
|
13
|
+
* only outside a string literal, a quoted identifier, a dollar-quoted body and a
|
|
14
|
+
* comment; keywords are matched against a mask that blanks comment and literal
|
|
15
|
+
* CONTENT while keeping every offset, so slicing the mask addresses the same
|
|
16
|
+
* characters in the original; and a construct written inside a comment or a
|
|
17
|
+
* string is never mistaken for a real one.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
/** A dollar-quote opener: `$$` or `$tag$`. */
|
|
22
|
+
const DOLLAR_QUOTE = /^\$([A-Za-z_][A-Za-z0-9_]*)?\$/;
|
|
23
|
+
/** `CREATE [UNIQUE] INDEX [IF NOT EXISTS] <name> ON <table>` up to the next token. */
|
|
24
|
+
const CREATE_INDEX_HEAD = /^\s*CREATE\s+(UNIQUE\s+)?INDEX\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:"(?:[^"]|"")*"|[A-Za-z_][\w$-]*)\s+ON\s+(?:"(?:[^"]|"")*"|[A-Za-z_][\w$.-]*)\s*/i;
|
|
25
|
+
/** `USING <method>` — an index access method, which DuckDB has no equivalent for. */
|
|
26
|
+
const USING_METHOD = /^USING\s+([A-Za-z_][A-Za-z0-9_]*)\s*/i;
|
|
27
|
+
/** An unsupported foreign-key referential action. */
|
|
28
|
+
const FK_REFERENTIAL_ACTION = /\bON\s+(DELETE|UPDATE)\s+(CASCADE|SET\s+NULL|SET\s+DEFAULT)\b/gi;
|
|
29
|
+
/**
|
|
30
|
+
* Split a migration file into statements, keeping each statement's exact text
|
|
31
|
+
* and offsets.
|
|
32
|
+
*
|
|
33
|
+
* A semicolon ends a statement only outside a single-quoted string, a
|
|
34
|
+
* double-quoted identifier, a dollar-quoted body, a line comment and a block
|
|
35
|
+
* comment. The returned text includes the trailing semicolon; concatenating
|
|
36
|
+
* every `text` reproduces the input byte for byte.
|
|
37
|
+
*
|
|
38
|
+
* @param sql - The migration file's SQL.
|
|
39
|
+
* @returns The statements in source order.
|
|
40
|
+
*/
|
|
41
|
+
export const splitSqlStatements = (sql) => {
|
|
42
|
+
const statements = [];
|
|
43
|
+
let start = 0;
|
|
44
|
+
let index = 0;
|
|
45
|
+
const length = sql.length;
|
|
46
|
+
while (index < length) {
|
|
47
|
+
const char = sql[index];
|
|
48
|
+
if (char === '-' && sql[index + 1] === '-') {
|
|
49
|
+
const newline = sql.indexOf('\n', index);
|
|
50
|
+
index = newline < 0 ? length : newline;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (char === '/' && sql[index + 1] === '*') {
|
|
54
|
+
const close = sql.indexOf('*/', index + 2);
|
|
55
|
+
index = close < 0 ? length : close + 2;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (char === "'") {
|
|
59
|
+
index++;
|
|
60
|
+
while (index < length) {
|
|
61
|
+
if (sql[index] === '\\') {
|
|
62
|
+
index += 2;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (sql[index] === "'" && sql[index + 1] === "'") {
|
|
66
|
+
index += 2;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (sql[index] === "'") {
|
|
70
|
+
index++;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
index++;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (char === '"') {
|
|
78
|
+
index++;
|
|
79
|
+
while (index < length) {
|
|
80
|
+
if (sql[index] === '"' && sql[index + 1] === '"') {
|
|
81
|
+
index += 2;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (sql[index] === '"') {
|
|
85
|
+
index++;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
index++;
|
|
89
|
+
}
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (char === '$') {
|
|
93
|
+
const opener = DOLLAR_QUOTE.exec(sql.slice(index));
|
|
94
|
+
if (opener) {
|
|
95
|
+
const tag = opener[0];
|
|
96
|
+
const close = sql.indexOf(tag, index + tag.length);
|
|
97
|
+
index = close < 0 ? length : close + tag.length;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (char === ';') {
|
|
102
|
+
index++;
|
|
103
|
+
statements.push({ text: sql.slice(start, index), start, end: index });
|
|
104
|
+
start = index;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
index++;
|
|
108
|
+
}
|
|
109
|
+
if (start < length) {
|
|
110
|
+
statements.push({ text: sql.slice(start, length), start, end: length });
|
|
111
|
+
}
|
|
112
|
+
return statements;
|
|
113
|
+
};
|
|
114
|
+
/**
|
|
115
|
+
* Replace comment and string-literal CONTENT with spaces, keeping every offset
|
|
116
|
+
* (and every double-quoted identifier) in place.
|
|
117
|
+
*
|
|
118
|
+
* Keyword and parenthesis scanning then cannot be fooled by text inside a
|
|
119
|
+
* comment or a literal, while a slice taken from the mask still addresses the
|
|
120
|
+
* same characters in the original.
|
|
121
|
+
*
|
|
122
|
+
* @param text - The SQL text to mask.
|
|
123
|
+
* @returns A same-length string safe for structural scanning.
|
|
124
|
+
*/
|
|
125
|
+
const maskSql = (text) => {
|
|
126
|
+
let masked = '';
|
|
127
|
+
let index = 0;
|
|
128
|
+
const length = text.length;
|
|
129
|
+
while (index < length) {
|
|
130
|
+
const char = text[index];
|
|
131
|
+
if (char === '-' && text[index + 1] === '-') {
|
|
132
|
+
while (index < length && text[index] !== '\n') {
|
|
133
|
+
masked += ' ';
|
|
134
|
+
index++;
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (char === '/' && text[index + 1] === '*') {
|
|
139
|
+
const close = text.indexOf('*/', index + 2);
|
|
140
|
+
const end = close < 0 ? length : close + 2;
|
|
141
|
+
masked += ' '.repeat(end - index);
|
|
142
|
+
index = end;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (char === "'") {
|
|
146
|
+
masked += ' ';
|
|
147
|
+
index++;
|
|
148
|
+
while (index < length) {
|
|
149
|
+
if (text[index] === '\\') {
|
|
150
|
+
masked += ' ';
|
|
151
|
+
index += 2;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
if (text[index] === "'" && text[index + 1] === "'") {
|
|
155
|
+
masked += ' ';
|
|
156
|
+
index += 2;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (text[index] === "'") {
|
|
160
|
+
masked += ' ';
|
|
161
|
+
index++;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
masked += ' ';
|
|
165
|
+
index++;
|
|
166
|
+
}
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (char === '$') {
|
|
170
|
+
const opener = DOLLAR_QUOTE.exec(text.slice(index));
|
|
171
|
+
if (opener) {
|
|
172
|
+
const tag = opener[0];
|
|
173
|
+
const close = text.indexOf(tag, index + tag.length);
|
|
174
|
+
const end = close < 0 ? length : close + tag.length;
|
|
175
|
+
masked += ' '.repeat(end - index);
|
|
176
|
+
index = end;
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
masked += char;
|
|
181
|
+
index++;
|
|
182
|
+
}
|
|
183
|
+
return masked;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Index of the parenthesis matching the one at `openAt`, or -1 when unbalanced.
|
|
187
|
+
*
|
|
188
|
+
* @param masked - Masked SQL, same length as the original.
|
|
189
|
+
* @param openAt - Offset of an opening parenthesis.
|
|
190
|
+
* @returns Offset of its match, or -1.
|
|
191
|
+
*/
|
|
192
|
+
const matchingParen = (masked, openAt) => {
|
|
193
|
+
let depth = 0;
|
|
194
|
+
for (let index = openAt; index < masked.length; index++) {
|
|
195
|
+
if (masked[index] === '(')
|
|
196
|
+
depth++;
|
|
197
|
+
else if (masked[index] === ')') {
|
|
198
|
+
depth--;
|
|
199
|
+
if (depth === 0)
|
|
200
|
+
return index;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return -1;
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Split a column list at its top-level commas.
|
|
207
|
+
*
|
|
208
|
+
* A comma inside a function call (`lower(a, b)`) or a string literal does not
|
|
209
|
+
* split — the same masking the statement splitter uses keeps offsets aligned.
|
|
210
|
+
*
|
|
211
|
+
* @param columns - Text between a `CREATE INDEX` statement's outer parentheses.
|
|
212
|
+
* @returns Each column/expression text, trimmed.
|
|
213
|
+
*/
|
|
214
|
+
export const splitSqlColumns = (columns) => {
|
|
215
|
+
const masked = maskSql(columns);
|
|
216
|
+
const parts = [];
|
|
217
|
+
let depth = 0;
|
|
218
|
+
let start = 0;
|
|
219
|
+
for (let index = 0; index < masked.length; index++) {
|
|
220
|
+
const char = masked[index];
|
|
221
|
+
if (char === '(')
|
|
222
|
+
depth++;
|
|
223
|
+
else if (char === ')')
|
|
224
|
+
depth--;
|
|
225
|
+
else if (char === ',' && depth === 0) {
|
|
226
|
+
parts.push(columns.slice(start, index).trim());
|
|
227
|
+
start = index + 1;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
parts.push(columns.slice(start).trim());
|
|
231
|
+
return parts.filter((part) => part.length > 0);
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Parse a `CREATE [UNIQUE] INDEX` statement into the parts this bond rewrites.
|
|
235
|
+
*
|
|
236
|
+
* Returns `null` for any other statement. The returned slices are taken from the
|
|
237
|
+
* ORIGINAL text, so a translator can rebuild the statement without losing the
|
|
238
|
+
* author's casing or quoting.
|
|
239
|
+
*
|
|
240
|
+
* @param statement - One statement from {@link splitSqlStatements}.
|
|
241
|
+
* @returns The parsed index, or `null` when the statement is not a `CREATE INDEX`.
|
|
242
|
+
*/
|
|
243
|
+
export const parseCreateIndexStatement = (statement) => {
|
|
244
|
+
const masked = maskSql(statement);
|
|
245
|
+
const head = CREATE_INDEX_HEAD.exec(masked);
|
|
246
|
+
if (!head)
|
|
247
|
+
return null;
|
|
248
|
+
let cursor = head[0].length;
|
|
249
|
+
const using = USING_METHOD.exec(masked.slice(cursor));
|
|
250
|
+
const usingEnd = using ? cursor + using[0].length : cursor;
|
|
251
|
+
cursor = usingEnd;
|
|
252
|
+
if (masked[cursor] !== '(')
|
|
253
|
+
return null;
|
|
254
|
+
const closeAt = matchingParen(masked, cursor);
|
|
255
|
+
if (closeAt < 0)
|
|
256
|
+
return null;
|
|
257
|
+
const beforeParen = using ? statement.slice(0, head[0].length) : statement.slice(0, cursor);
|
|
258
|
+
const prefix = `${beforeParen}(`;
|
|
259
|
+
const columns = statement.slice(cursor + 1, closeAt);
|
|
260
|
+
const afterClose = statement.slice(closeAt + 1);
|
|
261
|
+
const maskedAfterClose = masked.slice(closeAt + 1);
|
|
262
|
+
const whereMatch = /\bWHERE\b/i.exec(maskedAfterClose);
|
|
263
|
+
if (!whereMatch) {
|
|
264
|
+
return {
|
|
265
|
+
unique: Boolean(head[1]),
|
|
266
|
+
prefix,
|
|
267
|
+
columns,
|
|
268
|
+
afterClose,
|
|
269
|
+
predicate: null,
|
|
270
|
+
afterPredicate: null,
|
|
271
|
+
optionsBeforeWhere: '',
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
const predicateStart = closeAt + 1 + whereMatch.index + whereMatch[0].length;
|
|
275
|
+
const trailingSemicolon = /;\s*$/.exec(statement);
|
|
276
|
+
const predicateEnd = trailingSemicolon ? trailingSemicolon.index : statement.length;
|
|
277
|
+
return {
|
|
278
|
+
unique: Boolean(head[1]),
|
|
279
|
+
prefix,
|
|
280
|
+
columns,
|
|
281
|
+
afterClose,
|
|
282
|
+
predicate: statement.slice(predicateStart, predicateEnd).trim(),
|
|
283
|
+
afterPredicate: statement.slice(predicateEnd),
|
|
284
|
+
optionsBeforeWhere: statement.slice(closeAt + 1, predicateStart - whereMatch[0].length).trim(),
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Every unsupported foreign-key referential action in one statement, in source
|
|
289
|
+
* order and normalized (`ON DELETE CASCADE`).
|
|
290
|
+
*
|
|
291
|
+
* A construct inside a comment or a string literal is ignored: those carry no
|
|
292
|
+
* constraint. `NO ACTION` and `RESTRICT` do not match — DuckDB accepts them.
|
|
293
|
+
*
|
|
294
|
+
* @param statement - One statement from {@link splitSqlStatements}.
|
|
295
|
+
* @returns The normalized actions, e.g. `['ON DELETE CASCADE']`.
|
|
296
|
+
*/
|
|
297
|
+
export const referentialActionsIn = (statement) => {
|
|
298
|
+
const masked = maskSql(statement);
|
|
299
|
+
const actions = [];
|
|
300
|
+
const action = new RegExp(FK_REFERENTIAL_ACTION.source, 'gi');
|
|
301
|
+
let match;
|
|
302
|
+
while ((match = action.exec(masked))) {
|
|
303
|
+
const event = match[1] ?? '';
|
|
304
|
+
const what = (match[2] ?? '').replace(/\s+/g, ' ').toUpperCase();
|
|
305
|
+
actions.push(`ON ${event.toUpperCase()} ${what}`);
|
|
306
|
+
}
|
|
307
|
+
return actions;
|
|
308
|
+
};
|
|
309
|
+
//# sourceMappingURL=sql-dialect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-dialect.js","sourceRoot":"","sources":["../src/sql-dialect.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DuckDB DataStore implementation.
|
|
3
|
+
*
|
|
4
|
+
* Translates abstract DataStore CRUD methods to DuckDB SQL. DuckDB binds `?`
|
|
5
|
+
* and `$1` placeholders natively positionally, so the SQL built here needs no
|
|
6
|
+
* conversion on its way to the engine.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import type { DatabasePool, DataStore } from '@molecule/api-database';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a DataStore backed by a DuckDB DatabasePool.
|
|
13
|
+
*
|
|
14
|
+
* @param pool - The DuckDB DatabasePool to use for queries.
|
|
15
|
+
* @returns A DataStore that translates CRUD operations to DuckDB-compatible SQL.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createStore(pool: DatabasePool): DataStore;
|
|
18
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EAIV,MAAM,wBAAwB,CAAA;AA6J/B;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,CAsPzD"}
|