neon 3.1.0 → 3.2.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/README.md +30 -5
- package/dist/{_shared/auth_selection.js → _chunks/auth_selection-DGgq6ifc.js} +3 -3
- package/dist/_chunks/cmd_pipeline-CUbBO9U_.js +2818 -0
- package/dist/{_shared/credentials.js → _chunks/credentials-MYdHdKah.js} +3 -3
- package/dist/_chunks/env-NbA61JR3.js +585 -0
- package/dist/{_shared/env-core/env.js → _chunks/env_services-Tz9G4JeT.js} +179 -43
- package/dist/{_shared/paths.js → _chunks/paths-DMq0Lt7a.js} +2 -2
- package/dist/{_shared/profiles.js → _chunks/profiles-Ir29rqns.js} +4 -13
- package/dist/_chunks/psql-DWH-kc69.js +2169 -0
- package/dist/{_virtual/_rolldown/runtime.js → _chunks/rolldown-runtime-D7D4PA-g.js} +1 -1
- package/dist/{_shared/secure_file.js → _chunks/secure_file-BucZj4yQ.js} +2 -4
- package/dist/analytics.js +2 -2
- package/dist/auth_context.js +1 -1
- package/dist/commands/api.js +2 -2
- package/dist/commands/api_keys.js +2 -2
- package/dist/commands/auth.js +7 -6
- package/dist/commands/bootstrap.js +3 -3
- package/dist/commands/branches.js +2 -2
- package/dist/commands/bucket.js +2 -2
- package/dist/commands/checkout.js +2 -2
- package/dist/commands/config.js +2 -2
- package/dist/commands/connection_string.js +2 -2
- package/dist/commands/data_api.js +2 -2
- package/dist/commands/databases.js +2 -2
- package/dist/commands/deploy.js +2 -2
- package/dist/commands/dev.js +3 -3
- package/dist/commands/diff.js +2 -2
- package/dist/commands/env.js +42 -32
- package/dist/commands/functions.js +2 -2
- package/dist/commands/index.js +35 -33
- package/dist/commands/init.js +3 -3
- package/dist/commands/inspect.js +2 -2
- package/dist/commands/ip_allow.js +2 -2
- package/dist/commands/link.js +2 -2
- package/dist/commands/logs.js +2 -2
- package/dist/commands/neon_auth.js +2 -2
- package/dist/commands/open.js +33 -0
- package/dist/commands/operations.js +2 -2
- package/dist/commands/orgs.js +2 -2
- package/dist/commands/profile.js +7 -7
- package/dist/commands/projects.js +2 -2
- package/dist/commands/psql.js +2 -2
- package/dist/commands/roles.js +2 -2
- package/dist/commands/set_context.js +2 -2
- package/dist/commands/snapshots.js +2 -2
- package/dist/commands/status.js +2 -2
- package/dist/commands/user.js +2 -2
- package/dist/commands/vpc_endpoints.js +2 -2
- package/dist/config.js +1 -1
- package/dist/dev/env.js +1 -364
- package/dist/env_services.js +2 -49
- package/dist/index.js +2 -1
- package/dist/init/auth.js +4 -4
- package/dist/psql/cli.js +1 -1
- package/dist/psql/command/cmd_copy.js +1 -1
- package/dist/psql/command/cmd_io.js +1 -1403
- package/dist/psql/command/cmd_pipeline.js +1 -595
- package/dist/psql/command/dispatch.js +1 -2
- package/dist/psql/core/common.js +1 -834
- package/dist/psql/core/mainloop.js +1 -2
- package/dist/psql/core/startup.js +1 -656
- package/dist/psql/index.js +1 -1516
- package/dist/psql/io/psqlrc.js +1 -1
- package/dist/psql/types/index.js +6 -0
- package/dist/utils/inspect_db.js +1 -1
- package/dist/utils/middlewares.js +2 -1
- package/package.json +7 -4
- package/dist/_shared/env-core/reuse-secrets.js +0 -179
|
@@ -1,596 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { alignedPrinter } from "../print/aligned.js";
|
|
3
|
-
import { clearPipelineGateErrors, cmdGdesc } from "./cmd_io.js";
|
|
4
|
-
//#region src/psql/command/cmd_pipeline.ts
|
|
5
|
-
/**
|
|
6
|
-
* psql pipeline / extended-query backslash commands (WP-21).
|
|
7
|
-
*
|
|
8
|
-
* Implements the subset of upstream psql's "pipeline mode" backslash commands
|
|
9
|
-
* that drive the extended protocol directly. These are typically used together
|
|
10
|
-
* with the existing `\g` flow: a `\bind` (or `\parse`) command stashes
|
|
11
|
-
* parameter / statement state on the {@link BackslashContext}'s settings via
|
|
12
|
-
* a Symbol-keyed slot; when the mainloop then sees a `;` (or a `\g`), it can
|
|
13
|
-
* notice the stashed state and route the query through
|
|
14
|
-
* `Connection.query(sql, params)` instead of `execSimple`.
|
|
15
|
-
*
|
|
16
|
-
* Because the mainloop integration is owned by other WPs (and was deliberately
|
|
17
|
-
* left untouched here), this module exposes both the command specs AND a
|
|
18
|
-
* small helper, {@link getPipelineState}, that the mainloop will use to
|
|
19
|
-
* consult the stashed state. The commands operate on the buffered query the
|
|
20
|
-
* same way `\g` does — they execute or queue the buffer and reset it.
|
|
21
|
-
*
|
|
22
|
-
* Commands shipped:
|
|
23
|
-
*
|
|
24
|
-
* \bind [VALUE ...] stash params for next ; / \g
|
|
25
|
-
* \bind_named NAME [V ...] stash params + named prepared statement
|
|
26
|
-
* \parse NAME prepare current query buffer as NAME
|
|
27
|
-
* \close_prepared NAME Close('S', NAME)
|
|
28
|
-
* \startpipeline begin a pipeline session (settings.sendMode)
|
|
29
|
-
* \endpipeline end the pipeline session, drain results
|
|
30
|
-
* \syncpipeline send Sync mid-pipeline
|
|
31
|
-
* \sendpipeline submit the current buffered query w/o waiting
|
|
32
|
-
* \flushrequest send Flush
|
|
33
|
-
* \flush alias for \flushrequest
|
|
34
|
-
* \getresults [N] drain pending pipeline results
|
|
35
|
-
* \gdesc describe-without-execute the buffered query
|
|
36
|
-
*
|
|
37
|
-
* The set is registered in bulk via {@link registerPipelineCommands}.
|
|
38
|
-
*/
|
|
39
|
-
const BIND_STATE_KEY = Symbol.for("neonctl.psql.bindState");
|
|
40
|
-
const PIPELINE_KEY = Symbol.for("neonctl.psql.pipeline");
|
|
41
|
-
const PREPARED_BY_NAME_KEY = Symbol.for("neonctl.psql.preparedByName");
|
|
42
|
-
const stashOf = (settings) => settings;
|
|
43
|
-
/** Read (and clear) the pending bind params, if any. */
|
|
44
|
-
const consumeBindState = (settings) => {
|
|
45
|
-
const s = stashOf(settings);
|
|
46
|
-
const cur = s[BIND_STATE_KEY] ?? null;
|
|
47
|
-
s[BIND_STATE_KEY] = void 0;
|
|
48
|
-
return cur;
|
|
49
|
-
};
|
|
50
|
-
/**
|
|
51
|
-
* Peek at the bind stash without consuming. Used by `\g` to decide
|
|
52
|
-
* whether to skip the "empty buffer, no prior query" no-op guard:
|
|
53
|
-
* when a `\bind_named NAME` is pending, the prepared statement carries
|
|
54
|
-
* the SQL server-side so no buffer text is needed.
|
|
55
|
-
*/
|
|
56
|
-
const stagedNamedBindPresent = (settings) => {
|
|
57
|
-
const cur = stashOf(settings)[BIND_STATE_KEY];
|
|
58
|
-
return !!cur && cur.byName;
|
|
59
|
-
};
|
|
60
|
-
/** Stash a PreparedStatement for later `\bind_named NAME \g` lookup. */
|
|
61
|
-
const stashPrepared = (settings, name, ps) => {
|
|
62
|
-
const s = stashOf(settings);
|
|
63
|
-
let map = s[PREPARED_BY_NAME_KEY];
|
|
64
|
-
if (!map) {
|
|
65
|
-
map = /* @__PURE__ */ new Map();
|
|
66
|
-
s[PREPARED_BY_NAME_KEY] = map;
|
|
67
|
-
}
|
|
68
|
-
map.set(name, ps);
|
|
69
|
-
};
|
|
70
|
-
/** Look up a previously-stashed PreparedStatement by name. */
|
|
71
|
-
const lookupPrepared = (settings, name) => {
|
|
72
|
-
return stashOf(settings)[PREPARED_BY_NAME_KEY]?.get(name) ?? null;
|
|
73
|
-
};
|
|
74
|
-
/** Drop a stashed PreparedStatement (after `\close_prepared`). */
|
|
75
|
-
const dropPrepared = (settings, name) => {
|
|
76
|
-
const map = stashOf(settings)[PREPARED_BY_NAME_KEY];
|
|
77
|
-
if (map) map.delete(name);
|
|
78
|
-
};
|
|
79
|
-
/** Peek at the current pipeline session (or null). */
|
|
80
|
-
const getPipelineState = (settings) => stashOf(settings)[PIPELINE_KEY] ?? null;
|
|
81
|
-
const readCounter = (settings, name) => {
|
|
82
|
-
const raw = settings.vars.get(name);
|
|
83
|
-
if (raw === void 0) return 0;
|
|
84
|
-
const n = parseInt(raw, 10);
|
|
85
|
-
return Number.isFinite(n) && n >= 0 ? n : 0;
|
|
86
|
-
};
|
|
87
|
-
const setCounter = (settings, name, value) => {
|
|
88
|
-
settings.vars.set(name, String(Math.max(0, value)));
|
|
89
|
-
};
|
|
90
|
-
const bumpCounter = (settings, name, delta) => {
|
|
91
|
-
setCounter(settings, name, readCounter(settings, name) + delta);
|
|
92
|
-
};
|
|
93
|
-
const resetPipelineCounters = (settings) => {
|
|
94
|
-
setCounter(settings, "PIPELINE_COMMAND_COUNT", 0);
|
|
95
|
-
setCounter(settings, "PIPELINE_SYNC_COUNT", 0);
|
|
96
|
-
setCounter(settings, "PIPELINE_RESULT_COUNT", 0);
|
|
97
|
-
};
|
|
98
|
-
/**
|
|
99
|
-
* Wrap `Pipeline.execute` so each enqueued Execute message bumps
|
|
100
|
-
* `PIPELINE_COMMAND_COUNT`. The wrapping covers both call sites:
|
|
101
|
-
*
|
|
102
|
-
* - `cmdSendPipeline` (this file) — `\sendpipeline`.
|
|
103
|
-
* - `dispatchSendQuery` (mainloop) — implicit `;`-queries while pipeline
|
|
104
|
-
* is active. Mainloop calls `ps.session.execute('', 0)` so the wrapper
|
|
105
|
-
* fires automatically without mainloop knowing about the var store.
|
|
106
|
-
*
|
|
107
|
-
* The wrapper preserves the original function's `this` binding via `apply`.
|
|
108
|
-
*/
|
|
109
|
-
const wrapSessionForCounters = (session, settings) => {
|
|
110
|
-
const origExecute = session.execute.bind(session);
|
|
111
|
-
session.execute = (name, maxRows) => {
|
|
112
|
-
bumpCounter(settings, "PIPELINE_COMMAND_COUNT", 1);
|
|
113
|
-
return origExecute(name, maxRows);
|
|
114
|
-
};
|
|
115
|
-
return session;
|
|
116
|
-
};
|
|
117
|
-
const errResult = (ctx, message) => {
|
|
118
|
-
ctx.settings.lastErrorResult = { message };
|
|
119
|
-
writeErr(`\\${ctx.cmdName}: ${message}\n`);
|
|
120
|
-
return {
|
|
121
|
-
status: "error",
|
|
122
|
-
errorWritten: true
|
|
123
|
-
};
|
|
124
|
-
};
|
|
125
|
-
/**
|
|
126
|
-
* Coerce any thrown / rejected value into a printable string. The
|
|
127
|
-
* extended-protocol driver in `PgConnection` rejects with raw
|
|
128
|
-
* ConnectError records (`{severity, code, message, detail, ...}`) —
|
|
129
|
-
* not `Error` instances — so `String(err)` would produce
|
|
130
|
-
* `[object Object]` in the conformance output. We probe for a
|
|
131
|
-
* `.message` property (covering both `Error` and the ConnectError
|
|
132
|
-
* shape) and fall back to JSON.stringify only when there's no
|
|
133
|
-
* message field at all.
|
|
134
|
-
*/
|
|
135
|
-
const errorToMessage = (err) => {
|
|
136
|
-
if (err instanceof Error) return err.message;
|
|
137
|
-
if (err !== null && typeof err === "object" && "message" in err && typeof err.message === "string") return err.message;
|
|
138
|
-
try {
|
|
139
|
-
return JSON.stringify(err);
|
|
140
|
-
} catch {
|
|
141
|
-
return String(err);
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
/**
|
|
145
|
-
* Render a pipeline-collected ConnectError to stderr in the upstream
|
|
146
|
-
* shape: a `SEVERITY: message` line, followed by optional `DETAIL:` /
|
|
147
|
-
* `HINT:` / `CONTEXT:` lines (each on its own line). Matches the
|
|
148
|
-
* subset of `formatErrorReport`-style output the conformance corpus
|
|
149
|
-
* expects from `\endpipeline` for non-FATAL pipeline errors. We
|
|
150
|
-
* inline a minimal renderer here rather than importing the full
|
|
151
|
-
* `formatErrorReport` from `cmd_meta` because we always want the
|
|
152
|
-
* "default verbosity, no LINE/caret context" form — pipeline errors
|
|
153
|
-
* arrive after the buffered query has been reset and we don't carry
|
|
154
|
-
* the originating SQL position through `session.lastError`.
|
|
155
|
-
*/
|
|
156
|
-
const renderPipelineError = (err) => {
|
|
157
|
-
if (err === null || typeof err !== "object") {
|
|
158
|
-
writeErr(`ERROR: ${errorToMessage(err)}\n`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
const e = err;
|
|
162
|
-
if (e.pipelineAborted) {
|
|
163
|
-
writeErr(`${e.message ?? "Pipeline aborted, command did not run"}\n`);
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const severity = e.severity ?? "ERROR";
|
|
167
|
-
const message = e.message ?? "";
|
|
168
|
-
writeErr(`${severity}: ${message}\n`);
|
|
169
|
-
if (e.detail) writeErr(`DETAIL: ${e.detail}\n`);
|
|
170
|
-
if (e.hint) writeErr(`HINT: ${e.hint}\n`);
|
|
171
|
-
if (e.where) writeErr(`CONTEXT: ${e.where}\n`);
|
|
172
|
-
};
|
|
173
|
-
const readAllArgs = (ctx) => {
|
|
174
|
-
const out = [];
|
|
175
|
-
for (;;) {
|
|
176
|
-
const arg = ctx.nextArg("normal");
|
|
177
|
-
if (arg === null) break;
|
|
178
|
-
out.push(arg);
|
|
179
|
-
}
|
|
180
|
-
return out;
|
|
181
|
-
};
|
|
182
|
-
const cmdBind = {
|
|
183
|
-
name: "bind",
|
|
184
|
-
helpKey: "bind",
|
|
185
|
-
run(ctx) {
|
|
186
|
-
const values = readAllArgs(ctx);
|
|
187
|
-
stashOf(ctx.settings)[BIND_STATE_KEY] = {
|
|
188
|
-
name: "",
|
|
189
|
-
values,
|
|
190
|
-
byName: false
|
|
191
|
-
};
|
|
192
|
-
return Promise.resolve({ status: "ok" });
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
const cmdBindNamed = {
|
|
196
|
-
name: "bind_named",
|
|
197
|
-
helpKey: "bind_named",
|
|
198
|
-
run(ctx) {
|
|
199
|
-
const name = ctx.nextArg("normal");
|
|
200
|
-
if (name === null) {
|
|
201
|
-
stashOf(ctx.settings)[BIND_STATE_KEY] = void 0;
|
|
202
|
-
return Promise.resolve(errResult(ctx, "missing required argument"));
|
|
203
|
-
}
|
|
204
|
-
const values = readAllArgs(ctx);
|
|
205
|
-
stashOf(ctx.settings)[BIND_STATE_KEY] = {
|
|
206
|
-
name,
|
|
207
|
-
values,
|
|
208
|
-
byName: true
|
|
209
|
-
};
|
|
210
|
-
return Promise.resolve({ status: "ok" });
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
const cmdParse = {
|
|
214
|
-
name: "parse",
|
|
215
|
-
helpKey: "parse",
|
|
216
|
-
async run(ctx) {
|
|
217
|
-
const name = ctx.nextArg("normal");
|
|
218
|
-
if (name === null) return errResult(ctx, "missing required argument");
|
|
219
|
-
const sql = ctx.queryBuf;
|
|
220
|
-
if (sql.trim().length === 0) return errResult(ctx, "no query buffer");
|
|
221
|
-
if (!ctx.settings.db) return errResult(ctx, "no connection to the server");
|
|
222
|
-
const pipelineActive = getPipelineState(ctx.settings);
|
|
223
|
-
if (pipelineActive !== null) try {
|
|
224
|
-
const session = pipelineActive.session;
|
|
225
|
-
if (typeof session.parseSlot === "function") await session.parseSlot(name, sql, []);
|
|
226
|
-
else await session.parse(name, sql, []);
|
|
227
|
-
ctx.settings.lastQuery = sql;
|
|
228
|
-
bumpCounter(ctx.settings, "PIPELINE_COMMAND_COUNT", 1);
|
|
229
|
-
return {
|
|
230
|
-
status: "reset-buf",
|
|
231
|
-
newBuf: ""
|
|
232
|
-
};
|
|
233
|
-
} catch (err) {
|
|
234
|
-
return errResult(ctx, errorToMessage(err));
|
|
235
|
-
}
|
|
236
|
-
try {
|
|
237
|
-
const ps = await ctx.settings.db.prepare(name, sql);
|
|
238
|
-
stashPrepared(ctx.settings, name, ps);
|
|
239
|
-
ctx.settings.lastQuery = sql;
|
|
240
|
-
return {
|
|
241
|
-
status: "reset-buf",
|
|
242
|
-
newBuf: ""
|
|
243
|
-
};
|
|
244
|
-
} catch (err) {
|
|
245
|
-
return errResult(ctx, errorToMessage(err));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
const cmdClosePrepared = {
|
|
250
|
-
name: "close_prepared",
|
|
251
|
-
helpKey: "close_prepared",
|
|
252
|
-
async run(ctx) {
|
|
253
|
-
const name = ctx.nextArg("normal");
|
|
254
|
-
if (name === null) return errResult(ctx, "missing required argument");
|
|
255
|
-
const db = ctx.settings.db;
|
|
256
|
-
if (!db) return errResult(ctx, "no connection to the server");
|
|
257
|
-
const ps = getPipelineState(ctx.settings);
|
|
258
|
-
if (ps !== null) try {
|
|
259
|
-
const session = ps.session;
|
|
260
|
-
if (typeof session.closeSlot === "function") await session.closeSlot(name);
|
|
261
|
-
else await session.close(name);
|
|
262
|
-
bumpCounter(ctx.settings, "PIPELINE_COMMAND_COUNT", 1);
|
|
263
|
-
dropPrepared(ctx.settings, name);
|
|
264
|
-
return { status: "ok" };
|
|
265
|
-
} catch (err) {
|
|
266
|
-
return errResult(ctx, errorToMessage(err));
|
|
267
|
-
}
|
|
268
|
-
try {
|
|
269
|
-
if (db.closePreparedStatement) await db.closePreparedStatement(name);
|
|
270
|
-
else await (await db.prepare(name, "SELECT 1")).close();
|
|
271
|
-
dropPrepared(ctx.settings, name);
|
|
272
|
-
return { status: "ok" };
|
|
273
|
-
} catch (err) {
|
|
274
|
-
return errResult(ctx, errorToMessage(err));
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
const cmdStartPipeline = {
|
|
279
|
-
name: "startpipeline",
|
|
280
|
-
helpKey: "startpipeline",
|
|
281
|
-
run(ctx) {
|
|
282
|
-
if (!ctx.settings.db) return Promise.resolve(errResult(ctx, "no connection to the server"));
|
|
283
|
-
if (getPipelineState(ctx.settings) !== null) return Promise.resolve({ status: "ok" });
|
|
284
|
-
try {
|
|
285
|
-
const session = wrapSessionForCounters(ctx.settings.db.pipeline(), ctx.settings);
|
|
286
|
-
stashOf(ctx.settings)[PIPELINE_KEY] = {
|
|
287
|
-
session,
|
|
288
|
-
pending: [],
|
|
289
|
-
drainedCount: 0
|
|
290
|
-
};
|
|
291
|
-
ctx.settings.sendMode = "extended-pipeline";
|
|
292
|
-
resetPipelineCounters(ctx.settings);
|
|
293
|
-
return Promise.resolve({ status: "ok" });
|
|
294
|
-
} catch (err) {
|
|
295
|
-
return Promise.resolve(errResult(ctx, errorToMessage(err)));
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
const cmdEndPipeline = {
|
|
300
|
-
name: "endpipeline",
|
|
301
|
-
helpKey: "endpipeline",
|
|
302
|
-
async run(ctx) {
|
|
303
|
-
const ps = getPipelineState(ctx.settings);
|
|
304
|
-
if (!ps) {
|
|
305
|
-
ctx.settings.lastErrorResult = { message: "cannot send pipeline when not in pipeline mode" };
|
|
306
|
-
writeErr("cannot send pipeline when not in pipeline mode\n");
|
|
307
|
-
return {
|
|
308
|
-
status: "error",
|
|
309
|
-
errorWritten: true
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
try {
|
|
313
|
-
const alreadyDrained = ps.drainedCount;
|
|
314
|
-
const session = ps.session;
|
|
315
|
-
const cmdSlotsSnapshot = Array.isArray(session.cmdSlots) ? session.cmdSlots.slice() : [];
|
|
316
|
-
const fetchCountActive = (ctx.settings.vars.get("FETCH_COUNT") ?? "0") !== "0";
|
|
317
|
-
const sets = await ps.session.end();
|
|
318
|
-
stashOf(ctx.settings)[PIPELINE_KEY] = void 0;
|
|
319
|
-
ctx.settings.sendMode = "extended-query";
|
|
320
|
-
resetPipelineCounters(ctx.settings);
|
|
321
|
-
clearPipelineGateErrors(ctx.settings);
|
|
322
|
-
const settled = await Promise.allSettled(cmdSlotsSnapshot);
|
|
323
|
-
let errorRendered = false;
|
|
324
|
-
const entries = settled.length > 0 ? settled : sets.map((rs) => ({
|
|
325
|
-
status: "fulfilled",
|
|
326
|
-
value: rs
|
|
327
|
-
}));
|
|
328
|
-
const sliceForError = entries.slice(alreadyDrained);
|
|
329
|
-
const realLastError = (() => {
|
|
330
|
-
for (const r of sliceForError) {
|
|
331
|
-
if (r.status !== "rejected") continue;
|
|
332
|
-
const reason = r.reason;
|
|
333
|
-
if (!(typeof reason === "object" && reason !== null && reason.pipelineAborted === true)) return reason;
|
|
334
|
-
}
|
|
335
|
-
return null;
|
|
336
|
-
})() ?? (() => {
|
|
337
|
-
const le = session.lastError;
|
|
338
|
-
if (le === null || le === void 0) return null;
|
|
339
|
-
if (typeof le === "object" && le.pipelineAborted) return null;
|
|
340
|
-
return le;
|
|
341
|
-
})();
|
|
342
|
-
for (let i = alreadyDrained; i < entries.length; i++) {
|
|
343
|
-
const r = entries[i];
|
|
344
|
-
if (r.status === "fulfilled") {
|
|
345
|
-
const rs = r.value;
|
|
346
|
-
for (const n of rs.notices) {
|
|
347
|
-
let out = `${n.severity}: ${n.message}\n`;
|
|
348
|
-
if (n.detail !== void 0) out += `DETAIL: ${n.detail}\n`;
|
|
349
|
-
if (n.hint !== void 0) out += `HINT: ${n.hint}\n`;
|
|
350
|
-
writeErr(out);
|
|
351
|
-
}
|
|
352
|
-
const isSyncOrPlaceholder = rs.fields.length === 0 && rs.command === "" && rs.rows.length === 0;
|
|
353
|
-
const isCommandOnly = rs.fields.length === 0 && rs.rows.length === 0 && rs.command !== "";
|
|
354
|
-
if (!isSyncOrPlaceholder && !isCommandOnly) if (rs.fields.length === 0 && rs.rows.length > 0) {
|
|
355
|
-
if (!ctx.settings.popt.topt.tuplesOnly) {
|
|
356
|
-
process.stdout.write("--\n");
|
|
357
|
-
process.stdout.write(`(${rs.rows.length} ${rs.rows.length === 1 ? "row" : "rows"})\n\n`);
|
|
358
|
-
}
|
|
359
|
-
} else await alignedPrinter.printQuery(rs, ctx.settings.popt, process.stdout);
|
|
360
|
-
} else if (!errorRendered) {
|
|
361
|
-
const reason = r.reason;
|
|
362
|
-
const isAborted = typeof reason === "object" && reason !== null && reason.pipelineAborted === true;
|
|
363
|
-
if (fetchCountActive) writeErr("fetching results in chunked mode failed\n");
|
|
364
|
-
if (isAborted && realLastError !== null) renderPipelineError(realLastError);
|
|
365
|
-
else if (isAborted) writeErr("Pipeline aborted, command did not run\n");
|
|
366
|
-
else renderPipelineError(reason);
|
|
367
|
-
errorRendered = true;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
if (!errorRendered) {
|
|
371
|
-
const lastErr = session.lastError;
|
|
372
|
-
if (lastErr !== null && lastErr !== void 0) {
|
|
373
|
-
if (fetchCountActive) writeErr("fetching results in chunked mode failed\n");
|
|
374
|
-
renderPipelineError(lastErr);
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return { status: "ok" };
|
|
378
|
-
} catch (err) {
|
|
379
|
-
stashOf(ctx.settings)[PIPELINE_KEY] = void 0;
|
|
380
|
-
ctx.settings.sendMode = "extended-query";
|
|
381
|
-
resetPipelineCounters(ctx.settings);
|
|
382
|
-
clearPipelineGateErrors(ctx.settings);
|
|
383
|
-
return errResult(ctx, errorToMessage(err));
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
};
|
|
387
|
-
const cmdSyncPipeline = {
|
|
388
|
-
name: "syncpipeline",
|
|
389
|
-
helpKey: "syncpipeline",
|
|
390
|
-
async run(ctx) {
|
|
391
|
-
const ps = getPipelineState(ctx.settings);
|
|
392
|
-
if (!ps) return errResult(ctx, "no pipeline active");
|
|
393
|
-
try {
|
|
394
|
-
await ps.session.sync();
|
|
395
|
-
const queued = readCounter(ctx.settings, "PIPELINE_COMMAND_COUNT");
|
|
396
|
-
setCounter(ctx.settings, "PIPELINE_COMMAND_COUNT", 0);
|
|
397
|
-
bumpCounter(ctx.settings, "PIPELINE_RESULT_COUNT", queued);
|
|
398
|
-
bumpCounter(ctx.settings, "PIPELINE_SYNC_COUNT", 1);
|
|
399
|
-
return { status: "ok" };
|
|
400
|
-
} catch (err) {
|
|
401
|
-
return errResult(ctx, errorToMessage(err));
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
};
|
|
405
|
-
const cmdFlushRequest = {
|
|
406
|
-
name: "flushrequest",
|
|
407
|
-
helpKey: "flushrequest",
|
|
408
|
-
async run(ctx) {
|
|
409
|
-
const ps = getPipelineState(ctx.settings);
|
|
410
|
-
if (!ps) return errResult(ctx, "no pipeline active");
|
|
411
|
-
try {
|
|
412
|
-
await ps.session.flush();
|
|
413
|
-
const queued = readCounter(ctx.settings, "PIPELINE_COMMAND_COUNT");
|
|
414
|
-
setCounter(ctx.settings, "PIPELINE_COMMAND_COUNT", 0);
|
|
415
|
-
bumpCounter(ctx.settings, "PIPELINE_RESULT_COUNT", queued);
|
|
416
|
-
return { status: "ok" };
|
|
417
|
-
} catch (err) {
|
|
418
|
-
return errResult(ctx, errorToMessage(err));
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
const cmdFlush = {
|
|
423
|
-
name: "flush",
|
|
424
|
-
helpKey: "flush",
|
|
425
|
-
run(ctx) {
|
|
426
|
-
return cmdFlushRequest.run(ctx);
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
const cmdSendPipeline = {
|
|
430
|
-
name: "sendpipeline",
|
|
431
|
-
helpKey: "sendpipeline",
|
|
432
|
-
async run(ctx) {
|
|
433
|
-
const ps = getPipelineState(ctx.settings);
|
|
434
|
-
if (!ps) {
|
|
435
|
-
consumeBindState(ctx.settings);
|
|
436
|
-
ctx.settings.lastErrorResult = { message: "\\sendpipeline not allowed outside of pipeline mode" };
|
|
437
|
-
writeErr("\\sendpipeline not allowed outside of pipeline mode\n");
|
|
438
|
-
return {
|
|
439
|
-
status: "error",
|
|
440
|
-
errorWritten: true
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
const bind = consumeBindState(ctx.settings);
|
|
444
|
-
if (bind === null) {
|
|
445
|
-
ctx.settings.lastErrorResult = { message: "\\sendpipeline must be used after \\bind or \\bind_named" };
|
|
446
|
-
writeErr("\\sendpipeline must be used after \\bind or \\bind_named\n");
|
|
447
|
-
return {
|
|
448
|
-
status: "error",
|
|
449
|
-
errorWritten: true
|
|
450
|
-
};
|
|
451
|
-
}
|
|
452
|
-
const sql = ctx.queryBuf.trim();
|
|
453
|
-
const stmtName = bind.name;
|
|
454
|
-
const params = bind.values;
|
|
455
|
-
if (!bind.byName && sql.length === 0) return errResult(ctx, "no query buffer");
|
|
456
|
-
try {
|
|
457
|
-
if (!bind.byName) await ps.session.parse("", sql, []);
|
|
458
|
-
await ps.session.bind(stmtName, params);
|
|
459
|
-
const exec = (async () => {
|
|
460
|
-
await ps.session.execute("", 0);
|
|
461
|
-
return {
|
|
462
|
-
command: "",
|
|
463
|
-
rowCount: null,
|
|
464
|
-
oid: null,
|
|
465
|
-
fields: [],
|
|
466
|
-
rows: [],
|
|
467
|
-
notices: []
|
|
468
|
-
};
|
|
469
|
-
})();
|
|
470
|
-
ps.pending.push(exec);
|
|
471
|
-
return {
|
|
472
|
-
status: "reset-buf",
|
|
473
|
-
newBuf: ""
|
|
474
|
-
};
|
|
475
|
-
} catch (err) {
|
|
476
|
-
return errResult(ctx, errorToMessage(err));
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
};
|
|
480
|
-
const cmdGetResults = {
|
|
481
|
-
name: "getresults",
|
|
482
|
-
helpKey: "getresults",
|
|
483
|
-
async run(ctx) {
|
|
484
|
-
const ps = getPipelineState(ctx.settings);
|
|
485
|
-
const arg = ctx.nextArg("normal");
|
|
486
|
-
let requested = null;
|
|
487
|
-
if (arg !== null && arg.length > 0) {
|
|
488
|
-
const parsed = parseInt(arg, 10);
|
|
489
|
-
if (!Number.isFinite(parsed) || parsed < 0) return errResult(ctx, "invalid number of requested results");
|
|
490
|
-
requested = parsed;
|
|
491
|
-
}
|
|
492
|
-
if (!ps) {
|
|
493
|
-
process.stdout.write("No pending results to get\n");
|
|
494
|
-
return { status: "ok" };
|
|
495
|
-
}
|
|
496
|
-
const syncAvailable = readCounter(ctx.settings, "PIPELINE_SYNC_COUNT");
|
|
497
|
-
const resultAvailable = readCounter(ctx.settings, "PIPELINE_RESULT_COUNT");
|
|
498
|
-
const available = syncAvailable + resultAvailable;
|
|
499
|
-
if (available === 0) {
|
|
500
|
-
process.stdout.write("No pending results to get\n");
|
|
501
|
-
return { status: "ok" };
|
|
502
|
-
}
|
|
503
|
-
const n = requested === null || requested === 0 ? available : Math.min(requested, available);
|
|
504
|
-
const session = ps.session;
|
|
505
|
-
const slots = Array.isArray(session.cmdSlots) ? session.cmdSlots : [];
|
|
506
|
-
const start = ps.drainedCount;
|
|
507
|
-
const end = start + n;
|
|
508
|
-
const slice = slots.slice(start, end);
|
|
509
|
-
ps.drainedCount = end;
|
|
510
|
-
ps.pending.splice(0, n);
|
|
511
|
-
try {
|
|
512
|
-
const settled = await Promise.allSettled(slice);
|
|
513
|
-
const sliceErr = (() => {
|
|
514
|
-
for (const r of settled) {
|
|
515
|
-
if (r.status !== "rejected") continue;
|
|
516
|
-
const reason = r.reason;
|
|
517
|
-
if (!(typeof reason === "object" && reason !== null && reason.pipelineAborted === true)) return reason;
|
|
518
|
-
}
|
|
519
|
-
return null;
|
|
520
|
-
})();
|
|
521
|
-
const sessPeek = session;
|
|
522
|
-
const realErr = sliceErr ?? (typeof sessPeek.peekRealError === "function" ? await sessPeek.peekRealError() : null);
|
|
523
|
-
let errorRenderedHere = false;
|
|
524
|
-
let walkedItems = 0;
|
|
525
|
-
let syncsDrained = 0;
|
|
526
|
-
let resultsDrained = 0;
|
|
527
|
-
for (const r of settled) {
|
|
528
|
-
walkedItems++;
|
|
529
|
-
if (r.status !== "fulfilled") {
|
|
530
|
-
resultsDrained++;
|
|
531
|
-
if (!errorRenderedHere) {
|
|
532
|
-
const reason = r.reason;
|
|
533
|
-
if (typeof reason === "object" && reason !== null && reason.pipelineAborted === true && realErr !== null) renderPipelineError(realErr);
|
|
534
|
-
else renderPipelineError(reason);
|
|
535
|
-
errorRenderedHere = true;
|
|
536
|
-
}
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
const rs = r.value;
|
|
540
|
-
for (const n of rs.notices) {
|
|
541
|
-
let out = `${n.severity}: ${n.message}\n`;
|
|
542
|
-
if (n.detail !== void 0) out += `DETAIL: ${n.detail}\n`;
|
|
543
|
-
if (n.hint !== void 0) out += `HINT: ${n.hint}\n`;
|
|
544
|
-
writeErr(out);
|
|
545
|
-
}
|
|
546
|
-
if (rs.fields.length === 0 && rs.command === "" && rs.rows.length === 0) {
|
|
547
|
-
syncsDrained++;
|
|
548
|
-
continue;
|
|
549
|
-
}
|
|
550
|
-
resultsDrained++;
|
|
551
|
-
if (rs.fields.length === 0 && rs.rows.length > 0) {
|
|
552
|
-
if (!ctx.settings.popt.topt.tuplesOnly) {
|
|
553
|
-
process.stdout.write("--\n");
|
|
554
|
-
process.stdout.write(`(${rs.rows.length} ${rs.rows.length === 1 ? "row" : "rows"})\n\n`);
|
|
555
|
-
}
|
|
556
|
-
} else if (rs.fields.length > 0) await alignedPrinter.printQuery(rs, ctx.settings.popt, process.stdout);
|
|
557
|
-
}
|
|
558
|
-
const sessMark = session;
|
|
559
|
-
if (typeof sessMark.markDrained === "function") sessMark.markDrained(end);
|
|
560
|
-
if (errorRenderedHere) {
|
|
561
|
-
const sessAny = session;
|
|
562
|
-
if (typeof sessAny.clearLastError === "function") sessAny.clearLastError();
|
|
563
|
-
}
|
|
564
|
-
if (walkedItems === 0) {
|
|
565
|
-
const ddata = Math.min(n, resultAvailable);
|
|
566
|
-
resultsDrained = ddata;
|
|
567
|
-
syncsDrained = n - ddata;
|
|
568
|
-
} else {
|
|
569
|
-
const actualSyncs = Math.min(syncsDrained, syncAvailable);
|
|
570
|
-
const extraResults = syncsDrained - actualSyncs;
|
|
571
|
-
syncsDrained = actualSyncs;
|
|
572
|
-
resultsDrained += extraResults;
|
|
573
|
-
}
|
|
574
|
-
bumpCounter(ctx.settings, "PIPELINE_SYNC_COUNT", -syncsDrained);
|
|
575
|
-
bumpCounter(ctx.settings, "PIPELINE_RESULT_COUNT", -resultsDrained);
|
|
576
|
-
return { status: "ok" };
|
|
577
|
-
} catch (err) {
|
|
578
|
-
return errResult(ctx, errorToMessage(err));
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
};
|
|
582
|
-
const registerPipelineCommands = (registry) => {
|
|
583
|
-
registry.register(cmdBind);
|
|
584
|
-
registry.register(cmdBindNamed);
|
|
585
|
-
registry.register(cmdParse);
|
|
586
|
-
registry.register(cmdClosePrepared);
|
|
587
|
-
registry.register(cmdStartPipeline);
|
|
588
|
-
registry.register(cmdEndPipeline);
|
|
589
|
-
registry.register(cmdSyncPipeline);
|
|
590
|
-
registry.register(cmdFlushRequest);
|
|
591
|
-
registry.register(cmdFlush);
|
|
592
|
-
registry.register(cmdSendPipeline);
|
|
593
|
-
registry.register(cmdGetResults);
|
|
594
|
-
};
|
|
595
|
-
//#endregion
|
|
1
|
+
import { C as cmdGdesc, _ as stagedNamedBindPresent, a as cmdFlush, c as cmdParse, d as cmdSyncPipeline, f as consumeBindState, g as registerPipelineCommands, h as lookupPrepared, i as cmdEndPipeline, l as cmdSendPipeline, m as getPipelineState, n as cmdBindNamed, o as cmdFlushRequest, p as dropPrepared, r as cmdClosePrepared, s as cmdGetResults, t as cmdBind, u as cmdStartPipeline, v as stashPrepared } from "../../_chunks/cmd_pipeline-CUbBO9U_.js";
|
|
596
2
|
export { cmdBind, cmdBindNamed, cmdClosePrepared, cmdEndPipeline, cmdFlush, cmdFlushRequest, cmdGdesc, cmdGetResults, cmdParse, cmdSendPipeline, cmdStartPipeline, cmdSyncPipeline, consumeBindState, dropPrepared, getPipelineState, lookupPrepared, registerPipelineCommands, stagedNamedBindPresent, stashPrepared };
|
|
@@ -2,9 +2,8 @@ import { writeErr } from "./shared.js";
|
|
|
2
2
|
import { scanSlashArgs } from "../scanner/slash.js";
|
|
3
3
|
import { registerConnectCommands } from "./cmd_connect.js";
|
|
4
4
|
import { cmdCd, cmdCopyright, cmdEcho, cmdEdit, cmdErrverbose, cmdGetenv, cmdHelpSQL, cmdPrompt, cmdQecho, cmdQuit, cmdReset, cmdS, cmdSet, cmdSetenv, cmdShell, cmdSlashHelp, cmdTiming, cmdUnset, cmdWarn } from "./cmd_meta.js";
|
|
5
|
+
import { F as registerIoCommands, g as registerPipelineCommands } from "../../_chunks/cmd_pipeline-CUbBO9U_.js";
|
|
5
6
|
import { cmdA, cmdC, cmdEncoding, cmdF, cmdH, cmdPset, cmdT, cmdTitleAttr, cmdX } from "./cmd_format.js";
|
|
6
|
-
import { registerIoCommands } from "./cmd_io.js";
|
|
7
|
-
import { registerPipelineCommands } from "./cmd_pipeline.js";
|
|
8
7
|
import { registerCopyCommands } from "./cmd_copy.js";
|
|
9
8
|
import { registerDescribeCommands } from "./cmd_describe.js";
|
|
10
9
|
import { registerLargeObjectCommands } from "./cmd_lo.js";
|