@simplysm/orm-common 13.0.69 → 13.0.71
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 +54 -1447
- package/dist/create-db-context.d.ts +10 -10
- package/dist/create-db-context.js +9 -9
- package/dist/create-db-context.js.map +1 -1
- package/dist/ddl/column-ddl.d.ts +4 -4
- package/dist/ddl/initialize.d.ts +17 -17
- package/dist/ddl/initialize.js +2 -2
- package/dist/ddl/initialize.js.map +1 -1
- package/dist/ddl/relation-ddl.d.ts +6 -6
- package/dist/ddl/schema-ddl.d.ts +4 -4
- package/dist/ddl/table-ddl.d.ts +24 -24
- package/dist/ddl/table-ddl.js +4 -4
- package/dist/ddl/table-ddl.js.map +1 -1
- package/dist/errors/db-transaction-error.d.ts +15 -15
- package/dist/errors/db-transaction-error.d.ts.map +1 -1
- package/dist/exec/executable.d.ts +23 -23
- package/dist/exec/executable.js +3 -3
- package/dist/exec/executable.js.map +1 -1
- package/dist/exec/queryable.d.ts +160 -160
- package/dist/exec/queryable.js +119 -119
- package/dist/exec/queryable.js.map +1 -1
- package/dist/exec/search-parser.d.ts +37 -37
- package/dist/exec/search-parser.d.ts.map +1 -1
- package/dist/expr/expr-unit.d.ts +4 -4
- package/dist/expr/expr.d.ts +257 -257
- package/dist/expr/expr.js +265 -265
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/base/expr-renderer-base.d.ts +9 -9
- package/dist/query-builder/base/expr-renderer-base.js +2 -2
- package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
- package/dist/query-builder/base/query-builder-base.d.ts +26 -26
- package/dist/query-builder/base/query-builder-base.d.ts.map +1 -1
- package/dist/query-builder/base/query-builder-base.js +22 -22
- package/dist/query-builder/base/query-builder-base.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +18 -18
- package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
- package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-query-builder.js +11 -11
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +17 -17
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +8 -8
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +5 -5
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +4 -4
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +17 -17
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +5 -5
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +8 -8
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/query-builder/query-builder.d.ts +1 -1
- package/dist/schema/factory/column-builder.d.ts +79 -79
- package/dist/schema/factory/column-builder.js +42 -42
- package/dist/schema/factory/index-builder.d.ts +39 -39
- package/dist/schema/factory/index-builder.js +26 -26
- package/dist/schema/factory/relation-builder.d.ts +99 -99
- package/dist/schema/factory/relation-builder.d.ts.map +1 -1
- package/dist/schema/factory/relation-builder.js +38 -38
- package/dist/schema/procedure-builder.d.ts +49 -49
- package/dist/schema/procedure-builder.d.ts.map +1 -1
- package/dist/schema/procedure-builder.js +33 -33
- package/dist/schema/table-builder.d.ts +59 -59
- package/dist/schema/table-builder.d.ts.map +1 -1
- package/dist/schema/table-builder.js +43 -43
- package/dist/schema/view-builder.d.ts +49 -49
- package/dist/schema/view-builder.d.ts.map +1 -1
- package/dist/schema/view-builder.js +32 -32
- package/dist/types/column.d.ts +22 -22
- package/dist/types/column.js +1 -1
- package/dist/types/column.js.map +1 -1
- package/dist/types/db.d.ts +40 -40
- package/dist/types/expr.d.ts +59 -59
- package/dist/types/expr.d.ts.map +1 -1
- package/dist/types/query-def.d.ts +44 -44
- package/dist/types/query-def.d.ts.map +1 -1
- package/dist/utils/result-parser.d.ts +11 -11
- package/dist/utils/result-parser.js +3 -3
- package/dist/utils/result-parser.js.map +1 -1
- package/package.json +5 -5
- package/src/create-db-context.ts +20 -20
- package/src/ddl/column-ddl.ts +4 -4
- package/src/ddl/initialize.ts +259 -259
- package/src/ddl/relation-ddl.ts +89 -89
- package/src/ddl/schema-ddl.ts +4 -4
- package/src/ddl/table-ddl.ts +189 -189
- package/src/errors/db-transaction-error.ts +13 -13
- package/src/exec/executable.ts +25 -25
- package/src/exec/queryable.ts +2033 -2033
- package/src/exec/search-parser.ts +57 -57
- package/src/expr/expr-unit.ts +4 -4
- package/src/expr/expr.ts +2140 -2140
- package/src/query-builder/base/expr-renderer-base.ts +237 -237
- package/src/query-builder/base/query-builder-base.ts +213 -213
- package/src/query-builder/mssql/mssql-expr-renderer.ts +607 -607
- package/src/query-builder/mssql/mssql-query-builder.ts +650 -650
- package/src/query-builder/mysql/mysql-expr-renderer.ts +613 -613
- package/src/query-builder/mysql/mysql-query-builder.ts +759 -759
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +611 -611
- package/src/query-builder/postgresql/postgresql-query-builder.ts +686 -686
- package/src/query-builder/query-builder.ts +19 -19
- package/src/schema/factory/column-builder.ts +423 -423
- package/src/schema/factory/index-builder.ts +164 -164
- package/src/schema/factory/relation-builder.ts +453 -453
- package/src/schema/procedure-builder.ts +232 -232
- package/src/schema/table-builder.ts +319 -319
- package/src/schema/view-builder.ts +221 -221
- package/src/types/column.ts +188 -188
- package/src/types/db.ts +208 -208
- package/src/types/expr.ts +697 -697
- package/src/types/query-def.ts +513 -513
- package/src/utils/result-parser.ts +458 -458
- package/tests/db-context/create-db-context.spec.ts +224 -0
- package/tests/db-context/define-db-context.spec.ts +68 -0
- package/tests/ddl/basic.expected.ts +341 -0
- package/tests/ddl/basic.spec.ts +714 -0
- package/tests/ddl/column-builder.expected.ts +310 -0
- package/tests/ddl/column-builder.spec.ts +637 -0
- package/tests/ddl/index-builder.expected.ts +38 -0
- package/tests/ddl/index-builder.spec.ts +202 -0
- package/tests/ddl/procedure-builder.expected.ts +52 -0
- package/tests/ddl/procedure-builder.spec.ts +234 -0
- package/tests/ddl/relation-builder.expected.ts +36 -0
- package/tests/ddl/relation-builder.spec.ts +372 -0
- package/tests/ddl/table-builder.expected.ts +113 -0
- package/tests/ddl/table-builder.spec.ts +433 -0
- package/tests/ddl/view-builder.expected.ts +38 -0
- package/tests/ddl/view-builder.spec.ts +176 -0
- package/tests/dml/delete.expected.ts +96 -0
- package/tests/dml/delete.spec.ts +160 -0
- package/tests/dml/insert.expected.ts +192 -0
- package/tests/dml/insert.spec.ts +288 -0
- package/tests/dml/update.expected.ts +176 -0
- package/tests/dml/update.spec.ts +318 -0
- package/tests/dml/upsert.expected.ts +215 -0
- package/tests/dml/upsert.spec.ts +242 -0
- package/tests/errors/queryable-errors.spec.ts +177 -0
- package/tests/escape.spec.ts +100 -0
- package/tests/examples/pivot.expected.ts +211 -0
- package/tests/examples/pivot.spec.ts +533 -0
- package/tests/examples/sampling.expected.ts +69 -0
- package/tests/examples/sampling.spec.ts +105 -0
- package/tests/examples/unpivot.expected.ts +120 -0
- package/tests/examples/unpivot.spec.ts +226 -0
- package/tests/exec/search-parser.spec.ts +283 -0
- package/tests/executable/basic.expected.ts +18 -0
- package/tests/executable/basic.spec.ts +54 -0
- package/tests/expr/comparison.expected.ts +282 -0
- package/tests/expr/comparison.spec.ts +400 -0
- package/tests/expr/conditional.expected.ts +134 -0
- package/tests/expr/conditional.spec.ts +276 -0
- package/tests/expr/date.expected.ts +332 -0
- package/tests/expr/date.spec.ts +526 -0
- package/tests/expr/math.expected.ts +62 -0
- package/tests/expr/math.spec.ts +106 -0
- package/tests/expr/string.expected.ts +218 -0
- package/tests/expr/string.spec.ts +356 -0
- package/tests/expr/utility.expected.ts +147 -0
- package/tests/expr/utility.spec.ts +182 -0
- package/tests/select/basic.expected.ts +322 -0
- package/tests/select/basic.spec.ts +502 -0
- package/tests/select/filter.expected.ts +357 -0
- package/tests/select/filter.spec.ts +1068 -0
- package/tests/select/group.expected.ts +169 -0
- package/tests/select/group.spec.ts +244 -0
- package/tests/select/join.expected.ts +582 -0
- package/tests/select/join.spec.ts +805 -0
- package/tests/select/order.expected.ts +150 -0
- package/tests/select/order.spec.ts +189 -0
- package/tests/select/recursive-cte.expected.ts +244 -0
- package/tests/select/recursive-cte.spec.ts +514 -0
- package/tests/select/result-meta.spec.ts +270 -0
- package/tests/select/subquery.expected.ts +363 -0
- package/tests/select/subquery.spec.ts +537 -0
- package/tests/select/view.expected.ts +155 -0
- package/tests/select/view.spec.ts +235 -0
- package/tests/select/window.expected.ts +345 -0
- package/tests/select/window.spec.ts +618 -0
- package/tests/setup/MockExecutor.ts +18 -0
- package/tests/setup/TestDbContext.ts +59 -0
- package/tests/setup/models/Company.ts +13 -0
- package/tests/setup/models/Employee.ts +10 -0
- package/tests/setup/models/MonthlySales.ts +11 -0
- package/tests/setup/models/Post.ts +16 -0
- package/tests/setup/models/Sales.ts +10 -0
- package/tests/setup/models/User.ts +19 -0
- package/tests/setup/procedure/GetAllUsers.ts +9 -0
- package/tests/setup/procedure/GetUserById.ts +12 -0
- package/tests/setup/test-utils.ts +72 -0
- package/tests/setup/views/ActiveUsers.ts +8 -0
- package/tests/setup/views/UserSummary.ts +11 -0
- package/tests/types/nullable-queryable-record.spec.ts +145 -0
- package/tests/utils/result-parser-perf.spec.ts +210 -0
- package/tests/utils/result-parser.spec.ts +701 -0
- package/docs/expressions.md +0 -172
- package/docs/queries.md +0 -444
- package/docs/schema.md +0 -245
|
@@ -1,213 +1,213 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
QueryDef,
|
|
3
|
-
SelectQueryDef,
|
|
4
|
-
InsertQueryDef,
|
|
5
|
-
InsertIfNotExistsQueryDef,
|
|
6
|
-
InsertIntoQueryDef,
|
|
7
|
-
UpdateQueryDef,
|
|
8
|
-
DeleteQueryDef,
|
|
9
|
-
UpsertQueryDef,
|
|
10
|
-
CreateTableQueryDef,
|
|
11
|
-
DropTableQueryDef,
|
|
12
|
-
RenameTableQueryDef,
|
|
13
|
-
TruncateQueryDef,
|
|
14
|
-
AddColumnQueryDef,
|
|
15
|
-
DropColumnQueryDef,
|
|
16
|
-
ModifyColumnQueryDef,
|
|
17
|
-
RenameColumnQueryDef,
|
|
18
|
-
AddPkQueryDef,
|
|
19
|
-
DropPkQueryDef,
|
|
20
|
-
AddFkQueryDef,
|
|
21
|
-
DropFkQueryDef,
|
|
22
|
-
AddIdxQueryDef,
|
|
23
|
-
DropIdxQueryDef,
|
|
24
|
-
CreateViewQueryDef,
|
|
25
|
-
DropViewQueryDef,
|
|
26
|
-
CreateProcQueryDef,
|
|
27
|
-
DropProcQueryDef,
|
|
28
|
-
ExecProcQueryDef,
|
|
29
|
-
ClearSchemaQueryDef,
|
|
30
|
-
SchemaExistsQueryDef,
|
|
31
|
-
SwitchFkQueryDef,
|
|
32
|
-
SelectQueryDefJoin,
|
|
33
|
-
QueryDefObjectName,
|
|
34
|
-
} from "../../types/query-def";
|
|
35
|
-
import type { Expr, WhereExpr } from "../../types/expr";
|
|
36
|
-
import type { QueryBuildResult } from "../../types/db";
|
|
37
|
-
import type { ExprRendererBase } from "./expr-renderer-base";
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* QueryDef → SQL
|
|
41
|
-
*
|
|
42
|
-
* Base
|
|
43
|
-
* - 100%
|
|
44
|
-
* -
|
|
45
|
-
* -
|
|
46
|
-
*/
|
|
47
|
-
export abstract class QueryBuilderBase {
|
|
48
|
-
protected abstract expr: ExprRendererBase;
|
|
49
|
-
|
|
50
|
-
//#region ========== Dispatch (100%
|
|
51
|
-
|
|
52
|
-
build(def: QueryDef): QueryBuildResult {
|
|
53
|
-
const method = this[def.type as keyof this];
|
|
54
|
-
if (typeof method !== "function") {
|
|
55
|
-
throw new Error(
|
|
56
|
-
}
|
|
57
|
-
return (method as (d: QueryDef) => QueryBuildResult).call(this, def);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/** SQL
|
|
61
|
-
protected result(sql: string, resultSetIndex?: number): QueryBuildResult {
|
|
62
|
-
return resultSetIndex != null ? { sql, resultSetIndex } : { sql };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
//#endregion
|
|
66
|
-
|
|
67
|
-
//#region ==========
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
protected abstract tableName(obj: QueryDefObjectName): string;
|
|
71
|
-
|
|
72
|
-
/** WHERE
|
|
73
|
-
protected renderWhere(wheres: WhereExpr[] | undefined): string {
|
|
74
|
-
if (wheres == null || wheres.length === 0) return "";
|
|
75
|
-
return ` WHERE ${this.expr.renderWhere(wheres)}`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** ORDER BY
|
|
79
|
-
protected renderOrderBy(orderBy: [Expr, ("ASC" | "DESC")?][] | undefined): string {
|
|
80
|
-
if (orderBy == null || orderBy.length === 0) return "";
|
|
81
|
-
const parts = orderBy.map(
|
|
82
|
-
([e, dir]) => `${this.expr.render(e)}${dir != null ? ` ${dir}` : ""}`,
|
|
83
|
-
);
|
|
84
|
-
return ` ORDER BY ${parts.join(", ")}`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** GROUP BY
|
|
88
|
-
protected renderGroupBy(groupBy: Expr[] | undefined): string {
|
|
89
|
-
if (groupBy == null || groupBy.length === 0) return "";
|
|
90
|
-
return ` GROUP BY ${groupBy.map((g) => this.expr.render(g)).join(", ")}`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** HAVING
|
|
94
|
-
protected renderHaving(having: WhereExpr[] | undefined): string {
|
|
95
|
-
if (having == null || having.length === 0) return "";
|
|
96
|
-
return ` HAVING ${this.expr.renderWhere(having)}`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** JOIN
|
|
100
|
-
protected renderJoins(joins: SelectQueryDefJoin[] | undefined): string {
|
|
101
|
-
if (joins == null || joins.length === 0) return "";
|
|
102
|
-
return joins.map((j) => this.renderJoin(j)).join("");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
protected abstract renderJoin(join: SelectQueryDefJoin): string;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* JOIN
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* - select:
|
|
115
|
-
* - joins:
|
|
116
|
-
* - orderBy, top, limit:
|
|
117
|
-
* - groupBy, having:
|
|
118
|
-
* - distinct:
|
|
119
|
-
* - from (
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* select/joins
|
|
124
|
-
*/
|
|
125
|
-
protected needsLateral(join: SelectQueryDefJoin): boolean {
|
|
126
|
-
// from
|
|
127
|
-
if (Array.isArray(join.from)) {
|
|
128
|
-
return true;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
const basicJoinProps = ["type", "from", "as", "where", "isSingle"];
|
|
133
|
-
return Object.keys(join).some((key) => !basicJoinProps.includes(key));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** FROM
|
|
137
|
-
protected renderFrom(from: SelectQueryDef["from"]): string {
|
|
138
|
-
if (from == null) {
|
|
139
|
-
throw new Error("FROM
|
|
140
|
-
}
|
|
141
|
-
if (typeof from === "string") {
|
|
142
|
-
return this.expr.wrap(from);
|
|
143
|
-
}
|
|
144
|
-
if ("type" in from) {
|
|
145
|
-
return `(${this.select(from).sql})`;
|
|
146
|
-
}
|
|
147
|
-
if (Array.isArray(from)) {
|
|
148
|
-
return `(${from.map((f) => this.select(f).sql).join(" UNION ALL ")})`;
|
|
149
|
-
}
|
|
150
|
-
return this.tableName(from);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
//#endregion
|
|
154
|
-
|
|
155
|
-
//#region ========== Abstract - DML ==========
|
|
156
|
-
|
|
157
|
-
protected abstract select(def: SelectQueryDef): QueryBuildResult;
|
|
158
|
-
protected abstract insert(def: InsertQueryDef): QueryBuildResult;
|
|
159
|
-
protected abstract insertIfNotExists(def: InsertIfNotExistsQueryDef): QueryBuildResult;
|
|
160
|
-
protected abstract insertInto(def: InsertIntoQueryDef): QueryBuildResult;
|
|
161
|
-
protected abstract update(def: UpdateQueryDef): QueryBuildResult;
|
|
162
|
-
protected abstract delete(def: DeleteQueryDef): QueryBuildResult;
|
|
163
|
-
protected abstract upsert(def: UpsertQueryDef): QueryBuildResult;
|
|
164
|
-
|
|
165
|
-
//#endregion
|
|
166
|
-
|
|
167
|
-
//#region ========== Abstract - DDL Table ==========
|
|
168
|
-
|
|
169
|
-
protected abstract createTable(def: CreateTableQueryDef): QueryBuildResult;
|
|
170
|
-
protected abstract dropTable(def: DropTableQueryDef): QueryBuildResult;
|
|
171
|
-
protected abstract renameTable(def: RenameTableQueryDef): QueryBuildResult;
|
|
172
|
-
protected abstract truncate(def: TruncateQueryDef): QueryBuildResult;
|
|
173
|
-
|
|
174
|
-
//#endregion
|
|
175
|
-
|
|
176
|
-
//#region ========== Abstract - DDL Column ==========
|
|
177
|
-
|
|
178
|
-
protected abstract addColumn(def: AddColumnQueryDef): QueryBuildResult;
|
|
179
|
-
protected abstract dropColumn(def: DropColumnQueryDef): QueryBuildResult;
|
|
180
|
-
protected abstract modifyColumn(def: ModifyColumnQueryDef): QueryBuildResult;
|
|
181
|
-
protected abstract renameColumn(def: RenameColumnQueryDef): QueryBuildResult;
|
|
182
|
-
|
|
183
|
-
//#endregion
|
|
184
|
-
|
|
185
|
-
//#region ========== Abstract - DDL Constraint ==========
|
|
186
|
-
|
|
187
|
-
protected abstract addPk(def: AddPkQueryDef): QueryBuildResult;
|
|
188
|
-
protected abstract dropPk(def: DropPkQueryDef): QueryBuildResult;
|
|
189
|
-
protected abstract addFk(def: AddFkQueryDef): QueryBuildResult;
|
|
190
|
-
protected abstract dropFk(def: DropFkQueryDef): QueryBuildResult;
|
|
191
|
-
protected abstract addIdx(def: AddIdxQueryDef): QueryBuildResult;
|
|
192
|
-
protected abstract dropIdx(def: DropIdxQueryDef): QueryBuildResult;
|
|
193
|
-
|
|
194
|
-
//#endregion
|
|
195
|
-
|
|
196
|
-
//#region ========== Abstract - DDL View/Procedure ==========
|
|
197
|
-
|
|
198
|
-
protected abstract createView(def: CreateViewQueryDef): QueryBuildResult;
|
|
199
|
-
protected abstract dropView(def: DropViewQueryDef): QueryBuildResult;
|
|
200
|
-
protected abstract createProc(def: CreateProcQueryDef): QueryBuildResult;
|
|
201
|
-
protected abstract dropProc(def: DropProcQueryDef): QueryBuildResult;
|
|
202
|
-
protected abstract execProc(def: ExecProcQueryDef): QueryBuildResult;
|
|
203
|
-
|
|
204
|
-
//#endregion
|
|
205
|
-
|
|
206
|
-
//#region ========== Abstract - Utils ==========
|
|
207
|
-
|
|
208
|
-
protected abstract clearSchema(def: ClearSchemaQueryDef): QueryBuildResult;
|
|
209
|
-
protected abstract schemaExists(def: SchemaExistsQueryDef): QueryBuildResult;
|
|
210
|
-
protected abstract switchFk(def: SwitchFkQueryDef): QueryBuildResult;
|
|
211
|
-
|
|
212
|
-
//#endregion
|
|
213
|
-
}
|
|
1
|
+
import type {
|
|
2
|
+
QueryDef,
|
|
3
|
+
SelectQueryDef,
|
|
4
|
+
InsertQueryDef,
|
|
5
|
+
InsertIfNotExistsQueryDef,
|
|
6
|
+
InsertIntoQueryDef,
|
|
7
|
+
UpdateQueryDef,
|
|
8
|
+
DeleteQueryDef,
|
|
9
|
+
UpsertQueryDef,
|
|
10
|
+
CreateTableQueryDef,
|
|
11
|
+
DropTableQueryDef,
|
|
12
|
+
RenameTableQueryDef,
|
|
13
|
+
TruncateQueryDef,
|
|
14
|
+
AddColumnQueryDef,
|
|
15
|
+
DropColumnQueryDef,
|
|
16
|
+
ModifyColumnQueryDef,
|
|
17
|
+
RenameColumnQueryDef,
|
|
18
|
+
AddPkQueryDef,
|
|
19
|
+
DropPkQueryDef,
|
|
20
|
+
AddFkQueryDef,
|
|
21
|
+
DropFkQueryDef,
|
|
22
|
+
AddIdxQueryDef,
|
|
23
|
+
DropIdxQueryDef,
|
|
24
|
+
CreateViewQueryDef,
|
|
25
|
+
DropViewQueryDef,
|
|
26
|
+
CreateProcQueryDef,
|
|
27
|
+
DropProcQueryDef,
|
|
28
|
+
ExecProcQueryDef,
|
|
29
|
+
ClearSchemaQueryDef,
|
|
30
|
+
SchemaExistsQueryDef,
|
|
31
|
+
SwitchFkQueryDef,
|
|
32
|
+
SelectQueryDefJoin,
|
|
33
|
+
QueryDefObjectName,
|
|
34
|
+
} from "../../types/query-def";
|
|
35
|
+
import type { Expr, WhereExpr } from "../../types/expr";
|
|
36
|
+
import type { QueryBuildResult } from "../../types/db";
|
|
37
|
+
import type { ExprRendererBase } from "./expr-renderer-base";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* QueryDef → SQL render abstract base class
|
|
41
|
+
*
|
|
42
|
+
* Base principles:
|
|
43
|
+
* - Implement only 100% identical logic across all dialects (dispatch)
|
|
44
|
+
* - If different at all, make it abstract
|
|
45
|
+
* - Method name identical to def.type (enables dynamic dispatch)
|
|
46
|
+
*/
|
|
47
|
+
export abstract class QueryBuilderBase {
|
|
48
|
+
protected abstract expr: ExprRendererBase;
|
|
49
|
+
|
|
50
|
+
//#region ========== Dispatch (100% identical) ==========
|
|
51
|
+
|
|
52
|
+
build(def: QueryDef): QueryBuildResult {
|
|
53
|
+
const method = this[def.type as keyof this];
|
|
54
|
+
if (typeof method !== "function") {
|
|
55
|
+
throw new Error(`Unknown QueryDef type: ${def.type}`);
|
|
56
|
+
}
|
|
57
|
+
return (method as (d: QueryDef) => QueryBuildResult).call(this, def);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Helper to wrap SQL in QueryBuildResult */
|
|
61
|
+
protected result(sql: string, resultSetIndex?: number): QueryBuildResult {
|
|
62
|
+
return resultSetIndex != null ? { sql, resultSetIndex } : { sql };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
//#endregion
|
|
66
|
+
|
|
67
|
+
//#region ========== Common render method (100% identical) ==========
|
|
68
|
+
|
|
69
|
+
/** Table name render (different per dialect, so abstract) */
|
|
70
|
+
protected abstract tableName(obj: QueryDefObjectName): string;
|
|
71
|
+
|
|
72
|
+
/** WHERE clause render */
|
|
73
|
+
protected renderWhere(wheres: WhereExpr[] | undefined): string {
|
|
74
|
+
if (wheres == null || wheres.length === 0) return "";
|
|
75
|
+
return ` WHERE ${this.expr.renderWhere(wheres)}`;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** ORDER BY clause render */
|
|
79
|
+
protected renderOrderBy(orderBy: [Expr, ("ASC" | "DESC")?][] | undefined): string {
|
|
80
|
+
if (orderBy == null || orderBy.length === 0) return "";
|
|
81
|
+
const parts = orderBy.map(
|
|
82
|
+
([e, dir]) => `${this.expr.render(e)}${dir != null ? ` ${dir}` : ""}`,
|
|
83
|
+
);
|
|
84
|
+
return ` ORDER BY ${parts.join(", ")}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** GROUP BY clause render */
|
|
88
|
+
protected renderGroupBy(groupBy: Expr[] | undefined): string {
|
|
89
|
+
if (groupBy == null || groupBy.length === 0) return "";
|
|
90
|
+
return ` GROUP BY ${groupBy.map((g) => this.expr.render(g)).join(", ")}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** HAVING clause render */
|
|
94
|
+
protected renderHaving(having: WhereExpr[] | undefined): string {
|
|
95
|
+
if (having == null || having.length === 0) return "";
|
|
96
|
+
return ` HAVING ${this.expr.renderWhere(having)}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** JOIN clause render */
|
|
100
|
+
protected renderJoins(joins: SelectQueryDefJoin[] | undefined): string {
|
|
101
|
+
if (joins == null || joins.length === 0) return "";
|
|
102
|
+
return joins.map((j) => this.renderJoin(j)).join("");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Single JOIN render (different per dialect, so abstract) */
|
|
106
|
+
protected abstract renderJoin(join: SelectQueryDefJoin): string;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Detect if JOIN needs LATERAL/CROSS APPLY
|
|
110
|
+
*
|
|
111
|
+
* If JOIN has only basic properties (type, from, as, where, isSingle), treat as normal JOIN.
|
|
112
|
+
* Otherwise, subquery is needed, so use LATERAL JOIN:
|
|
113
|
+
*
|
|
114
|
+
* - select: column transformation/aggregation needed (normal JOIN references entire table)
|
|
115
|
+
* - joins: nested JOIN handled inside subquery
|
|
116
|
+
* - orderBy, top, limit: sorting/limit applied inside subquery
|
|
117
|
+
* - groupBy, having: aggregation performed inside subquery
|
|
118
|
+
* - distinct: deduplication applied inside subquery
|
|
119
|
+
* - from (array): UNION ALL pattern
|
|
120
|
+
*
|
|
121
|
+
* Note: select and joins are auto-generated during nested joins, so not in basicJoinProps.
|
|
122
|
+
* Even if user doesn't call .select() directly, internal .joinSingle() may add
|
|
123
|
+
* select/joins, which also requires subquery.
|
|
124
|
+
*/
|
|
125
|
+
protected needsLateral(join: SelectQueryDefJoin): boolean {
|
|
126
|
+
// If from is array, always LATERAL (UNION ALL pattern)
|
|
127
|
+
if (Array.isArray(join.from)) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// LATERAL needed if join has additional properties beyond basic JOIN properties
|
|
132
|
+
const basicJoinProps = ["type", "from", "as", "where", "isSingle"];
|
|
133
|
+
return Object.keys(join).some((key) => !basicJoinProps.includes(key));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** FROM clause source render */
|
|
137
|
+
protected renderFrom(from: SelectQueryDef["from"]): string {
|
|
138
|
+
if (from == null) {
|
|
139
|
+
throw new Error("FROM clause is required.");
|
|
140
|
+
}
|
|
141
|
+
if (typeof from === "string") {
|
|
142
|
+
return this.expr.wrap(from);
|
|
143
|
+
}
|
|
144
|
+
if ("type" in from) {
|
|
145
|
+
return `(${this.select(from).sql})`;
|
|
146
|
+
}
|
|
147
|
+
if (Array.isArray(from)) {
|
|
148
|
+
return `(${from.map((f) => this.select(f).sql).join(" UNION ALL ")})`;
|
|
149
|
+
}
|
|
150
|
+
return this.tableName(from);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
//#endregion
|
|
154
|
+
|
|
155
|
+
//#region ========== Abstract - DML ==========
|
|
156
|
+
|
|
157
|
+
protected abstract select(def: SelectQueryDef): QueryBuildResult;
|
|
158
|
+
protected abstract insert(def: InsertQueryDef): QueryBuildResult;
|
|
159
|
+
protected abstract insertIfNotExists(def: InsertIfNotExistsQueryDef): QueryBuildResult;
|
|
160
|
+
protected abstract insertInto(def: InsertIntoQueryDef): QueryBuildResult;
|
|
161
|
+
protected abstract update(def: UpdateQueryDef): QueryBuildResult;
|
|
162
|
+
protected abstract delete(def: DeleteQueryDef): QueryBuildResult;
|
|
163
|
+
protected abstract upsert(def: UpsertQueryDef): QueryBuildResult;
|
|
164
|
+
|
|
165
|
+
//#endregion
|
|
166
|
+
|
|
167
|
+
//#region ========== Abstract - DDL Table ==========
|
|
168
|
+
|
|
169
|
+
protected abstract createTable(def: CreateTableQueryDef): QueryBuildResult;
|
|
170
|
+
protected abstract dropTable(def: DropTableQueryDef): QueryBuildResult;
|
|
171
|
+
protected abstract renameTable(def: RenameTableQueryDef): QueryBuildResult;
|
|
172
|
+
protected abstract truncate(def: TruncateQueryDef): QueryBuildResult;
|
|
173
|
+
|
|
174
|
+
//#endregion
|
|
175
|
+
|
|
176
|
+
//#region ========== Abstract - DDL Column ==========
|
|
177
|
+
|
|
178
|
+
protected abstract addColumn(def: AddColumnQueryDef): QueryBuildResult;
|
|
179
|
+
protected abstract dropColumn(def: DropColumnQueryDef): QueryBuildResult;
|
|
180
|
+
protected abstract modifyColumn(def: ModifyColumnQueryDef): QueryBuildResult;
|
|
181
|
+
protected abstract renameColumn(def: RenameColumnQueryDef): QueryBuildResult;
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
|
|
185
|
+
//#region ========== Abstract - DDL Constraint ==========
|
|
186
|
+
|
|
187
|
+
protected abstract addPk(def: AddPkQueryDef): QueryBuildResult;
|
|
188
|
+
protected abstract dropPk(def: DropPkQueryDef): QueryBuildResult;
|
|
189
|
+
protected abstract addFk(def: AddFkQueryDef): QueryBuildResult;
|
|
190
|
+
protected abstract dropFk(def: DropFkQueryDef): QueryBuildResult;
|
|
191
|
+
protected abstract addIdx(def: AddIdxQueryDef): QueryBuildResult;
|
|
192
|
+
protected abstract dropIdx(def: DropIdxQueryDef): QueryBuildResult;
|
|
193
|
+
|
|
194
|
+
//#endregion
|
|
195
|
+
|
|
196
|
+
//#region ========== Abstract - DDL View/Procedure ==========
|
|
197
|
+
|
|
198
|
+
protected abstract createView(def: CreateViewQueryDef): QueryBuildResult;
|
|
199
|
+
protected abstract dropView(def: DropViewQueryDef): QueryBuildResult;
|
|
200
|
+
protected abstract createProc(def: CreateProcQueryDef): QueryBuildResult;
|
|
201
|
+
protected abstract dropProc(def: DropProcQueryDef): QueryBuildResult;
|
|
202
|
+
protected abstract execProc(def: ExecProcQueryDef): QueryBuildResult;
|
|
203
|
+
|
|
204
|
+
//#endregion
|
|
205
|
+
|
|
206
|
+
//#region ========== Abstract - Utils ==========
|
|
207
|
+
|
|
208
|
+
protected abstract clearSchema(def: ClearSchemaQueryDef): QueryBuildResult;
|
|
209
|
+
protected abstract schemaExists(def: SchemaExistsQueryDef): QueryBuildResult;
|
|
210
|
+
protected abstract switchFk(def: SwitchFkQueryDef): QueryBuildResult;
|
|
211
|
+
|
|
212
|
+
//#endregion
|
|
213
|
+
}
|