deno.land / x / pg_mem@2.8.1 / execution / statement-exec.ts

statement-exec.ts
نووسراو ببینە
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
import { watchUse, ignore, errorMessage, pushExecutionCtx, fromEntries } from '../utils.ts';import { _ISchema, _Transaction, _FunctionDefinition, _ArgDefDetails, _IType, _ISelection, _IStatement, NotSupported, QueryError, nil, OnStatementExecuted, _IStatementExecutor, StatementResult, Parameter, IValue } from '../interfaces-private.ts';import { toSql, Statement } from 'https://deno.land/x/pgsql_ast_parser@12.0.1/mod.ts';import { ExecuteCreateTable } from './schema-amends/create-table.ts';import { ExecuteCreateSequence } from './schema-amends/create-sequence.ts';import { locOf, ExecHelper } from './exec-utils.ts';import { CreateIndexExec } from './schema-amends/create-index.ts';import { Alter } from './schema-amends/alter.ts';import { AlterSequence } from './schema-amends/alter-sequence.ts';import { DropIndex } from './schema-amends/drop-index.ts';import { DropTable } from './schema-amends/drop-table.ts';import { DropSequence } from './schema-amends/drop-sequence.ts';import { CommitExecutor, RollbackExecutor, BeginStatementExec } from './transaction-statements.ts';import { TruncateTable } from './records-mutations/truncate-table.ts';import { ShowExecutor } from './show.ts';import { SetExecutor } from './set.ts';import { CreateEnum } from './schema-amends/create-enum.ts';import { CreateView } from './schema-amends/create-view.ts';import { CreateMaterializedView } from './schema-amends/create-materialized-view.ts';import { CreateSchema } from './schema-amends/create-schema.ts';import { CreateFunction } from './schema-amends/create-function.ts';import { DoStatementExec } from './schema-amends/do.ts';import { SelectExec } from './select.ts';import { withSelection, withStatement, withNameResolver, INameResolver } from '../parser/context.ts';import { DropType } from './schema-amends/drop-type.ts';import { AlterEnum } from './schema-amends/alter-enum.ts';
const detailsIncluded = Symbol('errorDetailsIncluded');
export class SimpleExecutor extends ExecHelper implements _IStatementExecutor { constructor(st: Statement, private exec: (t: _Transaction) => void, private opName?: string) { super(st); } execute(t: _Transaction): StatementResult { this.exec(t); return this.noData(t, this.opName); }}
class MapNameResolver implements INameResolver { constructor(private map: Map<string, any>, readonly isolated: boolean) { } resolve(name: string): IValue | nil { return this.map.get(name); }}
export class StatementExec implements _IStatement { private onExecutedCallbacks: OnStatementExecuted[] = [] private executor?: _IStatementExecutor; private checkAstCoverage?: (() => void);
constructor(readonly schema: _ISchema, private statement: Statement, private pAsSql: string | nil, private parameters?: Parameter[]) { }
onExecuted(callback: OnStatementExecuted): void { this.onExecutedCallbacks.push(callback); }
private get db() { return this.schema.db; }

private _getExecutor(p: Statement): _IStatementExecutor { switch (p.type) { case 'start transaction': case 'begin': return new BeginStatementExec(p); case 'commit': return new CommitExecutor(p); case 'rollback': return new RollbackExecutor(p); case 'select': case 'delete': case 'update': case 'insert': case 'union': case 'union all': case 'values': case 'with recursive': case 'with': return new SelectExec(this, p); case 'truncate table': return new TruncateTable(p); case 'create table': return new ExecuteCreateTable(p); case 'create index': return new CreateIndexExec(this, p); case 'alter table': return new Alter(this, p); case 'create extension': return new SimpleExecutor(p, () => this.schema.executeCreateExtension(p)); case 'create sequence': return new ExecuteCreateSequence(this.schema, p, false); case 'alter sequence': return new AlterSequence(this, p); case 'drop index': return new DropIndex(this, p); case 'drop table': return new DropTable(this, p); case 'drop sequence': return new DropSequence(this, p); case 'drop type': return new DropType(this, p); case 'show': return new ShowExecutor(p); case 'set': case 'set names': case 'set timezone': return new SetExecutor(p); case 'create enum': return new CreateEnum(this, p); case 'alter enum': return new AlterEnum(this,p) case 'create view': return new CreateView(this, p); case 'create materialized view': return new CreateMaterializedView(this, p); case 'create schema': return new CreateSchema(this, p); case 'create function': return new CreateFunction(this, p); case 'drop function': return new SimpleExecutor(p, () => this.schema.dropFunction(p), 'DROP'); case 'do': return new DoStatementExec(this, p); case 'comment': case 'raise': case 'deallocate': ignore(p); return new SimpleExecutor(p, () => { });
case 'refresh materialized view': // todo: a decent materialized view implementation ignore(p); return new SimpleExecutor(p, () => { });
case 'tablespace': throw new NotSupported('"TABLESPACE" statement'); case 'prepare': throw new NotSupported('"PREPARE" statement'); case 'create composite type': throw new NotSupported('create composite type'); case 'drop trigger': throw new NotSupported('"drop trigger" statement'); case 'alter index': throw new NotSupported('"alter index" statement'); default: throw NotSupported.never(p, 'statement type'); } }



compile(): _IStatementExecutor { return this.niceErrors(() => {
if (this.executor) { return this.executor!; } // build the AST coverage checker let p = this.statement; if (!this.db.options.noAstCoverageCheck) { const watched = watchUse(p); p = watched.checked; this.checkAstCoverage = () => { const err = watched.check?.(); if (err) { throw new NotSupported(err); } }; }
// build parameters context const namedParams = fromEntries(this.parameters?.filter(p => !!p.value.id).map(x => [x.value.id!, x]) ?? []); const nameResolver = new MapNameResolver(namedParams, true);

// parse the AST withNameResolver(nameResolver, () => withStatement(this, () => withSelection(this.schema.dualTable.selection, () => this.executor = this._getExecutor(p) ) ) );
return this.executor!; }); }

executeStatement(t: _Transaction): StatementResult { return this.niceErrors(() => pushExecutionCtx({ transaction: t, schema: this.schema, }, () => {
t.clearTransientData();
// actual execution if (!this.executor) { throw new Error('Statement not prepared') } const result = this.executor.execute(t);
// post-execution for (const s of this.onExecutedCallbacks) { s(t); }

// check AST coverage if necessary this.checkAstCoverage?.();

return result; })); }
private niceErrors<T>(act: () => T): T { try { return act(); } catch (e) { // handle reeantrant calls (avoids including error tips twice) if (e && typeof e === 'object' && (e as any)[detailsIncluded]) { throw e; }
// include error tips if (!this.db.options.noErrorDiagnostic && (e instanceof Error) || e instanceof NotSupported) {
// compute SQL const msgs = [e.message];

if (e instanceof QueryError) { msgs.push(`🐜 This seems to be an execution error, which means that your request syntax seems okay, but the resulting statement cannot be executed → Probably not a pg-mem error.`); } else if (e instanceof NotSupported) { msgs.push(`👉 pg-mem is work-in-progress, and it would seem that you've hit one of its limits.`); } else { msgs.push('💥 This is a nasty error, which was unexpected by pg-mem. Also known "a bug" 😁 Please file an issue !') }
if (!this.db.options.noErrorDiagnostic) { if (this.pAsSql) { msgs.push(`*️⃣ Failed SQL statement: ${this.pAsSql}`); } else { try { msgs.push(`*️⃣ Reconsituted failed SQL statement: ${toSql.statement(this.statement)}`); } catch (f) { msgs.push(`*️⃣ <Failed to reconsitute SQL - ${errorMessage(f)}>`); } } } msgs.push('👉 You can file an issue at https://github.com/oguimbal/pg-mem along with a way to reproduce this error (if you can), and the stacktrace:') e.message = msgs.join('\n\n') + '\n\n'; }
// set error location if (e && typeof e === 'object') { (e as any).location = locOf(this.statement); (e as any)[detailsIncluded] = true; } throw e; } }
}
pg_mem

Version Info

Tagged at
4 months ago