rado 0.1.29 → 0.1.30
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/dist/lib/Formatter.d.ts +35 -36
- package/dist/lib/Formatter.js +385 -280
- package/dist/lib/Schema.js +6 -1
- package/dist/lib/Statement.d.ts +19 -32
- package/dist/lib/Statement.js +36 -89
- package/dist/sqlite/SqliteFormatter.d.ts +2 -3
- package/dist/sqlite/SqliteFormatter.js +11 -11
- package/dist/sqlite/SqliteSchema.js +11 -8
- package/package.json +1 -1
package/dist/lib/Formatter.js
CHANGED
|
@@ -4,17 +4,7 @@ import { BinOp, Expr, ExprData, ExprType, UnOp } from "./Expr.js";
|
|
|
4
4
|
import { OrderDirection } from "./OrderBy.js";
|
|
5
5
|
import { ParamType } from "./Param.js";
|
|
6
6
|
import { Query, QueryType } from "./Query.js";
|
|
7
|
-
import {
|
|
8
|
-
Statement,
|
|
9
|
-
call,
|
|
10
|
-
identifier,
|
|
11
|
-
newline,
|
|
12
|
-
param,
|
|
13
|
-
parenthesis,
|
|
14
|
-
raw,
|
|
15
|
-
separated,
|
|
16
|
-
value
|
|
17
|
-
} from "./Statement.js";
|
|
7
|
+
import { Statement } from "./Statement.js";
|
|
18
8
|
import { Target, TargetType } from "./Target.js";
|
|
19
9
|
var binOps = {
|
|
20
10
|
[BinOp.Add]: "+",
|
|
@@ -44,281 +34,386 @@ var joins = {
|
|
|
44
34
|
var Formatter = class {
|
|
45
35
|
constructor() {
|
|
46
36
|
}
|
|
47
|
-
formatAccess(on, field, formatAsJson) {
|
|
48
|
-
return formatAsJson ? this.formatJsonAccess(on, field) : this.formatSqlAccess(on, field);
|
|
49
|
-
}
|
|
50
37
|
compile(query, formatInline = false) {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
const stmt = new Statement();
|
|
39
|
+
const result = this.format(
|
|
40
|
+
{
|
|
41
|
+
stmt,
|
|
42
|
+
formatSubject: (mkSubject) => {
|
|
43
|
+
stmt.raw("json_object('result', ");
|
|
44
|
+
mkSubject();
|
|
45
|
+
stmt.raw(")");
|
|
46
|
+
},
|
|
47
|
+
nameResult: "result"
|
|
48
|
+
},
|
|
49
|
+
query
|
|
50
|
+
).compile(this, formatInline);
|
|
55
51
|
return result;
|
|
56
52
|
}
|
|
57
|
-
format(
|
|
53
|
+
format(ctx, query) {
|
|
58
54
|
switch (query.type) {
|
|
59
55
|
case QueryType.Select:
|
|
60
|
-
return this.formatSelect(
|
|
56
|
+
return this.formatSelect(ctx, query);
|
|
61
57
|
case QueryType.Insert:
|
|
62
|
-
return this.formatInsert(
|
|
58
|
+
return this.formatInsert(ctx, query);
|
|
63
59
|
case QueryType.Update:
|
|
64
|
-
return this.formatUpdate(
|
|
60
|
+
return this.formatUpdate(ctx, query);
|
|
65
61
|
case QueryType.Delete:
|
|
66
|
-
return this.formatDelete(
|
|
62
|
+
return this.formatDelete(ctx, query);
|
|
67
63
|
case QueryType.CreateTable:
|
|
68
|
-
return this.formatCreateTable(
|
|
64
|
+
return this.formatCreateTable(ctx, query);
|
|
69
65
|
case QueryType.CreateIndex:
|
|
70
|
-
return this.formatCreateIndex(
|
|
66
|
+
return this.formatCreateIndex(ctx, query);
|
|
71
67
|
case QueryType.DropIndex:
|
|
72
|
-
return this.formatDropIndex(
|
|
68
|
+
return this.formatDropIndex(ctx, query);
|
|
73
69
|
case QueryType.AlterTable:
|
|
74
|
-
return this.formatAlterTable(
|
|
70
|
+
return this.formatAlterTable(ctx, query);
|
|
75
71
|
case QueryType.Transaction:
|
|
76
|
-
return this.formatTransaction(
|
|
72
|
+
return this.formatTransaction(ctx, query);
|
|
77
73
|
case QueryType.Batch:
|
|
78
|
-
return this.formatBatch(query.queries
|
|
74
|
+
return this.formatBatch(ctx, query.queries);
|
|
79
75
|
case QueryType.Raw:
|
|
80
|
-
return this.formatRaw(
|
|
76
|
+
return this.formatRaw(ctx, query);
|
|
81
77
|
}
|
|
82
78
|
}
|
|
83
|
-
formatSelect(
|
|
84
|
-
|
|
79
|
+
formatSelect(ctx, query) {
|
|
80
|
+
const { stmt } = ctx;
|
|
81
|
+
stmt.add("SELECT").space();
|
|
82
|
+
this.formatSelection(ctx, query.selection);
|
|
83
|
+
stmt.addLine("FROM").space();
|
|
84
|
+
this.formatTarget(ctx, query.from);
|
|
85
|
+
this.formatWhere(ctx, query.where);
|
|
86
|
+
this.formatGroupBy(ctx, query.groupBy);
|
|
87
|
+
this.formatHaving(ctx, query.having);
|
|
88
|
+
this.formatOrderBy(ctx, query.orderBy);
|
|
89
|
+
this.formatLimit(ctx, query);
|
|
90
|
+
return stmt;
|
|
85
91
|
}
|
|
86
|
-
formatInsert(
|
|
92
|
+
formatInsert(ctx, query) {
|
|
93
|
+
const { stmt } = ctx;
|
|
87
94
|
const columns = Object.values(query.into.columns);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
stmt.add("INSERT INTO").addIdentifier(query.into.name);
|
|
96
|
+
if (query.into.alias)
|
|
97
|
+
stmt.raw("AS").addIdentifier(query.into.alias);
|
|
98
|
+
for (const column of stmt.call(columns))
|
|
99
|
+
this.formatString(ctx, column.name);
|
|
100
|
+
stmt.add("VALUES");
|
|
101
|
+
for (const row of stmt.separate(query.data))
|
|
102
|
+
this.formatInsertRow(ctx, query.into.columns, row);
|
|
103
|
+
if (query.selection) {
|
|
104
|
+
stmt.add("RETURNING").space();
|
|
105
|
+
this.formatSelection(ctx, query.selection);
|
|
106
|
+
}
|
|
107
|
+
return stmt;
|
|
96
108
|
}
|
|
97
|
-
formatUpdate(
|
|
109
|
+
formatUpdate(ctx, query) {
|
|
110
|
+
const { stmt } = ctx;
|
|
98
111
|
const data = query.set || {};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
stmt.add("UPDATE").addIdentifier(query.table.name).add("SET").space();
|
|
113
|
+
for (const key of stmt.separate(Object.keys(data))) {
|
|
114
|
+
stmt.identifier(key).add("=").space();
|
|
115
|
+
this.formatExpr(
|
|
116
|
+
{
|
|
117
|
+
...ctx,
|
|
118
|
+
formatAsJson: true
|
|
119
|
+
},
|
|
120
|
+
ExprData.create(data[key])
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
this.formatWhere(ctx, query.where);
|
|
124
|
+
this.formatLimit(ctx, query);
|
|
125
|
+
return stmt;
|
|
126
|
+
}
|
|
127
|
+
formatDelete(ctx, query) {
|
|
128
|
+
const { stmt } = ctx;
|
|
129
|
+
stmt.add("DELETE FROM").addIdentifier(query.table.name);
|
|
130
|
+
stmt.space();
|
|
131
|
+
this.formatWhere(ctx, query.where);
|
|
132
|
+
stmt.space();
|
|
133
|
+
this.formatLimit(ctx, query);
|
|
134
|
+
return stmt;
|
|
122
135
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
formatCreateTable(ctx, query) {
|
|
137
|
+
const { stmt } = ctx;
|
|
138
|
+
stmt.add("CREATE TABLE");
|
|
139
|
+
if (query.ifNotExists)
|
|
140
|
+
stmt.add("IF NOT EXISTS");
|
|
141
|
+
stmt.addIdentifier(query.table.name);
|
|
142
|
+
for (const column of stmt.call(Object.values(query.table.columns))) {
|
|
143
|
+
this.formatColumn(ctx, column);
|
|
144
|
+
}
|
|
145
|
+
return stmt;
|
|
146
|
+
}
|
|
147
|
+
formatCreateIndex(ctx, query) {
|
|
148
|
+
const { stmt } = ctx;
|
|
149
|
+
stmt.add("CREATE");
|
|
150
|
+
if (query.index.unique)
|
|
151
|
+
stmt.add("UNIQUE");
|
|
152
|
+
stmt.add("INDEX");
|
|
153
|
+
if (query.ifNotExists)
|
|
154
|
+
stmt.add("IF NOT EXISTS");
|
|
155
|
+
stmt.addIdentifier(query.index.name).add("ON").addIdentifier(query.table.name);
|
|
156
|
+
for (const expr of stmt.call(query.index.on)) {
|
|
157
|
+
this.formatExprValue(
|
|
158
|
+
{
|
|
159
|
+
...ctx,
|
|
160
|
+
skipTableName: true,
|
|
161
|
+
forceInline: true
|
|
162
|
+
},
|
|
163
|
+
expr
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
this.formatWhere(ctx, query.where);
|
|
167
|
+
return stmt;
|
|
168
|
+
}
|
|
169
|
+
formatDropIndex(ctx, query) {
|
|
170
|
+
const { stmt } = ctx;
|
|
171
|
+
stmt.add("DROP INDEX");
|
|
172
|
+
if (query.ifExists)
|
|
173
|
+
stmt.add("IF EXISTS");
|
|
174
|
+
stmt.addIdentifier(query.name);
|
|
175
|
+
return stmt;
|
|
176
|
+
}
|
|
177
|
+
formatAlterTable(ctx, query) {
|
|
178
|
+
const { stmt } = ctx;
|
|
179
|
+
stmt.add("ALTER TABLE").addIdentifier(query.table.name);
|
|
141
180
|
if (query.addColumn) {
|
|
142
|
-
stmt
|
|
181
|
+
stmt.add("ADD COLUMN");
|
|
182
|
+
this.formatColumn(ctx, query.addColumn);
|
|
143
183
|
} else if (query.dropColumn) {
|
|
144
|
-
stmt
|
|
184
|
+
stmt.add("DROP COLUMN").addIdentifier(query.dropColumn);
|
|
145
185
|
} else if (query.alterColumn) {
|
|
146
186
|
throw new Error(`Not available in this formatter: alter column`);
|
|
147
187
|
}
|
|
148
188
|
return stmt;
|
|
149
189
|
}
|
|
150
|
-
formatTransaction({ op, id }
|
|
190
|
+
formatTransaction(ctx, { op, id }) {
|
|
191
|
+
const { stmt } = ctx;
|
|
151
192
|
switch (op) {
|
|
152
193
|
case Query.TransactionOperation.Begin:
|
|
153
|
-
return raw("SAVEPOINT").addIdentifier(id);
|
|
194
|
+
return stmt.raw("SAVEPOINT").addIdentifier(id);
|
|
154
195
|
case Query.TransactionOperation.Commit:
|
|
155
|
-
return raw("RELEASE").addIdentifier(id);
|
|
196
|
+
return stmt.raw("RELEASE").addIdentifier(id);
|
|
156
197
|
case Query.TransactionOperation.Rollback:
|
|
157
|
-
return raw("ROLLBACK TO").addIdentifier(id);
|
|
198
|
+
return stmt.raw("ROLLBACK TO").addIdentifier(id);
|
|
158
199
|
}
|
|
159
200
|
}
|
|
160
|
-
formatBatch(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
201
|
+
formatBatch(ctx, queries) {
|
|
202
|
+
const { stmt } = ctx;
|
|
203
|
+
for (const query of stmt.separate(queries, ";"))
|
|
204
|
+
this.format(ctx, query);
|
|
205
|
+
return stmt;
|
|
165
206
|
}
|
|
166
|
-
formatRaw({ strings, params }
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
207
|
+
formatRaw(ctx, { strings, params }) {
|
|
208
|
+
const { stmt } = ctx;
|
|
209
|
+
for (let i = 0; i < strings.length; i++) {
|
|
210
|
+
ctx.stmt.raw(strings[i]);
|
|
211
|
+
if (i < params.length) {
|
|
212
|
+
const param = params[i];
|
|
213
|
+
if (param instanceof Expr)
|
|
214
|
+
this.formatExpr(ctx, param.expr);
|
|
215
|
+
else
|
|
216
|
+
this.formatValue(ctx, param);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return stmt;
|
|
175
220
|
}
|
|
176
|
-
formatColumn(column) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
221
|
+
formatColumn(ctx, column) {
|
|
222
|
+
const { stmt } = ctx;
|
|
223
|
+
stmt.identifier(column.name).space();
|
|
224
|
+
this.formatType(ctx, column.type);
|
|
225
|
+
if (column.unique)
|
|
226
|
+
stmt.add("UNIQUE");
|
|
227
|
+
if (column.autoIncrement)
|
|
228
|
+
stmt.add("AUTOINCREMENT");
|
|
229
|
+
if (column.primaryKey)
|
|
230
|
+
stmt.add("PRIMARY KEY");
|
|
231
|
+
if (!column.nullable)
|
|
232
|
+
stmt.add("NOT NULL");
|
|
233
|
+
if (column.defaultValue !== void 0) {
|
|
234
|
+
stmt.add("DEFAULT").space();
|
|
235
|
+
stmt.openParenthesis();
|
|
236
|
+
this.formatExpr(
|
|
237
|
+
{
|
|
238
|
+
...ctx,
|
|
181
239
|
formatAsJson: true,
|
|
182
240
|
forceInline: true
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
241
|
+
},
|
|
242
|
+
column.defaultValue
|
|
243
|
+
);
|
|
244
|
+
stmt.closeParenthesis();
|
|
245
|
+
}
|
|
246
|
+
if (column.references)
|
|
247
|
+
this.formatContraintReference(ctx, column.references);
|
|
248
|
+
return stmt;
|
|
188
249
|
}
|
|
189
|
-
formatContraintReference(reference) {
|
|
250
|
+
formatContraintReference(ctx, reference) {
|
|
251
|
+
const { stmt } = ctx;
|
|
190
252
|
if (reference.type !== ExprType.Field || reference.expr.type !== ExprType.Row)
|
|
191
253
|
throw new Error("not supported");
|
|
192
254
|
const from = reference.expr.target;
|
|
193
|
-
return
|
|
255
|
+
return stmt.add("REFERENCES").addIdentifier(Target.source(from).name).openParenthesis().identifier(reference.field).closeParenthesis();
|
|
194
256
|
}
|
|
195
|
-
formatType(type) {
|
|
257
|
+
formatType(ctx, type) {
|
|
258
|
+
const { stmt } = ctx;
|
|
196
259
|
switch (type) {
|
|
197
260
|
case ColumnType.String:
|
|
198
|
-
return raw("TEXT");
|
|
261
|
+
return stmt.raw("TEXT");
|
|
199
262
|
case ColumnType.Json:
|
|
200
|
-
return raw("JSON");
|
|
263
|
+
return stmt.raw("JSON");
|
|
201
264
|
case ColumnType.Number:
|
|
202
|
-
return raw("NUMERIC");
|
|
265
|
+
return stmt.raw("NUMERIC");
|
|
203
266
|
case ColumnType.Boolean:
|
|
204
|
-
return raw("BOOLEAN");
|
|
267
|
+
return stmt.raw("BOOLEAN");
|
|
205
268
|
case ColumnType.Integer:
|
|
206
|
-
return raw("INTEGER");
|
|
269
|
+
return stmt.raw("INTEGER");
|
|
207
270
|
}
|
|
208
271
|
}
|
|
209
|
-
formatInsertRow(columns, row) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
);
|
|
272
|
+
formatInsertRow(ctx, columns, row) {
|
|
273
|
+
const { stmt } = ctx;
|
|
274
|
+
for (const [property, column] of stmt.call(Object.entries(columns))) {
|
|
275
|
+
const columnValue = row[property];
|
|
276
|
+
this.formatColumnValue(ctx, column, columnValue);
|
|
277
|
+
}
|
|
278
|
+
return stmt;
|
|
218
279
|
}
|
|
219
|
-
formatColumnValue(column, columnValue) {
|
|
280
|
+
formatColumnValue(ctx, column, columnValue) {
|
|
281
|
+
const { stmt } = ctx;
|
|
220
282
|
if (columnValue instanceof Expr)
|
|
221
|
-
return this.formatExprValue(columnValue.expr
|
|
283
|
+
return this.formatExprValue(ctx, columnValue.expr);
|
|
222
284
|
const isNull = columnValue === void 0 || columnValue === null;
|
|
223
285
|
const isOptional = column.nullable || column.autoIncrement || column.primaryKey;
|
|
224
286
|
if (isNull) {
|
|
225
287
|
if (column.defaultValue !== void 0)
|
|
226
|
-
return this.
|
|
288
|
+
return this.formatExprJson(ctx, column.defaultValue);
|
|
227
289
|
if (!isOptional)
|
|
228
290
|
throw new TypeError(`Expected value for column ${column.name}`);
|
|
229
|
-
return raw("NULL");
|
|
291
|
+
return stmt.raw("NULL");
|
|
230
292
|
}
|
|
231
293
|
switch (column.type) {
|
|
232
294
|
case ColumnType.String:
|
|
233
295
|
if (typeof columnValue !== "string")
|
|
234
296
|
throw new TypeError(`Expected string for column ${column.name}`);
|
|
235
|
-
return value(columnValue);
|
|
297
|
+
return stmt.value(columnValue);
|
|
236
298
|
case ColumnType.Integer:
|
|
237
299
|
case ColumnType.Number:
|
|
238
300
|
if (typeof columnValue !== "number")
|
|
239
301
|
throw new TypeError(`Expected number for column ${column.name}`);
|
|
240
|
-
return value(columnValue);
|
|
302
|
+
return stmt.value(columnValue);
|
|
241
303
|
case ColumnType.Boolean:
|
|
242
304
|
if (typeof columnValue !== "boolean")
|
|
243
305
|
throw new TypeError(`Expected boolean for column ${column.name}`);
|
|
244
|
-
return raw(this.escapeValue(columnValue));
|
|
306
|
+
return stmt.raw(this.escapeValue(columnValue));
|
|
245
307
|
case ColumnType.Json:
|
|
246
308
|
if (typeof columnValue !== "object")
|
|
247
309
|
throw new TypeError(`Expected object for column ${column.name}`);
|
|
248
|
-
return value(JSON.stringify(columnValue));
|
|
310
|
+
return stmt.value(JSON.stringify(columnValue));
|
|
249
311
|
}
|
|
250
312
|
}
|
|
251
|
-
formatTarget(
|
|
313
|
+
formatTarget(ctx, target) {
|
|
314
|
+
const { stmt } = ctx;
|
|
252
315
|
switch (target.type) {
|
|
253
316
|
case TargetType.Table:
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
(
|
|
257
|
-
|
|
317
|
+
stmt.identifier(target.table.name);
|
|
318
|
+
if (target.table.alias)
|
|
319
|
+
stmt.add("AS").addIdentifier(target.table.alias);
|
|
320
|
+
return stmt;
|
|
258
321
|
case TargetType.Join:
|
|
259
322
|
const { left, right, joinType } = target;
|
|
260
|
-
|
|
323
|
+
this.formatTarget(ctx, left);
|
|
324
|
+
stmt.addLine(joins[joinType]).add("JOIN");
|
|
325
|
+
this.formatTarget(ctx, right);
|
|
326
|
+
stmt.add("ON");
|
|
327
|
+
this.formatExprValue(ctx, target.on);
|
|
328
|
+
return stmt;
|
|
261
329
|
default:
|
|
262
330
|
throw new Error(`Cannot format target of type ${target.type}`);
|
|
263
331
|
}
|
|
264
332
|
}
|
|
265
|
-
formatWhere(
|
|
333
|
+
formatWhere(ctx, expr) {
|
|
334
|
+
const { stmt } = ctx;
|
|
266
335
|
if (!expr)
|
|
267
|
-
return;
|
|
268
|
-
|
|
336
|
+
return stmt;
|
|
337
|
+
stmt.newline().raw("WHERE");
|
|
338
|
+
this.formatExprValue(ctx, expr);
|
|
339
|
+
return stmt;
|
|
269
340
|
}
|
|
270
|
-
formatHaving(
|
|
341
|
+
formatHaving(ctx, expr) {
|
|
342
|
+
const { stmt } = ctx;
|
|
271
343
|
if (!expr)
|
|
272
|
-
return;
|
|
273
|
-
|
|
344
|
+
return stmt;
|
|
345
|
+
stmt.newline().raw("HAVING");
|
|
346
|
+
this.formatExprValue(ctx, expr);
|
|
347
|
+
return stmt;
|
|
274
348
|
}
|
|
275
|
-
formatGroupBy(
|
|
349
|
+
formatGroupBy(ctx, groupBy) {
|
|
350
|
+
const { stmt } = ctx;
|
|
276
351
|
if (!groupBy)
|
|
277
|
-
return;
|
|
278
|
-
|
|
352
|
+
return stmt;
|
|
353
|
+
stmt.newline().raw("GROUP BY");
|
|
354
|
+
for (const expr of stmt.separate(groupBy))
|
|
355
|
+
this.formatExprValue(ctx, expr);
|
|
356
|
+
return stmt;
|
|
279
357
|
}
|
|
280
|
-
formatOrderBy(
|
|
358
|
+
formatOrderBy(ctx, orderBy) {
|
|
359
|
+
const { stmt } = ctx;
|
|
281
360
|
if (!orderBy)
|
|
282
|
-
return;
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
);
|
|
361
|
+
return stmt;
|
|
362
|
+
stmt.newline().raw("ORDER BY");
|
|
363
|
+
for (const { expr, order } of stmt.separate(orderBy)) {
|
|
364
|
+
this.formatExprValue(ctx, expr);
|
|
365
|
+
stmt.add(order === OrderDirection.Asc ? "ASC" : "DESC");
|
|
366
|
+
}
|
|
367
|
+
return stmt;
|
|
290
368
|
}
|
|
291
|
-
formatLimit({ limit, offset, singleResult }
|
|
369
|
+
formatLimit(ctx, { limit, offset, singleResult }) {
|
|
370
|
+
const { stmt } = ctx;
|
|
292
371
|
if (!limit && !offset && !singleResult)
|
|
293
|
-
return;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
372
|
+
return stmt;
|
|
373
|
+
stmt.newline().raw("LIMIT").addValue(singleResult ? 1 : limit);
|
|
374
|
+
if (offset && offset > 0)
|
|
375
|
+
stmt.raw("OFFSET").addValue(offset);
|
|
376
|
+
return stmt;
|
|
377
|
+
}
|
|
378
|
+
formatSelection(ctx, selection) {
|
|
379
|
+
const { stmt, formatSubject } = ctx;
|
|
380
|
+
const mkSubject = () => this.formatExpr(
|
|
381
|
+
{
|
|
382
|
+
...ctx,
|
|
383
|
+
formatSubject: void 0,
|
|
384
|
+
formatAsJson: true
|
|
385
|
+
},
|
|
386
|
+
selection
|
|
306
387
|
);
|
|
388
|
+
if (formatSubject)
|
|
389
|
+
formatSubject(mkSubject);
|
|
390
|
+
else
|
|
391
|
+
mkSubject();
|
|
392
|
+
if (ctx.nameResult)
|
|
393
|
+
stmt.add("AS").addIdentifier(ctx.nameResult);
|
|
394
|
+
return stmt;
|
|
395
|
+
}
|
|
396
|
+
formatExprJson(ctx, expr) {
|
|
397
|
+
return this.formatExpr({ ...ctx, formatAsJson: true }, expr);
|
|
307
398
|
}
|
|
308
|
-
formatExprValue(
|
|
309
|
-
return this.formatExpr(
|
|
399
|
+
formatExprValue(ctx, expr) {
|
|
400
|
+
return this.formatExpr({ ...ctx, formatAsJson: false }, expr);
|
|
310
401
|
}
|
|
311
|
-
formatIn(
|
|
402
|
+
formatIn(ctx, expr) {
|
|
403
|
+
const { stmt } = ctx;
|
|
312
404
|
switch (expr.type) {
|
|
313
405
|
case ExprType.Field:
|
|
314
|
-
|
|
406
|
+
stmt.openParenthesis();
|
|
407
|
+
stmt.raw("SELECT value FROM json_each");
|
|
408
|
+
stmt.openParenthesis();
|
|
409
|
+
this.formatExprJson(ctx, expr);
|
|
410
|
+
stmt.closeParenthesis();
|
|
411
|
+
stmt.closeParenthesis();
|
|
412
|
+
return stmt;
|
|
315
413
|
default:
|
|
316
|
-
return this.formatExprValue(
|
|
414
|
+
return this.formatExprValue(ctx, expr);
|
|
317
415
|
}
|
|
318
416
|
}
|
|
319
|
-
formatUnwrapArray(stmt) {
|
|
320
|
-
return parenthesis(raw("SELECT value FROM").addCall("json_each", stmt));
|
|
321
|
-
}
|
|
322
417
|
retrieveField(expr, field) {
|
|
323
418
|
switch (expr.type) {
|
|
324
419
|
case ExprType.Record:
|
|
@@ -329,123 +424,140 @@ var Formatter = class {
|
|
|
329
424
|
return void 0;
|
|
330
425
|
}
|
|
331
426
|
}
|
|
332
|
-
formatField(expr, field
|
|
427
|
+
formatField(ctx, expr, field) {
|
|
428
|
+
const { stmt } = ctx;
|
|
333
429
|
const fieldExpr = this.retrieveField(expr, field);
|
|
334
430
|
if (fieldExpr)
|
|
335
|
-
return this.formatExpr(
|
|
431
|
+
return this.formatExpr(ctx, fieldExpr);
|
|
336
432
|
switch (expr.type) {
|
|
337
433
|
case ExprType.Row:
|
|
338
434
|
switch (expr.target.type) {
|
|
339
435
|
case TargetType.Table:
|
|
340
|
-
const selection = ctx.skipTableName ? identifier(field) : identifier(expr.target.table.alias || expr.target.table.name).raw(".").identifier(field);
|
|
341
436
|
const column = expr.target.table.columns[field];
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
default:
|
|
347
|
-
return selection;
|
|
437
|
+
const asJson = column?.type === ColumnType.Json && ctx.formatAsJson;
|
|
438
|
+
if (asJson) {
|
|
439
|
+
stmt.add("json");
|
|
440
|
+
stmt.openParenthesis();
|
|
348
441
|
}
|
|
442
|
+
if (!ctx.skipTableName) {
|
|
443
|
+
stmt.identifier(expr.target.table.alias || expr.target.table.name).raw(".");
|
|
444
|
+
}
|
|
445
|
+
stmt.identifier(field);
|
|
446
|
+
if (asJson)
|
|
447
|
+
stmt.closeParenthesis();
|
|
448
|
+
return stmt;
|
|
349
449
|
}
|
|
350
450
|
default:
|
|
351
|
-
return this.formatAccess(
|
|
352
|
-
this.formatExpr(expr, ctx),
|
|
353
|
-
field,
|
|
354
|
-
ctx.formatAsJson
|
|
355
|
-
);
|
|
451
|
+
return this.formatAccess(ctx, () => this.formatExpr(ctx, expr), field);
|
|
356
452
|
}
|
|
357
453
|
}
|
|
358
|
-
formatString(input) {
|
|
359
|
-
|
|
454
|
+
formatString(ctx, input) {
|
|
455
|
+
const { stmt } = ctx;
|
|
456
|
+
return stmt.raw(this.escapeValue(String(input)));
|
|
360
457
|
}
|
|
361
|
-
formatInlineValue(rawValue) {
|
|
458
|
+
formatInlineValue(ctx, rawValue) {
|
|
459
|
+
const { stmt } = ctx;
|
|
362
460
|
switch (true) {
|
|
363
461
|
case (rawValue === null || rawValue === void 0):
|
|
364
|
-
return raw("NULL");
|
|
462
|
+
return stmt.raw("NULL");
|
|
365
463
|
case typeof rawValue === "boolean":
|
|
366
|
-
return rawValue ? raw("TRUE") : raw("FALSE");
|
|
464
|
+
return rawValue ? stmt.raw("TRUE") : stmt.raw("FALSE");
|
|
367
465
|
case (typeof rawValue === "string" || typeof rawValue === "number"):
|
|
368
|
-
return this.formatString(rawValue);
|
|
466
|
+
return this.formatString(ctx, rawValue);
|
|
369
467
|
default:
|
|
370
|
-
return this.formatString(JSON.stringify(rawValue));
|
|
468
|
+
return this.formatString(ctx, JSON.stringify(rawValue));
|
|
371
469
|
}
|
|
372
470
|
}
|
|
373
|
-
formatValue(
|
|
374
|
-
const { formatAsJson, forceInline } = ctx;
|
|
471
|
+
formatValue(ctx, rawValue) {
|
|
472
|
+
const { stmt, formatAsJson, forceInline } = ctx;
|
|
375
473
|
switch (true) {
|
|
376
474
|
case (rawValue === null || rawValue === void 0):
|
|
377
|
-
return raw("NULL");
|
|
475
|
+
return stmt.raw("NULL");
|
|
378
476
|
case (!formatAsJson && typeof rawValue === "boolean"):
|
|
379
|
-
return rawValue ? raw("1") : raw("0");
|
|
477
|
+
return rawValue ? stmt.raw("1") : stmt.raw("0");
|
|
380
478
|
case Array.isArray(rawValue):
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
)
|
|
387
|
-
)
|
|
388
|
-
|
|
479
|
+
if (formatAsJson) {
|
|
480
|
+
stmt.raw("json_array");
|
|
481
|
+
stmt.openParenthesis();
|
|
482
|
+
}
|
|
483
|
+
for (const v of stmt.separate(rawValue))
|
|
484
|
+
this.formatValue({ ...ctx, formatAsJson: false }, v);
|
|
485
|
+
if (formatAsJson)
|
|
486
|
+
stmt.closeParenthesis();
|
|
487
|
+
return stmt;
|
|
389
488
|
case (typeof rawValue === "string" || typeof rawValue === "number"):
|
|
390
489
|
if (forceInline)
|
|
391
|
-
return raw(this.escapeValue(rawValue));
|
|
392
|
-
return value(rawValue);
|
|
490
|
+
return stmt.raw(this.escapeValue(rawValue));
|
|
491
|
+
return stmt.value(rawValue);
|
|
393
492
|
default:
|
|
394
|
-
|
|
493
|
+
if (formatAsJson) {
|
|
494
|
+
stmt.raw("json");
|
|
495
|
+
stmt.openParenthesis();
|
|
496
|
+
}
|
|
497
|
+
this.formatString(ctx, JSON.stringify(rawValue));
|
|
395
498
|
if (formatAsJson)
|
|
396
|
-
|
|
397
|
-
return
|
|
499
|
+
stmt.closeParenthesis();
|
|
500
|
+
return stmt;
|
|
398
501
|
}
|
|
399
502
|
}
|
|
400
|
-
formatExpr(
|
|
503
|
+
formatExpr(ctx, expr) {
|
|
504
|
+
const { stmt } = ctx;
|
|
401
505
|
switch (expr.type) {
|
|
402
506
|
case ExprType.UnOp:
|
|
403
507
|
switch (expr.op) {
|
|
404
508
|
case UnOp.IsNull:
|
|
405
|
-
return this.formatExprValue(expr.expr
|
|
509
|
+
return this.formatExprValue(ctx, expr.expr).add("IS NULL");
|
|
406
510
|
case UnOp.Not:
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
);
|
|
511
|
+
stmt.raw("NOT").openParenthesis();
|
|
512
|
+
this.formatExprValue(ctx, expr.expr);
|
|
513
|
+
return stmt.closeParenthesis();
|
|
410
514
|
}
|
|
411
515
|
case ExprType.BinOp:
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
)
|
|
416
|
-
|
|
516
|
+
stmt.openParenthesis();
|
|
517
|
+
this.formatExprValue(ctx, expr.a).add(binOps[expr.op]).space();
|
|
518
|
+
if (expr.op === BinOp.In || expr.op === BinOp.NotIn)
|
|
519
|
+
this.formatIn(ctx, expr.b);
|
|
520
|
+
else
|
|
521
|
+
this.formatExprValue(ctx, expr.b);
|
|
522
|
+
return stmt.closeParenthesis();
|
|
417
523
|
case ExprType.Param:
|
|
418
524
|
switch (expr.param.type) {
|
|
419
525
|
case ParamType.Value:
|
|
420
|
-
return this.formatValue(expr.param.value
|
|
526
|
+
return this.formatValue(ctx, expr.param.value);
|
|
421
527
|
case ParamType.Named:
|
|
422
|
-
return param(expr.param.name);
|
|
528
|
+
return stmt.param(expr.param.name);
|
|
423
529
|
}
|
|
424
530
|
case ExprType.Field:
|
|
425
|
-
return this.formatField(expr.expr, expr.field
|
|
531
|
+
return this.formatField(ctx, expr.expr, expr.field);
|
|
426
532
|
case ExprType.Call: {
|
|
427
533
|
if (expr.method === "cast") {
|
|
428
534
|
const [e, type] = expr.params;
|
|
429
535
|
const typeName = type.type === ExprType.Param && type.param.type === ParamType.Value && type.param.value;
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
);
|
|
536
|
+
stmt.raw("cast").openParenthesis();
|
|
537
|
+
this.formatExprValue(ctx, e).add("as").space();
|
|
538
|
+
this.formatString(ctx, typeName);
|
|
539
|
+
return stmt.closeParenthesis();
|
|
433
540
|
} else {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return
|
|
541
|
+
stmt.addIdentifier(expr.method).openParenthesis();
|
|
542
|
+
for (const param of stmt.separate(expr.params))
|
|
543
|
+
this.formatExprValue(ctx, param);
|
|
544
|
+
return stmt.closeParenthesis();
|
|
438
545
|
}
|
|
439
546
|
}
|
|
440
547
|
case ExprType.Query:
|
|
441
|
-
if (!ctx.formatAsJson)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
raw("
|
|
448
|
-
|
|
548
|
+
if (!ctx.formatAsJson) {
|
|
549
|
+
stmt.openParenthesis();
|
|
550
|
+
this.format(ctx, expr.query);
|
|
551
|
+
return stmt.closeParenthesis();
|
|
552
|
+
}
|
|
553
|
+
if (expr.query.singleResult) {
|
|
554
|
+
stmt.raw("json").openParenthesis().openParenthesis();
|
|
555
|
+
this.format({ ...ctx, nameResult: "result" }, expr.query);
|
|
556
|
+
return stmt.closeParenthesis().closeParenthesis();
|
|
557
|
+
}
|
|
558
|
+
stmt.openParenthesis().raw("SELECT json_group_array(json(result))").newline().raw("FROM").openParenthesis();
|
|
559
|
+
this.format({ ...ctx, nameResult: "result" }, expr.query);
|
|
560
|
+
return stmt.closeParenthesis().closeParenthesis();
|
|
449
561
|
case ExprType.Row:
|
|
450
562
|
switch (expr.target.type) {
|
|
451
563
|
case TargetType.Table:
|
|
@@ -453,6 +565,7 @@ var Formatter = class {
|
|
|
453
565
|
if (!table)
|
|
454
566
|
throw new Error(`Cannot select empty target`);
|
|
455
567
|
return this.formatExpr(
|
|
568
|
+
ctx,
|
|
456
569
|
ExprData.Record(
|
|
457
570
|
Object.fromEntries(
|
|
458
571
|
Object.entries(table.columns).map(([key, column]) => [
|
|
@@ -460,39 +573,35 @@ var Formatter = class {
|
|
|
460
573
|
ExprData.Field(ExprData.Row(expr.target), column.name)
|
|
461
574
|
])
|
|
462
575
|
)
|
|
463
|
-
)
|
|
464
|
-
ctx
|
|
576
|
+
)
|
|
465
577
|
);
|
|
466
578
|
case TargetType.Each:
|
|
467
|
-
return identifier(expr.target.alias).raw(".value");
|
|
579
|
+
return stmt.identifier(expr.target.alias).raw(".value");
|
|
468
580
|
default:
|
|
469
581
|
throw new Error(`Cannot select from ${expr.target.type}`);
|
|
470
582
|
}
|
|
471
583
|
case ExprType.Merge:
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
);
|
|
584
|
+
stmt.identifier("json_patch").openParenthesis();
|
|
585
|
+
this.formatExpr({ ...ctx, formatAsJson: true }, expr.a);
|
|
586
|
+
stmt.raw(", ");
|
|
587
|
+
this.formatExpr({ ...ctx, formatAsJson: true }, expr.b);
|
|
588
|
+
return stmt.closeParenthesis();
|
|
477
589
|
case ExprType.Record:
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
590
|
+
stmt.identifier("json_object");
|
|
591
|
+
for (const [key, value] of stmt.call(Object.entries(expr.fields))) {
|
|
592
|
+
this.formatString(ctx, key).raw(", ");
|
|
593
|
+
this.formatExprJson(ctx, value);
|
|
594
|
+
}
|
|
595
|
+
return stmt;
|
|
484
596
|
case ExprType.Filter: {
|
|
485
597
|
const { target, condition } = expr;
|
|
486
598
|
switch (target.type) {
|
|
487
599
|
case TargetType.Each:
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
).add("AS").addIdentifier(target.alias).add("WHERE").add(this.formatExprValue(condition, ctx))
|
|
494
|
-
)
|
|
495
|
-
);
|
|
600
|
+
stmt.openParenthesis().raw("SELECT json_group_array(json(result)) FROM ").openParenthesis().raw("SELECT value AS result").add("FROM json_each").openParenthesis();
|
|
601
|
+
this.formatExpr(ctx, target.expr);
|
|
602
|
+
stmt.closeParenthesis().add("AS").addIdentifier(target.alias).add("WHERE").space();
|
|
603
|
+
this.formatExprValue(ctx, condition);
|
|
604
|
+
return stmt.closeParenthesis().closeParenthesis();
|
|
496
605
|
default:
|
|
497
606
|
throw new Error("todo");
|
|
498
607
|
}
|
|
@@ -501,14 +610,10 @@ var Formatter = class {
|
|
|
501
610
|
const { target, result } = expr;
|
|
502
611
|
switch (target.type) {
|
|
503
612
|
case TargetType.Each:
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
this.formatExpr(target.expr, { ...ctx, formatAsJson: true })
|
|
509
|
-
).add("AS").addIdentifier(target.alias)
|
|
510
|
-
)
|
|
511
|
-
);
|
|
613
|
+
stmt.openParenthesis().raw("SELECT json_group_array(json(result)) FROM ").openParenthesis().raw("SELECT").space();
|
|
614
|
+
this.formatExprJson(ctx, result).add("AS result").add("FROM json_each").openParenthesis();
|
|
615
|
+
this.formatExprJson(ctx, target.expr);
|
|
616
|
+
return stmt.closeParenthesis().add("AS").addIdentifier(target.alias).closeParenthesis().closeParenthesis();
|
|
512
617
|
default:
|
|
513
618
|
throw new Error("todo");
|
|
514
619
|
}
|