rado 0.4.4 → 0.4.6

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.
Files changed (89) hide show
  1. package/dist/define/CTE.d.ts +2 -0
  2. package/dist/define/CTE.js +51 -0
  3. package/dist/define/Cursor.d.ts +108 -0
  4. package/dist/define/Cursor.js +338 -0
  5. package/dist/define/Update.d.ts +4 -0
  6. package/dist/define/Update.js +0 -0
  7. package/dist/define/query/Batch.d.ts +7 -0
  8. package/dist/define/query/Batch.js +17 -0
  9. package/dist/define/query/CreateTable.d.ts +6 -0
  10. package/dist/define/query/CreateTable.js +11 -0
  11. package/dist/define/query/Delete.d.ts +11 -0
  12. package/dist/define/query/Delete.js +18 -0
  13. package/dist/define/query/Insert.d.ts +22 -0
  14. package/dist/define/query/Insert.js +47 -0
  15. package/dist/define/query/Select.d.ts +39 -0
  16. package/dist/define/query/Select.js +170 -0
  17. package/dist/define/query/TableSelect.d.ts +28 -0
  18. package/dist/define/query/TableSelect.js +79 -0
  19. package/dist/define/query/Union.d.ts +17 -0
  20. package/dist/define/query/Union.js +116 -0
  21. package/dist/define/query/Update.d.ts +12 -0
  22. package/dist/define/query/Update.js +18 -0
  23. package/dist/deno/driver/better-sqlite3.js +57 -0
  24. package/dist/deno/driver/bun-sqlite.js +69 -0
  25. package/dist/deno/driver/sql.js.js +72 -0
  26. package/dist/deno/driver/sqlite3.js +123 -0
  27. package/dist/deno/index.js +14 -0
  28. package/dist/deno/lib/Driver.js +330 -0
  29. package/dist/deno/lib/Formatter.js +715 -0
  30. package/dist/deno/lib/Sanitizer.js +0 -0
  31. package/dist/deno/lib/SqlError.js +11 -0
  32. package/dist/deno/lib/Statement.js +108 -0
  33. package/dist/deno/sqlite/SqliteFormatter.js +70 -0
  34. package/dist/deno/sqlite/SqliteFunctions.js +150 -0
  35. package/dist/deno/sqlite/SqliteSchema.js +47 -0
  36. package/dist/deno/sqlite.js +3 -0
  37. package/dist/deno/util/Callable.js +15 -0
  38. package/dist/driver/d1.d.ts +4 -1
  39. package/dist/driver/d1.js +4 -2
  40. package/dist/driver/sqlite3.d.ts +4 -1
  41. package/dist/driver/sqlite3.js +4 -2
  42. package/dist/lib/Driver.d.ts +8 -2
  43. package/dist/lib/Driver.js +7 -4
  44. package/dist/sqlite/index.d.ts +2 -0
  45. package/dist/sqlite/index.js +3 -0
  46. package/dist/src/driver/better-sqlite3.js +49 -0
  47. package/dist/src/driver/sql.js.js +66 -0
  48. package/dist/src/driver/sqlite3.js +87 -0
  49. package/dist/src/index.js +24 -0
  50. package/dist/src/lib/Column.js +63 -0
  51. package/dist/src/lib/Cursor.js +231 -0
  52. package/dist/src/lib/Driver.js +316 -0
  53. package/dist/src/lib/Expr.js +284 -0
  54. package/dist/src/lib/Fields.js +0 -0
  55. package/dist/src/lib/Formatter.js +625 -0
  56. package/dist/src/lib/Functions.js +11 -0
  57. package/dist/src/lib/Id.js +0 -0
  58. package/dist/src/lib/Index.js +20 -0
  59. package/dist/src/lib/Ops.js +45 -0
  60. package/dist/src/lib/OrderBy.js +9 -0
  61. package/dist/src/lib/Param.js +27 -0
  62. package/dist/src/lib/Query.js +74 -0
  63. package/dist/src/lib/Sanitizer.js +0 -0
  64. package/dist/src/lib/Schema.js +67 -0
  65. package/dist/src/lib/Selection.js +7 -0
  66. package/dist/src/lib/Statement.js +103 -0
  67. package/dist/src/lib/Table.js +130 -0
  68. package/dist/src/lib/Target.js +37 -0
  69. package/dist/src/lib/Update.js +0 -0
  70. package/dist/src/sqlite/SqliteFormatter.js +67 -0
  71. package/dist/src/sqlite/SqliteFunctions.js +146 -0
  72. package/dist/src/sqlite/SqliteSchema.js +47 -0
  73. package/dist/src/sqlite.js +3 -0
  74. package/dist/test/DbSuite.js +28 -0
  75. package/dist/test/TSTestTypes.js +6 -0
  76. package/dist/test/TestBasic.js +172 -0
  77. package/dist/test/TestExtend.js +68 -0
  78. package/dist/test/TestFts5.js +34 -0
  79. package/dist/test/TestFunctions.js +28 -0
  80. package/dist/test/TestJoins.js +34 -0
  81. package/dist/test/TestJson.js +33 -0
  82. package/dist/test/TestPrepare.js +27 -0
  83. package/dist/test/TestRawSql.js +31 -0
  84. package/dist/test/TestSchema.js +69 -0
  85. package/dist/test/TestSubQueries.js +79 -0
  86. package/dist/test/TestTransaction.js +54 -0
  87. package/dist/test/TestUpdate.js +95 -0
  88. package/dist/test/index.js +14 -0
  89. package/package.json +1 -1
@@ -0,0 +1,715 @@
1
+ // src/lib/Formatter.ts
2
+ import { ColumnType } from "../define/Column.ts";
3
+ import { BinOpType, Expr, ExprData, ExprType, UnOpType } from "../define/Expr.ts";
4
+ import { OrderDirection } from "../define/OrderBy.ts";
5
+ import { ParamType } from "../define/Param.ts";
6
+ import { Query, QueryType } from "../define/Query.ts";
7
+ import { Target, TargetType } from "../define/Target.ts";
8
+ import { Statement } from "./Statement.ts";
9
+ var binOps = {
10
+ [BinOpType.Add]: "+",
11
+ [BinOpType.Subt]: "-",
12
+ [BinOpType.Mult]: "*",
13
+ [BinOpType.Mod]: "%",
14
+ [BinOpType.Div]: "/",
15
+ [BinOpType.Greater]: ">",
16
+ [BinOpType.GreaterOrEqual]: ">=",
17
+ [BinOpType.Less]: "<",
18
+ [BinOpType.LessOrEqual]: "<=",
19
+ [BinOpType.Equals]: "=",
20
+ [BinOpType.NotEquals]: "!=",
21
+ [BinOpType.And]: "AND",
22
+ [BinOpType.Or]: "OR",
23
+ [BinOpType.Like]: "LIKE",
24
+ [BinOpType.Glob]: "GLOB",
25
+ [BinOpType.Match]: "MATCH",
26
+ [BinOpType.In]: "IN",
27
+ [BinOpType.NotIn]: "NOT IN",
28
+ [BinOpType.Concat]: "||"
29
+ };
30
+ var joins = {
31
+ left: "LEFT",
32
+ inner: "INNER"
33
+ };
34
+ function formatAsResultObject(stmt, mkSubject) {
35
+ stmt.raw("json_object('result', ");
36
+ mkSubject();
37
+ stmt.raw(")");
38
+ }
39
+ var Formatter = class {
40
+ constructor() {
41
+ }
42
+ compile(query, options) {
43
+ const result = this.format(
44
+ this.createContext({ topLevel: true, ...options }),
45
+ query
46
+ );
47
+ return result;
48
+ }
49
+ createContext(options) {
50
+ return { stmt: new Statement(this, options), ...options };
51
+ }
52
+ format(ctx, query) {
53
+ switch (query.type) {
54
+ case QueryType.Select:
55
+ return this.formatSelect(ctx, query);
56
+ case QueryType.Insert:
57
+ return this.formatInsert(ctx, query);
58
+ case QueryType.Update:
59
+ return this.formatUpdate(ctx, query);
60
+ case QueryType.Delete:
61
+ return this.formatDelete(ctx, query);
62
+ case QueryType.CreateTable:
63
+ return this.formatCreateTable(ctx, query);
64
+ case QueryType.AlterTable:
65
+ return this.formatAlterTable(ctx, query);
66
+ case QueryType.DropTable:
67
+ return this.formatDropTable(ctx, query);
68
+ case QueryType.CreateIndex:
69
+ return this.formatCreateIndex(ctx, query);
70
+ case QueryType.DropIndex:
71
+ return this.formatDropIndex(ctx, query);
72
+ case QueryType.Transaction:
73
+ return this.formatTransaction(ctx, query);
74
+ case QueryType.Batch:
75
+ return this.formatBatch(ctx, query);
76
+ case QueryType.Raw:
77
+ return this.formatRaw(ctx, query);
78
+ }
79
+ }
80
+ formatSelect({ topLevel, ...ctx }, query) {
81
+ const { stmt } = ctx;
82
+ stmt.raw("SELECT").space();
83
+ this.formatSelection(
84
+ ctx,
85
+ query.selection,
86
+ topLevel ? formatAsResultObject : void 0
87
+ );
88
+ if (query.from) {
89
+ stmt.addLine("FROM").space();
90
+ this.formatTarget(ctx, query.from);
91
+ }
92
+ this.formatWhere(ctx, query.where);
93
+ this.formatGroupBy(ctx, query.groupBy);
94
+ this.formatHaving(ctx, query.having);
95
+ this.formatOrderBy(ctx, query.orderBy);
96
+ this.formatLimit(ctx, query);
97
+ return stmt;
98
+ }
99
+ formatInsert(ctx, query) {
100
+ const { stmt } = ctx;
101
+ const columns = Object.values(query.into.columns).map((c) => c.name);
102
+ stmt.add("INSERT INTO").addIdentifier(query.into.name);
103
+ if (query.into.alias)
104
+ stmt.raw("AS").addIdentifier(query.into.alias);
105
+ for (const column of stmt.call(columns))
106
+ this.formatString(ctx, column);
107
+ if (query.data) {
108
+ stmt.add("VALUES").space();
109
+ for (const row of stmt.separate(query.data))
110
+ this.formatInsertRow(ctx, query.into.columns, row);
111
+ }
112
+ if (query.select) {
113
+ stmt.space();
114
+ this.formatSelect(
115
+ {
116
+ ...ctx,
117
+ topLevel: false,
118
+ selectAsColumns: true
119
+ },
120
+ query.select
121
+ );
122
+ }
123
+ if (query.selection) {
124
+ stmt.add("RETURNING").space();
125
+ this.formatSelection(ctx, query.selection, formatAsResultObject);
126
+ }
127
+ return stmt;
128
+ }
129
+ formatUpdate(ctx, query) {
130
+ const { stmt } = ctx;
131
+ const data = query.set || {};
132
+ stmt.add("UPDATE").addIdentifier(query.table.name).add("SET").space();
133
+ const keys = Object.keys(data).filter((key) => query.table.columns[key]);
134
+ for (const key of stmt.separate(keys)) {
135
+ stmt.identifier(key).add("=").space();
136
+ const value = data[key];
137
+ if (Expr.isExpr(value))
138
+ this.formatExprJson(ctx, ExprData.create(data[key]));
139
+ else
140
+ this.formatValue({ ...ctx, formatAsInsert: true }, value);
141
+ }
142
+ this.formatWhere(ctx, query.where);
143
+ this.formatLimit(ctx, query);
144
+ return stmt;
145
+ }
146
+ formatDelete(ctx, query) {
147
+ const { stmt } = ctx;
148
+ stmt.add("DELETE FROM").addIdentifier(query.table.name);
149
+ stmt.space();
150
+ this.formatWhere(ctx, query.where);
151
+ stmt.space();
152
+ this.formatLimit(ctx, query);
153
+ return stmt;
154
+ }
155
+ formatCreateTable(ctx, query) {
156
+ const { stmt } = ctx;
157
+ stmt.add("CREATE TABLE");
158
+ if (query.ifNotExists)
159
+ stmt.add("IF NOT EXISTS");
160
+ stmt.addIdentifier(query.table.name);
161
+ for (const column of stmt.call(Object.values(query.table.columns))) {
162
+ this.formatColumn(ctx, column);
163
+ }
164
+ return stmt;
165
+ }
166
+ formatCreateIndex(ctx, query) {
167
+ const { stmt } = ctx;
168
+ stmt.add("CREATE");
169
+ if (query.index.unique)
170
+ stmt.add("UNIQUE");
171
+ stmt.add("INDEX");
172
+ if (query.ifNotExists)
173
+ stmt.add("IF NOT EXISTS");
174
+ stmt.addIdentifier(query.index.name).add("ON").addIdentifier(query.table.name);
175
+ for (const expr of stmt.call(query.index.on)) {
176
+ this.formatExprValue(
177
+ {
178
+ ...ctx,
179
+ skipTableName: true,
180
+ forceInline: true
181
+ },
182
+ expr
183
+ );
184
+ }
185
+ this.formatWhere(ctx, query.where);
186
+ return stmt;
187
+ }
188
+ formatDropIndex(ctx, query) {
189
+ const { stmt } = ctx;
190
+ stmt.add("DROP INDEX");
191
+ if (query.ifExists)
192
+ stmt.add("IF EXISTS");
193
+ stmt.addIdentifier(query.name);
194
+ return stmt;
195
+ }
196
+ formatAlterTable(ctx, query) {
197
+ const { stmt } = ctx;
198
+ stmt.add("ALTER TABLE").addIdentifier(
199
+ query.renameTable ? query.renameTable.from : query.table.name
200
+ );
201
+ if (query.addColumn) {
202
+ stmt.add("ADD COLUMN").space();
203
+ this.formatColumn(ctx, query.addColumn);
204
+ } else if (query.dropColumn) {
205
+ stmt.add("DROP COLUMN").addIdentifier(query.dropColumn);
206
+ } else if (query.renameColumn) {
207
+ stmt.add("RENAME COLUMN");
208
+ stmt.addIdentifier(query.renameColumn.from).add("TO");
209
+ stmt.addIdentifier(query.renameColumn.to);
210
+ } else if (query.renameTable) {
211
+ stmt.add("RENAME TO").addIdentifier(query.table.name);
212
+ } else if (query.alterColumn) {
213
+ throw new Error(`Not available in this formatter: alter column`);
214
+ }
215
+ return stmt;
216
+ }
217
+ formatDropTable(ctx, query) {
218
+ const { stmt } = ctx;
219
+ stmt.add("DROP TABLE");
220
+ if (query.ifExists)
221
+ stmt.add("IF EXISTS");
222
+ stmt.addIdentifier(query.table.name);
223
+ return stmt;
224
+ }
225
+ formatTransaction(ctx, { op, id }) {
226
+ const { stmt } = ctx;
227
+ switch (op) {
228
+ case Query.TransactionOperation.Begin:
229
+ return stmt.raw("SAVEPOINT").addIdentifier(id);
230
+ case Query.TransactionOperation.Commit:
231
+ return stmt.raw("RELEASE").addIdentifier(id);
232
+ case Query.TransactionOperation.Rollback:
233
+ return stmt.raw("ROLLBACK TO").addIdentifier(id);
234
+ }
235
+ }
236
+ formatBatch(ctx, { queries }) {
237
+ const { stmt } = ctx;
238
+ for (const query of stmt.separate(queries, ";"))
239
+ this.format(ctx, query);
240
+ return stmt;
241
+ }
242
+ formatRaw(ctx, { strings, params }) {
243
+ const { stmt } = ctx;
244
+ for (let i = 0; i < strings.length; i++) {
245
+ ctx.stmt.raw(strings[i]);
246
+ if (i < params.length) {
247
+ const param = params[i];
248
+ if (Expr.isExpr(param))
249
+ this.formatExpr(ctx, param[Expr.Data]);
250
+ else
251
+ this.formatValue(ctx, param);
252
+ }
253
+ }
254
+ return stmt;
255
+ }
256
+ formatColumn(ctx, column) {
257
+ const { stmt } = ctx;
258
+ stmt.identifier(column.name).space();
259
+ this.formatType(ctx, column.type);
260
+ if (column.unique)
261
+ stmt.add("UNIQUE");
262
+ if (column.autoIncrement)
263
+ stmt.add("AUTOINCREMENT");
264
+ if (column.primaryKey)
265
+ stmt.add("PRIMARY KEY");
266
+ if (!column.nullable)
267
+ stmt.add("NOT NULL");
268
+ if (column.defaultValue !== void 0) {
269
+ if (typeof column.defaultValue !== "function") {
270
+ stmt.add("DEFAULT").space();
271
+ stmt.openParenthesis();
272
+ this.formatExpr(
273
+ {
274
+ ...ctx,
275
+ formatAsInsert: true,
276
+ forceInline: true
277
+ },
278
+ column.defaultValue
279
+ );
280
+ stmt.closeParenthesis();
281
+ }
282
+ }
283
+ if (column.references)
284
+ this.formatContraintReference(ctx, column.references());
285
+ return stmt;
286
+ }
287
+ formatContraintReference(ctx, reference) {
288
+ const { stmt } = ctx;
289
+ if (reference.type !== ExprType.Field || reference.expr.type !== ExprType.Row)
290
+ throw new Error("not supported");
291
+ const from = reference.expr.target;
292
+ return stmt.add("REFERENCES").addIdentifier(Target.source(from).name).openParenthesis().identifier(reference.field).closeParenthesis();
293
+ }
294
+ formatType(ctx, type) {
295
+ const { stmt } = ctx;
296
+ switch (type) {
297
+ case ColumnType.String:
298
+ return stmt.raw("TEXT");
299
+ case ColumnType.Json:
300
+ return stmt.raw("JSON");
301
+ case ColumnType.Number:
302
+ return stmt.raw("NUMERIC");
303
+ case ColumnType.Boolean:
304
+ return stmt.raw("BOOLEAN");
305
+ case ColumnType.Integer:
306
+ return stmt.raw("INTEGER");
307
+ }
308
+ }
309
+ formatInsertRow(ctx, columns, row) {
310
+ const { stmt } = ctx;
311
+ for (const [property, column] of stmt.call(Object.entries(columns))) {
312
+ const columnValue = row[property];
313
+ this.formatColumnValue(ctx, column, columnValue);
314
+ }
315
+ return stmt;
316
+ }
317
+ formatColumnValue(ctx, column, columnValue) {
318
+ const { stmt } = ctx;
319
+ if (Expr.isExpr(columnValue))
320
+ return this.formatExprValue(ctx, columnValue[Expr.Data]);
321
+ const isNull = columnValue === void 0 || columnValue === null;
322
+ const isOptional = column.nullable || column.autoIncrement || column.primaryKey;
323
+ if (isNull) {
324
+ if (column.defaultValue !== void 0) {
325
+ if (typeof column.defaultValue === "function")
326
+ return this.formatExprJson(
327
+ { ...ctx, formatAsInsert: true },
328
+ column.defaultValue()
329
+ );
330
+ return this.formatExprJson(
331
+ { ...ctx, formatAsInsert: true },
332
+ column.defaultValue
333
+ );
334
+ }
335
+ if (!isOptional)
336
+ throw new TypeError(`Expected value for column ${column.name}`);
337
+ return stmt.raw("NULL");
338
+ }
339
+ switch (column.type) {
340
+ case ColumnType.String:
341
+ if (typeof columnValue !== "string")
342
+ throw new TypeError(`Expected string for column ${column.name}`);
343
+ return stmt.value(columnValue);
344
+ case ColumnType.Integer:
345
+ case ColumnType.Number:
346
+ if (typeof columnValue !== "number")
347
+ throw new TypeError(`Expected number for column ${column.name}`);
348
+ return stmt.value(columnValue);
349
+ case ColumnType.Boolean:
350
+ if (typeof columnValue !== "boolean")
351
+ throw new TypeError(`Expected boolean for column ${column.name}`);
352
+ return stmt.raw(this.escapeValue(columnValue));
353
+ case ColumnType.Json:
354
+ return stmt.value(JSON.stringify(columnValue));
355
+ }
356
+ }
357
+ formatTarget(ctx, target) {
358
+ const { stmt } = ctx;
359
+ switch (target.type) {
360
+ case TargetType.Table:
361
+ stmt.identifier(target.table.name);
362
+ if (target.table.alias)
363
+ stmt.add("AS").addIdentifier(target.table.alias);
364
+ return stmt;
365
+ case TargetType.Join:
366
+ const { left, right, joinType } = target;
367
+ this.formatTarget(ctx, left);
368
+ stmt.addLine(joins[joinType]).add("JOIN").space();
369
+ this.formatTarget(ctx, right);
370
+ stmt.add("ON").space();
371
+ this.formatExprValue(ctx, target.on);
372
+ return stmt;
373
+ case TargetType.Query:
374
+ stmt.openParenthesis();
375
+ this.format(ctx, target.query);
376
+ stmt.closeParenthesis();
377
+ if (target.alias)
378
+ stmt.add("AS").addIdentifier(target.alias);
379
+ return stmt;
380
+ case TargetType.Expr:
381
+ throw new Error("Cannot format expression as target");
382
+ }
383
+ }
384
+ formatWhere({ topLevel, ...ctx }, expr) {
385
+ const { stmt } = ctx;
386
+ if (!expr)
387
+ return stmt;
388
+ stmt.newline().raw("WHERE").space();
389
+ this.formatExprValue(ctx, expr);
390
+ return stmt;
391
+ }
392
+ formatHaving({ topLevel, ...ctx }, expr) {
393
+ const { stmt } = ctx;
394
+ if (!expr)
395
+ return stmt;
396
+ stmt.newline().raw("HAVING");
397
+ this.formatExprValue(ctx, expr);
398
+ return stmt;
399
+ }
400
+ formatGroupBy(ctx, groupBy) {
401
+ const { stmt } = ctx;
402
+ if (!groupBy)
403
+ return stmt;
404
+ stmt.newline().raw("GROUP BY");
405
+ for (const expr of stmt.separate(groupBy))
406
+ this.formatExprValue(ctx, expr);
407
+ return stmt;
408
+ }
409
+ formatOrderBy(ctx, orderBy) {
410
+ const { stmt } = ctx;
411
+ if (!orderBy)
412
+ return stmt;
413
+ stmt.newline().raw("ORDER BY").space();
414
+ for (const { expr, order } of stmt.separate(orderBy)) {
415
+ this.formatExprValue(ctx, expr);
416
+ stmt.add(order === OrderDirection.Asc ? "ASC" : "DESC");
417
+ }
418
+ return stmt;
419
+ }
420
+ formatLimit(ctx, { limit, offset, singleResult }) {
421
+ const { stmt, forceInline } = ctx;
422
+ if (!limit && !offset && !singleResult)
423
+ return stmt;
424
+ stmt.newline().raw("LIMIT").space();
425
+ this.formatValue(ctx, singleResult ? 1 : limit);
426
+ if (offset && offset > 0) {
427
+ stmt.add("OFFSET").space();
428
+ this.formatValue(ctx, offset);
429
+ }
430
+ return stmt;
431
+ }
432
+ formatSelection(ctx, selection, formatSubject) {
433
+ const { stmt } = ctx;
434
+ const mkSubject = () => this.formatExpr(
435
+ {
436
+ ...ctx,
437
+ formatAsJson: true
438
+ },
439
+ selection
440
+ );
441
+ if (formatSubject)
442
+ formatSubject(stmt, mkSubject);
443
+ else
444
+ this.formatExpr(ctx, selection);
445
+ if (!ctx.selectAsColumns)
446
+ stmt.add("AS").addIdentifier("result");
447
+ return stmt;
448
+ }
449
+ formatExprJson(ctx, expr) {
450
+ return this.formatExpr({ ...ctx, formatAsJson: true }, expr);
451
+ }
452
+ formatExprValue(ctx, expr) {
453
+ return this.formatExpr({ ...ctx, formatAsJson: false }, expr);
454
+ }
455
+ retrieveField(expr, field) {
456
+ switch (expr.type) {
457
+ case ExprType.Record:
458
+ return expr.fields[field];
459
+ case ExprType.Merge:
460
+ return this.retrieveField(expr.a, field) || this.retrieveField(expr.b, field);
461
+ default:
462
+ return void 0;
463
+ }
464
+ }
465
+ formatField(ctx, expr, field) {
466
+ const { stmt } = ctx;
467
+ const fieldExpr = this.retrieveField(expr, field);
468
+ if (fieldExpr)
469
+ return this.formatExpr(ctx, fieldExpr);
470
+ switch (expr.type) {
471
+ case ExprType.Row:
472
+ switch (expr.target.type) {
473
+ case TargetType.Table:
474
+ const column = expr.target.table.columns[field];
475
+ const asBoolean = column?.type === ColumnType.Boolean && ctx.formatAsJson;
476
+ const jsonColumn = column?.type === ColumnType.Json;
477
+ const asJson = jsonColumn && ctx.formatAsJson;
478
+ if (asJson) {
479
+ stmt.raw("json");
480
+ stmt.openParenthesis();
481
+ }
482
+ if (asBoolean)
483
+ stmt.add(`json(iif(`);
484
+ if (!ctx.skipTableName) {
485
+ stmt.identifier(expr.target.table.alias || expr.target.table.name).raw(".");
486
+ }
487
+ stmt.identifier(field);
488
+ if (asBoolean)
489
+ stmt.add(`, 'true', 'false'))`);
490
+ if (asJson)
491
+ stmt.closeParenthesis();
492
+ if (jsonColumn && !asJson)
493
+ stmt.raw("->>'$'");
494
+ return stmt;
495
+ }
496
+ default:
497
+ return this.formatAccess(ctx, () => this.formatExpr(ctx, expr), field);
498
+ }
499
+ }
500
+ formatString(ctx, input) {
501
+ const { stmt } = ctx;
502
+ return stmt.raw(this.escapeValue(String(input)));
503
+ }
504
+ formatInlineValue(ctx, rawValue) {
505
+ const { stmt } = ctx;
506
+ switch (true) {
507
+ case (rawValue === null || rawValue === void 0):
508
+ return stmt.raw("NULL");
509
+ case typeof rawValue === "boolean":
510
+ return rawValue ? stmt.raw("TRUE") : stmt.raw("FALSE");
511
+ case (typeof rawValue === "string" || typeof rawValue === "number"):
512
+ return this.formatString(ctx, rawValue);
513
+ default:
514
+ return this.formatString(ctx, JSON.stringify(rawValue));
515
+ }
516
+ }
517
+ formatValue(ctx, rawValue) {
518
+ const { stmt, formatAsJson, formatAsInsert, forceInline } = ctx;
519
+ const asJson = formatAsJson || formatAsInsert;
520
+ switch (true) {
521
+ case (rawValue === null || rawValue === void 0):
522
+ return stmt.raw("NULL");
523
+ case ((formatAsInsert || !formatAsJson) && typeof rawValue === "boolean"):
524
+ return rawValue ? stmt.raw("1") : stmt.raw("0");
525
+ case (!formatAsInsert && Array.isArray(rawValue)):
526
+ if (asJson)
527
+ stmt.raw("json_array");
528
+ stmt.openParenthesis();
529
+ for (const v of stmt.separate(rawValue))
530
+ this.formatValue({ ...ctx, formatAsJson: asJson }, v);
531
+ stmt.closeParenthesis();
532
+ return stmt;
533
+ case (typeof rawValue === "string" || typeof rawValue === "number"):
534
+ if (forceInline)
535
+ return stmt.raw(this.escapeValue(rawValue));
536
+ return stmt.value(rawValue);
537
+ default:
538
+ if (formatAsJson) {
539
+ stmt.raw("json");
540
+ stmt.openParenthesis();
541
+ }
542
+ if (forceInline)
543
+ this.formatString(ctx, JSON.stringify(rawValue));
544
+ else
545
+ stmt.value(JSON.stringify(rawValue));
546
+ if (formatAsJson)
547
+ stmt.closeParenthesis();
548
+ return stmt;
549
+ }
550
+ }
551
+ formatExpr({ formatAsIn, ...ctx }, expr) {
552
+ const { stmt } = ctx;
553
+ switch (expr.type) {
554
+ case ExprType.UnOp:
555
+ switch (expr.op) {
556
+ case UnOpType.IsNull:
557
+ return this.formatExprValue(ctx, expr.expr).add("IS NULL");
558
+ case UnOpType.Not:
559
+ stmt.raw("NOT").openParenthesis();
560
+ this.formatExprValue(ctx, expr.expr);
561
+ return stmt.closeParenthesis();
562
+ }
563
+ case ExprType.BinOp:
564
+ stmt.openParenthesis();
565
+ this.formatExprValue(ctx, expr.a).add(binOps[expr.op]).space();
566
+ const asIn = expr.op === BinOpType.In || expr.op === BinOpType.NotIn;
567
+ this.formatExprValue({ ...ctx, formatAsIn: asIn }, expr.b);
568
+ return stmt.closeParenthesis();
569
+ case ExprType.Param:
570
+ switch (expr.param.type) {
571
+ case ParamType.Value:
572
+ return this.formatValue(ctx, expr.param.value);
573
+ case ParamType.Named:
574
+ return stmt.param(expr.param);
575
+ }
576
+ case ExprType.Field:
577
+ if (formatAsIn) {
578
+ stmt.openParenthesis();
579
+ stmt.raw("SELECT value FROM json_each");
580
+ stmt.openParenthesis();
581
+ this.formatExprJson(ctx, expr);
582
+ stmt.closeParenthesis();
583
+ return stmt.closeParenthesis();
584
+ }
585
+ return this.formatField(ctx, expr.expr, expr.field);
586
+ case ExprType.Call: {
587
+ if (expr.method === "cast") {
588
+ const [e, type] = expr.params;
589
+ const typeName = type.type === ExprType.Param && type.param.type === ParamType.Value && type.param.value;
590
+ stmt.raw("cast").openParenthesis();
591
+ this.formatExprValue(ctx, e).add("as").space();
592
+ this.formatString(ctx, typeName);
593
+ return stmt.closeParenthesis();
594
+ } else if (expr.method === "exists") {
595
+ stmt.raw("exists").space();
596
+ return this.formatExprValue(ctx, expr.params[0]);
597
+ } else {
598
+ stmt.identifier(expr.method);
599
+ for (const param of stmt.call(expr.params))
600
+ this.formatExprValue(ctx, param);
601
+ return stmt;
602
+ }
603
+ }
604
+ case ExprType.Query:
605
+ if (!ctx.formatAsJson) {
606
+ stmt.openParenthesis();
607
+ this.format(ctx, expr.query);
608
+ return stmt.closeParenthesis();
609
+ }
610
+ if (expr.query.singleResult) {
611
+ stmt.openParenthesis();
612
+ this.format({ ...ctx, topLevel: true }, expr.query);
613
+ return stmt.closeParenthesis().raw(`->'$.result'`);
614
+ }
615
+ stmt.openParenthesis().raw(`SELECT json_group_array(result->'$.result')`).newline().raw("FROM").space().openParenthesis();
616
+ this.format({ ...ctx, topLevel: true }, expr.query);
617
+ return stmt.closeParenthesis().closeParenthesis();
618
+ case ExprType.Row:
619
+ switch (expr.target.type) {
620
+ case TargetType.Table:
621
+ const table = Target.source(expr.target);
622
+ if (!table)
623
+ throw new Error(`Cannot select empty target`);
624
+ if (ctx.tableAsExpr)
625
+ return stmt.identifier(table.alias || table.name);
626
+ stmt.identifier("json_object");
627
+ for (const [key, column] of stmt.call(
628
+ Object.entries(table.columns)
629
+ )) {
630
+ this.formatString(ctx, key).raw(", ");
631
+ this.formatField(ctx, expr, column.name);
632
+ }
633
+ return stmt;
634
+ case TargetType.Query:
635
+ case TargetType.Expr:
636
+ return stmt.identifier(expr.target.alias).raw(".value");
637
+ default:
638
+ throw new Error(`Cannot select from ${expr.target.type}`);
639
+ }
640
+ case ExprType.Merge:
641
+ stmt.identifier("json_patch").openParenthesis();
642
+ this.formatExpr({ ...ctx, formatAsJson: true }, expr.a);
643
+ stmt.raw(", ");
644
+ this.formatExpr({ ...ctx, formatAsJson: true }, expr.b);
645
+ return stmt.closeParenthesis();
646
+ case ExprType.Record:
647
+ if (ctx.selectAsColumns) {
648
+ const inner = { ...ctx, selectAsColumns: false };
649
+ for (const [key, value] of stmt.separate(
650
+ Object.entries(expr.fields)
651
+ )) {
652
+ this.formatExprJson(inner, value);
653
+ }
654
+ return stmt;
655
+ }
656
+ stmt.identifier("json_object").openParenthesis();
657
+ for (const [key, value] of stmt.separate(Object.entries(expr.fields))) {
658
+ this.formatString(ctx, key).raw(", ");
659
+ this.formatExprJson(ctx, value);
660
+ }
661
+ return stmt.closeParenthesis();
662
+ case ExprType.Filter: {
663
+ const { target, condition } = expr;
664
+ switch (target.type) {
665
+ case TargetType.Expr:
666
+ stmt.openParenthesis();
667
+ if (!formatAsIn) {
668
+ stmt.raw("SELECT json_group_array(json(result)) FROM ").openParenthesis();
669
+ }
670
+ stmt.raw("SELECT value AS result").add("FROM json_each").openParenthesis();
671
+ this.formatExpr(ctx, target.expr);
672
+ stmt.closeParenthesis();
673
+ if (target.alias)
674
+ stmt.add("AS").addIdentifier(target.alias);
675
+ stmt.add("WHERE").space();
676
+ this.formatExprValue(ctx, condition);
677
+ if (!formatAsIn) {
678
+ stmt.closeParenthesis();
679
+ }
680
+ return stmt.closeParenthesis();
681
+ default:
682
+ throw new Error("todo");
683
+ }
684
+ }
685
+ case ExprType.Map: {
686
+ const { target, result } = expr;
687
+ switch (target.type) {
688
+ case TargetType.Expr:
689
+ stmt.openParenthesis();
690
+ if (!formatAsIn) {
691
+ stmt.raw("SELECT json_group_array(json(result)) FROM ").openParenthesis();
692
+ }
693
+ stmt.raw("SELECT").space();
694
+ this.formatExpr(ctx, result).add("AS result").add("FROM json_each").openParenthesis();
695
+ this.formatExprJson(ctx, target.expr);
696
+ stmt.closeParenthesis();
697
+ if (target.alias)
698
+ stmt.add("AS").addIdentifier(target.alias);
699
+ if (!formatAsIn) {
700
+ stmt.closeParenthesis();
701
+ }
702
+ return stmt.closeParenthesis();
703
+ default:
704
+ throw new Error("todo");
705
+ }
706
+ }
707
+ default:
708
+ console.log(expr);
709
+ throw new Error("todo");
710
+ }
711
+ }
712
+ };
713
+ export {
714
+ Formatter
715
+ };
File without changes