@crvouga/mockingbird-service-postgres 1.5.1 → 1.7.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/AGENTS.md +5 -6
- package/CHANGELOG.md +27 -0
- package/COMPATIBILITY.md +14 -5
- package/README.md +30 -13
- package/dist/admin.js +191 -54
- package/dist/admin.js.map +4 -4
- package/dist/ast/nodes.d.ts +1 -0
- package/dist/index.js +118 -32
- package/dist/index.js.map +3 -3
- package/dist/runtime/database-context.d.ts +4 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +25808 -0
- package/dist/server.js.map +7 -0
- package/dist/sql/deparse.d.ts +1 -0
- package/dist/unstable.js +96 -31
- package/dist/unstable.js.map +3 -3
- package/dist/wire/cli.js +1766 -173
- package/dist/wire/cli.js.map +4 -4
- package/dist/wire/cluster.d.ts +23 -8
- package/dist/wire/connection.d.ts +25 -1
- package/dist/wire/fleet.d.ts +80 -0
- package/dist/wire/index.d.ts +11 -1
- package/dist/wire/index.js +608 -78
- package/dist/wire/index.js.map +3 -3
- package/dist/wire/probe.d.ts +2 -0
- package/dist/wire/protocol.d.ts +4 -0
- package/package.json +13 -2
package/dist/admin.js
CHANGED
|
@@ -717,12 +717,12 @@ function bootAdmin(config) {
|
|
|
717
717
|
throw new Error(`admin shell is missing #${id}`);
|
|
718
718
|
return node;
|
|
719
719
|
};
|
|
720
|
-
const errorMessage = (data,
|
|
720
|
+
const errorMessage = (data, fallback2) => {
|
|
721
721
|
if (!isRecord(data))
|
|
722
|
-
return
|
|
722
|
+
return fallback2;
|
|
723
723
|
const error = data.error;
|
|
724
724
|
if (!isRecord(error) || typeof error.message !== "string" || error.message === "") {
|
|
725
|
-
return
|
|
725
|
+
return fallback2;
|
|
726
726
|
}
|
|
727
727
|
return error.message;
|
|
728
728
|
};
|
|
@@ -981,8 +981,8 @@ function bootAdmin(config) {
|
|
|
981
981
|
const data = await api("GET", "/namespaces");
|
|
982
982
|
const select = el("namespace", HTMLSelectElement);
|
|
983
983
|
const listed2 = requireList(isRecord(data) ? data.namespaces : void 0, "Namespaces");
|
|
984
|
-
const
|
|
985
|
-
const names = (listed2.length > 0 ? listed2.map((name) => String(name)) : [
|
|
984
|
+
const fallback2 = isRecord(data) && typeof data.default === "string" && data.default !== "" ? data.default : "default";
|
|
985
|
+
const names = (listed2.length > 0 ? listed2.map((name) => String(name)) : [fallback2]).slice();
|
|
986
986
|
if (!names.includes(state.namespace))
|
|
987
987
|
names.unshift(state.namespace);
|
|
988
988
|
select.innerHTML = names.map((name) => `<option value="${esc(name)}">${esc(name)}</option>`).join("");
|
|
@@ -1561,29 +1561,30 @@ var createControlPlane = (context) => {
|
|
|
1561
1561
|
return json(200, { status: "ok", reset: target === "*" ? context.namespaces() : [target] });
|
|
1562
1562
|
},
|
|
1563
1563
|
"GET /namespaces": () => json(200, { default: context.defaultNamespace, namespaces: context.namespaces() }),
|
|
1564
|
-
"GET /clock": () => json(200, context.clock.state()),
|
|
1565
|
-
"POST /clock": ({ body }) => {
|
|
1564
|
+
"GET /clock": ({ namespace }) => json(200, (context.namespaceClock?.(namespace) ?? context.clock).state()),
|
|
1565
|
+
"POST /clock": ({ body, namespace }) => {
|
|
1566
|
+
const clock = context.namespaceClock?.(namespace) ?? context.clock;
|
|
1566
1567
|
if (!isRecord2(body))
|
|
1567
1568
|
return adminError(400, "expected a JSON object");
|
|
1568
1569
|
if (body.reset === true)
|
|
1569
|
-
|
|
1570
|
+
clock.reset();
|
|
1570
1571
|
if (body.freeze === true)
|
|
1571
|
-
|
|
1572
|
+
clock.freeze();
|
|
1572
1573
|
if (body.set !== void 0) {
|
|
1573
1574
|
const instant = parseInstant(body.set);
|
|
1574
1575
|
if (instant === void 0)
|
|
1575
1576
|
return adminError(400, "set: expected epoch ms or ISO-8601");
|
|
1576
|
-
|
|
1577
|
+
clock.set(instant);
|
|
1577
1578
|
}
|
|
1578
1579
|
if (body.advance !== void 0) {
|
|
1579
1580
|
const delta = parseDuration(body.advance);
|
|
1580
1581
|
if (delta === void 0)
|
|
1581
1582
|
return adminError(400, 'advance: expected ms or "15m"-style');
|
|
1582
|
-
|
|
1583
|
+
clock.advance(delta);
|
|
1583
1584
|
}
|
|
1584
1585
|
if (body.freeze === false)
|
|
1585
|
-
|
|
1586
|
-
return json(200,
|
|
1586
|
+
clock.unfreeze();
|
|
1587
|
+
return json(200, clock.state());
|
|
1587
1588
|
},
|
|
1588
1589
|
"GET /faults": () => json(200, { faults: context.faults.list() }),
|
|
1589
1590
|
"POST /faults": ({ body, namespace }) => {
|
|
@@ -2425,7 +2426,33 @@ var faultResponse = (rule) => {
|
|
|
2425
2426
|
};
|
|
2426
2427
|
var createFaultRegistry = (rng = createRng(0), sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) => {
|
|
2427
2428
|
const entries = [];
|
|
2429
|
+
let isolated = false;
|
|
2430
|
+
const scopedRngs = /* @__PURE__ */ new Map();
|
|
2431
|
+
const random = (namespace) => {
|
|
2432
|
+
if (!isolated || namespace === "default")
|
|
2433
|
+
return rng;
|
|
2434
|
+
let scoped = scopedRngs.get(namespace);
|
|
2435
|
+
if (!scoped) {
|
|
2436
|
+
scoped = createRng(rng.seed);
|
|
2437
|
+
scopedRngs.set(namespace, scoped);
|
|
2438
|
+
}
|
|
2439
|
+
return scoped;
|
|
2440
|
+
};
|
|
2428
2441
|
return {
|
|
2442
|
+
isolateNamespaces() {
|
|
2443
|
+
isolated = true;
|
|
2444
|
+
},
|
|
2445
|
+
snapshot(namespace) {
|
|
2446
|
+
return {
|
|
2447
|
+
rules: structuredClone(entries.map((entry, position) => ({
|
|
2448
|
+
...entry.rule,
|
|
2449
|
+
remaining: entry.remaining,
|
|
2450
|
+
hits: entry.hits,
|
|
2451
|
+
position
|
|
2452
|
+
})).filter((entry) => entry.namespace === namespace)),
|
|
2453
|
+
rngState: random(namespace).state()
|
|
2454
|
+
};
|
|
2455
|
+
},
|
|
2429
2456
|
add(rule) {
|
|
2430
2457
|
const existing = entries.findIndex((e) => e.rule.id === rule.id);
|
|
2431
2458
|
const entry = { rule, remaining: rule.count ?? null, hits: 0 };
|
|
@@ -2445,6 +2472,16 @@ var createFaultRegistry = (rng = createRng(0), sleep = (ms) => new Promise((reso
|
|
|
2445
2472
|
},
|
|
2446
2473
|
clear() {
|
|
2447
2474
|
entries.length = 0;
|
|
2475
|
+
rng.reset();
|
|
2476
|
+
scopedRngs.clear();
|
|
2477
|
+
},
|
|
2478
|
+
restore(namespace, state) {
|
|
2479
|
+
for (let i = entries.length - 1; i >= 0; i--)
|
|
2480
|
+
if (entries[i]?.rule.namespace === namespace)
|
|
2481
|
+
entries.splice(i, 1);
|
|
2482
|
+
for (const { remaining, hits, position, ...rule } of state.rules)
|
|
2483
|
+
entries.splice(Math.min(position, entries.length), 0, { rule, remaining, hits });
|
|
2484
|
+
random(namespace).setState(state.rngState);
|
|
2448
2485
|
},
|
|
2449
2486
|
async take(candidate) {
|
|
2450
2487
|
const hits = [];
|
|
@@ -2454,7 +2491,7 @@ var createFaultRegistry = (rng = createRng(0), sleep = (ms) => new Promise((reso
|
|
|
2454
2491
|
if (!matches(entry.rule, candidate))
|
|
2455
2492
|
continue;
|
|
2456
2493
|
const rate = entry.rule.rate ?? 1;
|
|
2457
|
-
if (
|
|
2494
|
+
if (random(candidate.namespace).next() >= rate)
|
|
2458
2495
|
continue;
|
|
2459
2496
|
entry.hits++;
|
|
2460
2497
|
if (entry.remaining !== null)
|
|
@@ -2521,7 +2558,8 @@ var createJournal = (size = DEFAULT_JOURNAL_SIZE) => {
|
|
|
2521
2558
|
};
|
|
2522
2559
|
|
|
2523
2560
|
// ../core/dist/metrics.js
|
|
2524
|
-
var createMetrics = () => {
|
|
2561
|
+
var createMetrics = (partition = true) => {
|
|
2562
|
+
const namespaces = /* @__PURE__ */ new Map();
|
|
2525
2563
|
let requests = 0;
|
|
2526
2564
|
let faults = 0;
|
|
2527
2565
|
let totalDurationMs = 0;
|
|
@@ -2529,6 +2567,14 @@ var createMetrics = () => {
|
|
|
2529
2567
|
const unmatched = /* @__PURE__ */ new Map();
|
|
2530
2568
|
return {
|
|
2531
2569
|
record(entry) {
|
|
2570
|
+
if (partition) {
|
|
2571
|
+
let scoped = namespaces.get(entry.namespace);
|
|
2572
|
+
if (!scoped) {
|
|
2573
|
+
scoped = createMetrics(false);
|
|
2574
|
+
namespaces.set(entry.namespace, scoped);
|
|
2575
|
+
}
|
|
2576
|
+
scoped.record(entry);
|
|
2577
|
+
}
|
|
2532
2578
|
requests++;
|
|
2533
2579
|
totalDurationMs += entry.durationMs;
|
|
2534
2580
|
if (entry.faultId !== void 0)
|
|
@@ -2540,7 +2586,7 @@ var createMetrics = () => {
|
|
|
2540
2586
|
unmatched.set(route, (unmatched.get(route) ?? 0) + 1);
|
|
2541
2587
|
}
|
|
2542
2588
|
},
|
|
2543
|
-
report: () => ({
|
|
2589
|
+
report: (namespace) => namespace !== void 0 ? (namespaces.get(namespace) ?? createMetrics(false)).report() : {
|
|
2544
2590
|
requests,
|
|
2545
2591
|
byOperation: Object.fromEntries([...byOperation].sort(([a], [b]) => a.localeCompare(b))),
|
|
2546
2592
|
unmatched: [...unmatched].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([route, count]) => {
|
|
@@ -2549,8 +2595,13 @@ var createMetrics = () => {
|
|
|
2549
2595
|
}),
|
|
2550
2596
|
faults,
|
|
2551
2597
|
totalDurationMs
|
|
2552
|
-
}
|
|
2553
|
-
reset() {
|
|
2598
|
+
},
|
|
2599
|
+
reset(namespace) {
|
|
2600
|
+
if (namespace !== void 0) {
|
|
2601
|
+
namespaces.delete(namespace);
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
namespaces.clear();
|
|
2554
2605
|
requests = 0;
|
|
2555
2606
|
faults = 0;
|
|
2556
2607
|
totalDurationMs = 0;
|
|
@@ -2629,9 +2680,9 @@ var kindFromType = (type) => {
|
|
|
2629
2680
|
return "unknown";
|
|
2630
2681
|
return "string";
|
|
2631
2682
|
};
|
|
2632
|
-
var countParam = (value,
|
|
2683
|
+
var countParam = (value, fallback2, max) => {
|
|
2633
2684
|
if (value === null)
|
|
2634
|
-
return
|
|
2685
|
+
return fallback2;
|
|
2635
2686
|
if (!/^\d+$/.test(value))
|
|
2636
2687
|
return void 0;
|
|
2637
2688
|
return Math.min(max, Number(value));
|
|
@@ -6344,7 +6395,13 @@ var DatabaseState = class _DatabaseState {
|
|
|
6344
6395
|
this.settings.set("lc_numeric", "C");
|
|
6345
6396
|
this.settings.set("lc_time", "C");
|
|
6346
6397
|
this.settings.set("default_transaction_isolation", "read committed");
|
|
6398
|
+
this.settings.set("lock_timeout", "0");
|
|
6399
|
+
this.settings.set("idle_in_transaction_session_timeout", "0");
|
|
6400
|
+
this.settings.set("transaction_timeout", "0");
|
|
6347
6401
|
this.settings.set("statement_timeout", "0");
|
|
6402
|
+
this.settings.set("check_function_bodies", "on");
|
|
6403
|
+
this.settings.set("xmloption", "content");
|
|
6404
|
+
this.settings.set("row_security", "on");
|
|
6348
6405
|
this.settings.set("array_nulls", "on");
|
|
6349
6406
|
this.settings.set("backslash_quote", "safe_encoding");
|
|
6350
6407
|
}
|
|
@@ -9946,6 +10003,19 @@ function exactDegTan(x) {
|
|
|
9946
10003
|
return Math.tan(x * Math.PI / 180);
|
|
9947
10004
|
}
|
|
9948
10005
|
|
|
10006
|
+
// src/sql/deparse.ts
|
|
10007
|
+
function quoteIdent(name) {
|
|
10008
|
+
if (/^[a-z_][a-z0-9_$]*$/.test(name)) return name;
|
|
10009
|
+
return `"${name.replaceAll('"', '""')}"`;
|
|
10010
|
+
}
|
|
10011
|
+
|
|
10012
|
+
// src/runtime/database-context.ts
|
|
10013
|
+
var contexts = /* @__PURE__ */ new WeakMap();
|
|
10014
|
+
var fallback = { name: "postgres", names: () => ["postgres"] };
|
|
10015
|
+
function databaseCatalogContext(state) {
|
|
10016
|
+
return contexts.get(state) ?? fallback;
|
|
10017
|
+
}
|
|
10018
|
+
|
|
9949
10019
|
// src/functions/misc-fns.ts
|
|
9950
10020
|
var PG_VERSION_TEXT = "PostgreSQL 18.3 (postgres-mem) on TypeScript, in-memory engine";
|
|
9951
10021
|
function findSequenceForCall(ctx, name) {
|
|
@@ -10029,8 +10099,8 @@ function sequenceNextval(ctx, seq) {
|
|
|
10029
10099
|
function getMiscFunctions() {
|
|
10030
10100
|
const m = /* @__PURE__ */ new Map();
|
|
10031
10101
|
m.set("version", () => tv("text", PG_VERSION_TEXT));
|
|
10032
|
-
m.set("current_database", () => tv("name",
|
|
10033
|
-
m.set("current_catalog", () => tv("name",
|
|
10102
|
+
m.set("current_database", (ctx) => tv("name", databaseCatalogContext(ctx.state).name));
|
|
10103
|
+
m.set("current_catalog", (ctx) => tv("name", databaseCatalogContext(ctx.state).name));
|
|
10034
10104
|
m.set("current_schema", (ctx) => {
|
|
10035
10105
|
const path = ctx.state.effectiveSearchPath();
|
|
10036
10106
|
const first = path.find((s) => ctx.state.schemas.has(s));
|
|
@@ -10152,7 +10222,7 @@ function getMiscFunctions() {
|
|
|
10152
10222
|
if (!col.identity) return tv("text", null);
|
|
10153
10223
|
return tv(
|
|
10154
10224
|
"text",
|
|
10155
|
-
col.identity.sequence.split(".").map(
|
|
10225
|
+
col.identity.sequence.split(".").map(quoteIdent).join(".")
|
|
10156
10226
|
);
|
|
10157
10227
|
})
|
|
10158
10228
|
);
|
|
@@ -17402,14 +17472,19 @@ var Parser = class {
|
|
|
17402
17472
|
parseIdentityOptions() {
|
|
17403
17473
|
const options = {};
|
|
17404
17474
|
if (this.eatPunct("(")) {
|
|
17405
|
-
Object.assign(options, this.parseSequenceOptions());
|
|
17475
|
+
Object.assign(options, this.parseSequenceOptions(true));
|
|
17406
17476
|
this.expectPunct(")");
|
|
17407
17477
|
}
|
|
17408
17478
|
return options;
|
|
17409
17479
|
}
|
|
17410
|
-
parseSequenceOptions() {
|
|
17480
|
+
parseSequenceOptions(identity = false) {
|
|
17411
17481
|
const options = {};
|
|
17412
17482
|
for (; ; ) {
|
|
17483
|
+
if (identity && this.eatKw("sequence")) {
|
|
17484
|
+
this.expectKw("name");
|
|
17485
|
+
options.sequenceName = this.qualifiedName();
|
|
17486
|
+
continue;
|
|
17487
|
+
}
|
|
17413
17488
|
if (this.eatKw("increment")) {
|
|
17414
17489
|
this.eatKw("by");
|
|
17415
17490
|
options.increment = this.parseSignedBigInt();
|
|
@@ -23411,6 +23486,27 @@ function parseCsvLine(line, delim, quote) {
|
|
|
23411
23486
|
}
|
|
23412
23487
|
return fields;
|
|
23413
23488
|
}
|
|
23489
|
+
function splitCsvRecords(data, quote) {
|
|
23490
|
+
const records = [];
|
|
23491
|
+
let start = 0;
|
|
23492
|
+
let quoted = false;
|
|
23493
|
+
for (let i = 0; i < data.length; i++) {
|
|
23494
|
+
const char = data[i];
|
|
23495
|
+
if (char === quote) {
|
|
23496
|
+
if (quoted && data[i + 1] === quote) i++;
|
|
23497
|
+
else quoted = !quoted;
|
|
23498
|
+
continue;
|
|
23499
|
+
}
|
|
23500
|
+
if (char === "\n" && !quoted) {
|
|
23501
|
+
const end = i > start && data[i - 1] === "\r" ? i - 1 : i;
|
|
23502
|
+
records.push(data.slice(start, end));
|
|
23503
|
+
start = i + 1;
|
|
23504
|
+
}
|
|
23505
|
+
}
|
|
23506
|
+
if (quoted) throw pgError("invalid_text_representation", "unterminated CSV quoted field", "22P04");
|
|
23507
|
+
if (start < data.length) records.push(data.slice(start));
|
|
23508
|
+
return records;
|
|
23509
|
+
}
|
|
23414
23510
|
function executeCopyFromData(env, stmt, data) {
|
|
23415
23511
|
const format = String(stmt.options.format ?? "text").toLowerCase();
|
|
23416
23512
|
if (format !== "text" && format !== "csv") throw unsupported(`COPY format ${format}`);
|
|
@@ -23421,7 +23517,7 @@ function executeCopyFromData(env, stmt, data) {
|
|
|
23421
23517
|
const nullStr = String(stmt.options.null ?? (format === "csv" ? "" : "\\N"));
|
|
23422
23518
|
const quote = String(stmt.options.quote ?? '"');
|
|
23423
23519
|
const header = stmt.options.header === true || String(stmt.options.header ?? "").toLowerCase() === "true";
|
|
23424
|
-
let lines = data.split(/\r?\n/);
|
|
23520
|
+
let lines = format === "csv" ? splitCsvRecords(data, quote) : data.split(/\r?\n/);
|
|
23425
23521
|
const endMarker = lines.indexOf("\\.");
|
|
23426
23522
|
if (endMarker !== -1) lines = lines.slice(0, endMarker);
|
|
23427
23523
|
if (lines.length > 0 && lines[lines.length - 1] === "") lines = lines.slice(0, -1);
|
|
@@ -24155,7 +24251,8 @@ function pgSettings(ctx) {
|
|
|
24155
24251
|
"pg_settings"
|
|
24156
24252
|
);
|
|
24157
24253
|
}
|
|
24158
|
-
function pgDatabase() {
|
|
24254
|
+
function pgDatabase(ctx) {
|
|
24255
|
+
const names = databaseCatalogContext(ctx.state).names();
|
|
24159
24256
|
return rel(
|
|
24160
24257
|
[
|
|
24161
24258
|
["oid", "oid"],
|
|
@@ -24164,7 +24261,7 @@ function pgDatabase() {
|
|
|
24164
24261
|
["datistemplate", "bool"],
|
|
24165
24262
|
["datallowconn", "bool"]
|
|
24166
24263
|
],
|
|
24167
|
-
[
|
|
24264
|
+
names.map((name, index) => [5 + index, name, 6, false, true]),
|
|
24168
24265
|
"pg_database"
|
|
24169
24266
|
);
|
|
24170
24267
|
}
|
|
@@ -24199,13 +24296,14 @@ function pgTrigger(ctx) {
|
|
|
24199
24296
|
"pg_trigger"
|
|
24200
24297
|
);
|
|
24201
24298
|
}
|
|
24202
|
-
var
|
|
24299
|
+
var catalogName = (state) => databaseCatalogContext(state).name;
|
|
24203
24300
|
function infoSchemata(state) {
|
|
24301
|
+
const catalog = catalogName(state);
|
|
24204
24302
|
const rows = [
|
|
24205
|
-
[
|
|
24206
|
-
[
|
|
24303
|
+
[catalog, "pg_catalog", OWNER],
|
|
24304
|
+
[catalog, "information_schema", OWNER]
|
|
24207
24305
|
];
|
|
24208
|
-
for (const s of state.schemas.values()) rows.push([
|
|
24306
|
+
for (const s of state.schemas.values()) rows.push([catalog, s.name, OWNER]);
|
|
24209
24307
|
return rel(
|
|
24210
24308
|
[
|
|
24211
24309
|
["catalog_name", "name"],
|
|
@@ -24217,13 +24315,14 @@ function infoSchemata(state) {
|
|
|
24217
24315
|
);
|
|
24218
24316
|
}
|
|
24219
24317
|
function infoTables(ctx) {
|
|
24318
|
+
const catalog = catalogName(ctx.state);
|
|
24220
24319
|
const rows = [];
|
|
24221
24320
|
for (const schema of ctx.state.schemas.values()) {
|
|
24222
24321
|
for (const t of schema.tables.values()) {
|
|
24223
|
-
rows.push([
|
|
24322
|
+
rows.push([catalog, t.schema, t.name, t.temp ? "LOCAL TEMPORARY" : "BASE TABLE", "YES"]);
|
|
24224
24323
|
}
|
|
24225
24324
|
for (const v of schema.views.values()) {
|
|
24226
|
-
if (!v.materialized) rows.push([
|
|
24325
|
+
if (!v.materialized) rows.push([catalog, v.schema, v.name, "VIEW", "NO"]);
|
|
24227
24326
|
}
|
|
24228
24327
|
}
|
|
24229
24328
|
return rel(
|
|
@@ -24239,6 +24338,7 @@ function infoTables(ctx) {
|
|
|
24239
24338
|
);
|
|
24240
24339
|
}
|
|
24241
24340
|
function infoColumns(ctx) {
|
|
24341
|
+
const catalog = catalogName(ctx.state);
|
|
24242
24342
|
const rows = [];
|
|
24243
24343
|
for (const t of allTables(ctx.state)) {
|
|
24244
24344
|
t.columns.forEach((c, i) => {
|
|
@@ -24249,7 +24349,7 @@ function infoColumns(ctx) {
|
|
|
24249
24349
|
const dataType = isArrayType(id) ? "ARRAY" : isEnumType(id) ? "USER-DEFINED" : typeDisplayName(id);
|
|
24250
24350
|
const udt = isArrayType(id) ? `_${arrayUdt(id)}` : isEnumType(id) ? id.slice(5).split(".").pop() : id;
|
|
24251
24351
|
rows.push([
|
|
24252
|
-
|
|
24352
|
+
catalog,
|
|
24253
24353
|
t.schema,
|
|
24254
24354
|
t.name,
|
|
24255
24355
|
c.name,
|
|
@@ -24294,10 +24394,11 @@ function arrayUdt(t) {
|
|
|
24294
24394
|
return isEnumType(elem) ? elem.slice(5).split(".").pop() : elem;
|
|
24295
24395
|
}
|
|
24296
24396
|
function infoViews(ctx) {
|
|
24397
|
+
const catalog = catalogName(ctx.state);
|
|
24297
24398
|
const rows = [];
|
|
24298
24399
|
for (const schema of ctx.state.schemas.values()) {
|
|
24299
24400
|
for (const v of schema.views.values()) {
|
|
24300
|
-
if (!v.materialized) rows.push([
|
|
24401
|
+
if (!v.materialized) rows.push([catalog, v.schema, v.name, null]);
|
|
24301
24402
|
}
|
|
24302
24403
|
}
|
|
24303
24404
|
return rel(
|
|
@@ -24312,10 +24413,11 @@ function infoViews(ctx) {
|
|
|
24312
24413
|
);
|
|
24313
24414
|
}
|
|
24314
24415
|
function infoSequences(ctx) {
|
|
24416
|
+
const catalog = catalogName(ctx.state);
|
|
24315
24417
|
const rows = [];
|
|
24316
24418
|
for (const s of allSequences(ctx.state)) {
|
|
24317
24419
|
rows.push([
|
|
24318
|
-
|
|
24420
|
+
catalog,
|
|
24319
24421
|
s.schema,
|
|
24320
24422
|
s.name,
|
|
24321
24423
|
typeDisplayName(s.dataType),
|
|
@@ -24343,11 +24445,12 @@ function infoSequences(ctx) {
|
|
|
24343
24445
|
);
|
|
24344
24446
|
}
|
|
24345
24447
|
function infoTableConstraints(ctx) {
|
|
24448
|
+
const catalog = catalogName(ctx.state);
|
|
24346
24449
|
const rows = [];
|
|
24347
24450
|
for (const t of allTables(ctx.state)) {
|
|
24348
24451
|
for (const c of t.constraints) {
|
|
24349
24452
|
const type = c.kind === "primary_key" ? "PRIMARY KEY" : c.kind === "unique" ? "UNIQUE" : c.kind === "check" ? "CHECK" : "FOREIGN KEY";
|
|
24350
|
-
rows.push([
|
|
24453
|
+
rows.push([catalog, t.schema, c.name, catalog, t.schema, t.name, type]);
|
|
24351
24454
|
}
|
|
24352
24455
|
}
|
|
24353
24456
|
return rel(
|
|
@@ -24365,12 +24468,13 @@ function infoTableConstraints(ctx) {
|
|
|
24365
24468
|
);
|
|
24366
24469
|
}
|
|
24367
24470
|
function infoKeyColumnUsage(ctx) {
|
|
24471
|
+
const catalog = catalogName(ctx.state);
|
|
24368
24472
|
const rows = [];
|
|
24369
24473
|
for (const t of allTables(ctx.state)) {
|
|
24370
24474
|
for (const c of t.constraints) {
|
|
24371
24475
|
if (c.kind !== "primary_key" && c.kind !== "unique" && c.kind !== "foreign_key") continue;
|
|
24372
24476
|
c.columns.forEach((col, i) => {
|
|
24373
|
-
rows.push([
|
|
24477
|
+
rows.push([catalog, t.schema, c.name, catalog, t.schema, t.name, col, i + 1]);
|
|
24374
24478
|
});
|
|
24375
24479
|
}
|
|
24376
24480
|
}
|
|
@@ -24390,12 +24494,13 @@ function infoKeyColumnUsage(ctx) {
|
|
|
24390
24494
|
);
|
|
24391
24495
|
}
|
|
24392
24496
|
function infoRoutines(ctx) {
|
|
24497
|
+
const catalog = catalogName(ctx.state);
|
|
24393
24498
|
const rows = [];
|
|
24394
24499
|
for (const schema of ctx.state.schemas.values()) {
|
|
24395
24500
|
for (const fns of schema.functions.values()) {
|
|
24396
24501
|
for (const f of fns) {
|
|
24397
24502
|
rows.push([
|
|
24398
|
-
|
|
24503
|
+
catalog,
|
|
24399
24504
|
f.schema,
|
|
24400
24505
|
f.name,
|
|
24401
24506
|
"FUNCTION",
|
|
@@ -24452,7 +24557,7 @@ function buildCatalogRelation(ctx, schema, name) {
|
|
|
24452
24557
|
case "pg_settings":
|
|
24453
24558
|
return pgSettings(ctx);
|
|
24454
24559
|
case "pg_database":
|
|
24455
|
-
return pgDatabase();
|
|
24560
|
+
return pgDatabase(ctx);
|
|
24456
24561
|
case "pg_roles":
|
|
24457
24562
|
case "pg_user":
|
|
24458
24563
|
return pgRoles();
|
|
@@ -24633,6 +24738,11 @@ var MAX_IDENT = 63;
|
|
|
24633
24738
|
function truncIdent(s) {
|
|
24634
24739
|
return s.length > MAX_IDENT ? s.slice(0, MAX_IDENT) : s;
|
|
24635
24740
|
}
|
|
24741
|
+
function identitySequenceTarget(env, tableSchema, defaultName, options) {
|
|
24742
|
+
const parts = options.sequenceName;
|
|
24743
|
+
if (!parts || parts.length === 0) return { schema: tableSchema, name: defaultName };
|
|
24744
|
+
return targetSchema(env, parts);
|
|
24745
|
+
}
|
|
24636
24746
|
var SEQ_LIMITS = {
|
|
24637
24747
|
int2: { min: -32768n, max: 32767n },
|
|
24638
24748
|
int4: { min: -2147483648n, max: 2147483647n },
|
|
@@ -24809,8 +24919,8 @@ function buildColumn(env, schema, tableName, def, out, taken) {
|
|
|
24809
24919
|
break;
|
|
24810
24920
|
}
|
|
24811
24921
|
case "generated_identity": {
|
|
24812
|
-
const
|
|
24813
|
-
const seq = buildSequence(env, schema,
|
|
24922
|
+
const target = identitySequenceTarget(env, schema, truncIdent(`${tableName}_${def.name}_seq`), c.options);
|
|
24923
|
+
const seq = buildSequence(env, target.schema, target.name, c.options, false);
|
|
24814
24924
|
if (!c.options.as) {
|
|
24815
24925
|
seq.dataType = col.type.id === "int2" || col.type.id === "int4" || col.type.id === "int8" ? col.type.id : "int8";
|
|
24816
24926
|
const limits = SEQ_LIMITS[seq.dataType];
|
|
@@ -24819,7 +24929,7 @@ function buildColumn(env, schema, tableName, def, out, taken) {
|
|
|
24819
24929
|
}
|
|
24820
24930
|
seq.ownedBy = { table: tableName, column: def.name };
|
|
24821
24931
|
out.sequences.push(seq);
|
|
24822
|
-
col.identity = { always: c.always, sequence: `${schema.name}.${
|
|
24932
|
+
col.identity = { always: c.always, sequence: `${target.schema.name}.${target.name}` };
|
|
24823
24933
|
col.notNull = true;
|
|
24824
24934
|
break;
|
|
24825
24935
|
}
|
|
@@ -24955,10 +25065,11 @@ function executeCreateTable(env, stmt) {
|
|
|
24955
25065
|
throw pgError("invalid_table_definition", `multiple primary keys for table "${name}" are not allowed`, "42P16");
|
|
24956
25066
|
}
|
|
24957
25067
|
for (const seq of built.sequences) {
|
|
24958
|
-
|
|
25068
|
+
const seqSchema = state.getSchema(seq.schema);
|
|
25069
|
+
if (seqSchema.hasRelation(seq.name)) {
|
|
24959
25070
|
throw pgError("duplicate_table", `relation "${seq.name}" already exists`, "42P07");
|
|
24960
25071
|
}
|
|
24961
|
-
|
|
25072
|
+
seqSchema.sequences.set(seq.name, seq);
|
|
24962
25073
|
}
|
|
24963
25074
|
const table = new TableData(schema.name, name, built.columns, state.nextOid(), stmt.temp);
|
|
24964
25075
|
table.constraints = built.constraints;
|
|
@@ -25310,7 +25421,13 @@ function executeAlterTable(env, stmt) {
|
|
|
25310
25421
|
const built = { columns: [], constraints: [], sequences: [] };
|
|
25311
25422
|
const taken = constraintNames(table);
|
|
25312
25423
|
const col = buildColumn(env, schema, table.name, action.column, built, taken);
|
|
25313
|
-
for (const seq of built.sequences)
|
|
25424
|
+
for (const seq of built.sequences) {
|
|
25425
|
+
const seqSchema = state.getSchema(seq.schema);
|
|
25426
|
+
if (seqSchema.hasRelation(seq.name)) {
|
|
25427
|
+
throw pgError("duplicate_table", `relation "${seq.name}" already exists`, "42P07");
|
|
25428
|
+
}
|
|
25429
|
+
seqSchema.sequences.set(seq.name, seq);
|
|
25430
|
+
}
|
|
25314
25431
|
table.columns.push(col);
|
|
25315
25432
|
table.constraints.push(...built.constraints);
|
|
25316
25433
|
for (let i = 0; i < rows.length; i++) {
|
|
@@ -25630,12 +25747,32 @@ function executeAlterTable(env, stmt) {
|
|
|
25630
25747
|
"42P16"
|
|
25631
25748
|
);
|
|
25632
25749
|
}
|
|
25633
|
-
|
|
25634
|
-
|
|
25750
|
+
if (!col.notNull) {
|
|
25751
|
+
throw pgError(
|
|
25752
|
+
"object_not_in_prerequisite_state",
|
|
25753
|
+
`column "${action.column}" of relation "${table.name}" must be declared NOT NULL before identity can be added`,
|
|
25754
|
+
"55000"
|
|
25755
|
+
);
|
|
25756
|
+
}
|
|
25757
|
+
const target = identitySequenceTarget(
|
|
25758
|
+
env,
|
|
25759
|
+
schema,
|
|
25760
|
+
truncIdent(`${table.name}_${action.column}_seq`),
|
|
25761
|
+
action.options
|
|
25762
|
+
);
|
|
25763
|
+
if (target.schema.hasRelation(target.name)) {
|
|
25764
|
+
throw pgError("duplicate_table", `relation "${target.name}" already exists`, "42P07");
|
|
25765
|
+
}
|
|
25766
|
+
const seq = buildSequence(env, target.schema, target.name, action.options, false);
|
|
25767
|
+
if (!action.options.as) {
|
|
25768
|
+
seq.dataType = col.type.id === "int2" || col.type.id === "int4" || col.type.id === "int8" ? col.type.id : "int8";
|
|
25769
|
+
const limits = SEQ_LIMITS[seq.dataType];
|
|
25770
|
+
if (action.options.maxValue === void 0) seq.maxValue = seq.increment > 0n ? limits.max : -1n;
|
|
25771
|
+
if (action.options.minValue === void 0) seq.minValue = seq.increment > 0n ? 1n : limits.min;
|
|
25772
|
+
}
|
|
25635
25773
|
seq.ownedBy = { table: table.name, column: action.column };
|
|
25636
|
-
schema.sequences.set(
|
|
25637
|
-
col.identity = { always:
|
|
25638
|
-
col.notNull = true;
|
|
25774
|
+
target.schema.sequences.set(target.name, seq);
|
|
25775
|
+
col.identity = { always: action.always, sequence: `${target.schema.name}.${target.name}` };
|
|
25639
25776
|
break;
|
|
25640
25777
|
}
|
|
25641
25778
|
case "drop_identity": {
|
|
@@ -26504,7 +26641,7 @@ if (typeof disposeKey === "symbol") {
|
|
|
26504
26641
|
|
|
26505
26642
|
// src/admin.ts
|
|
26506
26643
|
var QUERY_CAP = 500;
|
|
26507
|
-
var
|
|
26644
|
+
var quoteIdent2 = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
26508
26645
|
var bounded = (value) => {
|
|
26509
26646
|
if (!Number.isSafeInteger(value) || value < 0) throw new Error("limit and offset must be non-negative integers");
|
|
26510
26647
|
return value;
|
|
@@ -26577,7 +26714,7 @@ var adapt = (db) => ({
|
|
|
26577
26714
|
tables: () => listed(db),
|
|
26578
26715
|
page(schema, table, limit, offset) {
|
|
26579
26716
|
const found = requireTable(db, schema, table);
|
|
26580
|
-
const from = `${
|
|
26717
|
+
const from = `${quoteIdent2(schema)}.${quoteIdent2(table)}`;
|
|
26581
26718
|
const take = bounded(limit);
|
|
26582
26719
|
const skip = bounded(offset);
|
|
26583
26720
|
const totalRow = db.query(`SELECT count(*) AS count FROM ${from}`);
|