@simplysm/orm-common 14.0.1 → 14.0.4
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 +135 -0
- package/dist/exec/queryable.js +18 -18
- package/dist/exec/queryable.js.map +1 -1
- package/dist/expr/expr.d.ts +102 -102
- package/dist/expr/expr.js +105 -105
- package/dist/expr/expr.js.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mssql/mssql-expr-renderer.js +17 -17
- 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 +26 -26
- package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-expr-renderer.js +14 -14
- package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
- package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/mysql/mysql-query-builder.js +67 -67
- package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js +13 -13
- package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
- package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
- package/dist/query-builder/postgresql/postgresql-query-builder.js +47 -47
- package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
- package/dist/schema/factory/relation-builder.d.ts +8 -8
- package/dist/schema/factory/relation-builder.js +9 -9
- package/dist/schema/factory/relation-builder.js.map +1 -1
- package/dist/schema/view-builder.js +2 -2
- package/dist/schema/view-builder.js.map +1 -1
- package/dist/types/column.d.ts +21 -21
- package/dist/types/column.js +5 -5
- package/dist/utils/result-parser.d.ts +11 -11
- package/dist/utils/result-parser.js +48 -48
- package/dist/utils/result-parser.js.map +1 -1
- package/docs/core.md +206 -0
- package/docs/expression.md +217 -0
- package/docs/query-builder.md +126 -0
- package/docs/queryable.md +236 -0
- package/docs/schema-builders.md +352 -0
- package/docs/types.md +501 -0
- package/package.json +7 -3
- package/src/exec/queryable.ts +18 -18
- package/src/expr/expr.ts +105 -105
- package/src/query-builder/mssql/mssql-expr-renderer.ts +17 -17
- package/src/query-builder/mssql/mssql-query-builder.ts +26 -26
- package/src/query-builder/mysql/mysql-expr-renderer.ts +14 -14
- package/src/query-builder/mysql/mysql-query-builder.ts +67 -67
- package/src/query-builder/postgresql/postgresql-expr-renderer.ts +13 -13
- package/src/query-builder/postgresql/postgresql-query-builder.ts +47 -47
- package/src/schema/factory/relation-builder.ts +9 -9
- package/src/schema/view-builder.ts +2 -2
- package/src/types/column.ts +23 -23
- package/src/utils/result-parser.ts +49 -49
package/docs/core.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Core
|
|
2
|
+
|
|
3
|
+
DbContext definition, creation, and lifecycle management.
|
|
4
|
+
|
|
5
|
+
## defineDbContext
|
|
6
|
+
|
|
7
|
+
Factory function that creates a `DbContextDef` blueprint from tables, views, procedures, and migrations. Automatically adds a `_migration` system table.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
function defineDbContext<TTables, TViews, TProcedures>(config: {
|
|
11
|
+
tables?: TTables;
|
|
12
|
+
views?: TViews;
|
|
13
|
+
procedures?: TProcedures;
|
|
14
|
+
migrations?: Migration[];
|
|
15
|
+
}): DbContextDef<TTables & { _migration: typeof _Migration }, TViews, TProcedures>;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
**Parameters:**
|
|
19
|
+
|
|
20
|
+
| Parameter | Type | Description |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| `config.tables` | `Record<string, TableBuilder>` | Table definitions |
|
|
23
|
+
| `config.views` | `Record<string, ViewBuilder>` | View definitions |
|
|
24
|
+
| `config.procedures` | `Record<string, ProcedureBuilder>` | Procedure definitions |
|
|
25
|
+
| `config.migrations` | `Migration[]` | Migration definitions |
|
|
26
|
+
|
|
27
|
+
**Example:**
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
const MyDb = defineDbContext({
|
|
31
|
+
tables: { user: User, post: Post },
|
|
32
|
+
views: { userSummary: UserSummary },
|
|
33
|
+
procedures: { getUserById: GetUserById },
|
|
34
|
+
migrations: [
|
|
35
|
+
{ name: "20260101_001_init", up: async (db) => { await db.createTable(User); } },
|
|
36
|
+
],
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## createDbContext
|
|
41
|
+
|
|
42
|
+
Factory that creates a complete `DbContextInstance` from a `DbContextDef` and a `DbContextExecutor`. The returned instance includes queryable accessors for all tables/views, executable accessors for procedures, connection/transaction management, and DDL methods.
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
function createDbContext<TDef extends DbContextDef<any, any, any>>(
|
|
46
|
+
def: TDef,
|
|
47
|
+
executor: DbContextExecutor,
|
|
48
|
+
opt: { database: string; schema?: string },
|
|
49
|
+
): DbContextInstance<TDef>;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Parameters:**
|
|
53
|
+
|
|
54
|
+
| Parameter | Type | Description |
|
|
55
|
+
|---|---|---|
|
|
56
|
+
| `def` | `DbContextDef` | Definition created by `defineDbContext()` |
|
|
57
|
+
| `executor` | `DbContextExecutor` | Query executor (e.g., `NodeDbContextExecutor`) |
|
|
58
|
+
| `opt.database` | `string` | Database name |
|
|
59
|
+
| `opt.schema` | `string` | Schema name (MSSQL: dbo, PostgreSQL: public) |
|
|
60
|
+
|
|
61
|
+
**Example:**
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const db = createDbContext(MyDb, executor, { database: "mydb" });
|
|
65
|
+
|
|
66
|
+
await db.connect(async () => {
|
|
67
|
+
const users = await db.user().execute();
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## DbContextDef
|
|
72
|
+
|
|
73
|
+
Blueprint interface created by `defineDbContext()`. Contains only schema metadata, no runtime state.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
interface DbContextDef<TTables, TViews, TProcedures> {
|
|
77
|
+
readonly meta: {
|
|
78
|
+
readonly tables: TTables;
|
|
79
|
+
readonly views: TViews;
|
|
80
|
+
readonly procedures: TProcedures;
|
|
81
|
+
readonly migrations: Migration[];
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## DbContextInstance
|
|
87
|
+
|
|
88
|
+
Full DbContext instance type returned by `createDbContext()`. Extends `DbContextBase` with queryable accessors, DDL methods, and connection management.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
type DbContextInstance<TDef> = DbContextBase
|
|
92
|
+
& DbContextConnectionMethods
|
|
93
|
+
& DbContextDdlMethods
|
|
94
|
+
& { [K in keyof TDef["meta"]["tables"]]: () => Queryable<...> }
|
|
95
|
+
& { [K in keyof TDef["meta"]["views"]]: () => Queryable<...> }
|
|
96
|
+
& { [K in keyof TDef["meta"]["procedures"]]: () => Executable<...> }
|
|
97
|
+
& {
|
|
98
|
+
_migration: () => Queryable<{ code: string }, any>;
|
|
99
|
+
initialize(options?: { dbs?: string[]; force?: boolean }): Promise<void>;
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## DbContextBase
|
|
104
|
+
|
|
105
|
+
Core interface used internally by Queryable, Executable, and ViewBuilder.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
interface DbContextBase {
|
|
109
|
+
status: DbContextStatus;
|
|
110
|
+
readonly database: string | undefined;
|
|
111
|
+
readonly schema: string | undefined;
|
|
112
|
+
getNextAlias(): string;
|
|
113
|
+
resetAliasCounter(): void;
|
|
114
|
+
executeDefs<T = DataRecord>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]>;
|
|
115
|
+
getQueryDefObjectName(tableOrView: TableBuilder | ViewBuilder): QueryDefObjectName;
|
|
116
|
+
switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## DbContextStatus
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
type DbContextStatus = "ready" | "connect" | "transact";
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
| Value | Description |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `"ready"` | Not connected |
|
|
129
|
+
| `"connect"` | Connected, no active transaction |
|
|
130
|
+
| `"transact"` | Inside a transaction |
|
|
131
|
+
|
|
132
|
+
## DbContextConnectionMethods
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
interface DbContextConnectionMethods {
|
|
136
|
+
connect<TResult>(fn: () => Promise<TResult>, isolationLevel?: IsolationLevel): Promise<TResult>;
|
|
137
|
+
connectWithoutTransaction<TResult>(callback: () => Promise<TResult>): Promise<TResult>;
|
|
138
|
+
transaction<TResult>(fn: () => Promise<TResult>, isolationLevel?: IsolationLevel): Promise<TResult>;
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
| Method | Description |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `connect(fn, isolationLevel?)` | Connect, begin transaction, execute `fn`, commit. Auto-rollback on error. |
|
|
145
|
+
| `connectWithoutTransaction(fn)` | Connect and execute `fn` without a transaction. For DDL or read-only operations. |
|
|
146
|
+
| `transaction(fn, isolationLevel?)` | Begin a nested transaction within an existing connection. Use inside `connectWithoutTransaction`. |
|
|
147
|
+
|
|
148
|
+
## DbContextDdlMethods
|
|
149
|
+
|
|
150
|
+
DDL execution methods and QueryDef generators on `DbContextInstance`.
|
|
151
|
+
|
|
152
|
+
### Execution Methods
|
|
153
|
+
|
|
154
|
+
| Method | Signature | Description |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| `createTable` | `(table: TableBuilder) => Promise<void>` | Create a table |
|
|
157
|
+
| `dropTable` | `(table: QueryDefObjectName) => Promise<void>` | Drop a table |
|
|
158
|
+
| `renameTable` | `(table: QueryDefObjectName, newName: string) => Promise<void>` | Rename a table |
|
|
159
|
+
| `createView` | `(view: ViewBuilder) => Promise<void>` | Create a view |
|
|
160
|
+
| `dropView` | `(view: QueryDefObjectName) => Promise<void>` | Drop a view |
|
|
161
|
+
| `createProc` | `(procedure: ProcedureBuilder) => Promise<void>` | Create a stored procedure |
|
|
162
|
+
| `dropProc` | `(procedure: QueryDefObjectName) => Promise<void>` | Drop a stored procedure |
|
|
163
|
+
| `addColumn` | `(table, columnName, column: ColumnBuilder) => Promise<void>` | Add a column |
|
|
164
|
+
| `dropColumn` | `(table, column: string) => Promise<void>` | Drop a column |
|
|
165
|
+
| `modifyColumn` | `(table, columnName, column: ColumnBuilder) => Promise<void>` | Modify a column |
|
|
166
|
+
| `renameColumn` | `(table, column, newName) => Promise<void>` | Rename a column |
|
|
167
|
+
| `addPrimaryKey` | `(table, columns: string[]) => Promise<void>` | Add primary key |
|
|
168
|
+
| `dropPrimaryKey` | `(table) => Promise<void>` | Drop primary key |
|
|
169
|
+
| `addForeignKey` | `(table, relationName, relationDef: ForeignKeyBuilder) => Promise<void>` | Add foreign key |
|
|
170
|
+
| `addIndex` | `(table, indexBuilder: IndexBuilder) => Promise<void>` | Add index |
|
|
171
|
+
| `dropForeignKey` | `(table, relationName) => Promise<void>` | Drop foreign key |
|
|
172
|
+
| `dropIndex` | `(table, columns: string[]) => Promise<void>` | Drop index |
|
|
173
|
+
| `clearSchema` | `(params: { database; schema? }) => Promise<void>` | Clear all objects in schema |
|
|
174
|
+
| `schemaExists` | `(database, schema?) => Promise<boolean>` | Check if schema exists |
|
|
175
|
+
| `truncate` | `(table) => Promise<void>` | Truncate table |
|
|
176
|
+
| `switchFk` | `(table, enabled: boolean) => Promise<void>` | Enable/disable FK constraints |
|
|
177
|
+
|
|
178
|
+
### QueryDef Generator Methods
|
|
179
|
+
|
|
180
|
+
Each DDL execution method has a corresponding `get*QueryDef` method (e.g., `getCreateTableQueryDef`, `getDropTableQueryDef`) that returns a `QueryDef` without executing it. These are useful for building migration scripts or batching DDL operations.
|
|
181
|
+
|
|
182
|
+
## DbTransactionError
|
|
183
|
+
|
|
184
|
+
Standardized transaction error that wraps DBMS-native errors with a `DbErrorCode`.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
class DbTransactionError extends Error {
|
|
188
|
+
readonly name = "DbTransactionError";
|
|
189
|
+
constructor(
|
|
190
|
+
readonly code: DbErrorCode,
|
|
191
|
+
message: string,
|
|
192
|
+
readonly originalError?: unknown,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## DbErrorCode
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
enum DbErrorCode {
|
|
201
|
+
NO_ACTIVE_TRANSACTION = "NO_ACTIVE_TRANSACTION",
|
|
202
|
+
TRANSACTION_ALREADY_STARTED = "TRANSACTION_ALREADY_STARTED",
|
|
203
|
+
DEADLOCK = "DEADLOCK",
|
|
204
|
+
LOCK_TIMEOUT = "LOCK_TIMEOUT",
|
|
205
|
+
}
|
|
206
|
+
```
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# Expression DSL
|
|
2
|
+
|
|
3
|
+
Dialect-independent SQL expression builder. Generates JSON AST (`Expr`) instead of SQL strings. The QueryBuilder transforms the AST to target DBMS syntax.
|
|
4
|
+
|
|
5
|
+
## expr
|
|
6
|
+
|
|
7
|
+
Constant object with all expression builder methods. Used inside Queryable callbacks for `where()`, `select()`, `orderBy()`, etc.
|
|
8
|
+
|
|
9
|
+
### Value Generation
|
|
10
|
+
|
|
11
|
+
| Method | Signature | Description |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `val` | `(dataType: ColumnPrimitiveStr, value) => ExprUnit` | Wrap literal value as ExprUnit |
|
|
14
|
+
| `col` | `(dataType, ...path: string[]) => ExprUnit` | Generate column reference (internal use) |
|
|
15
|
+
| `raw` | `(dataType) => tagged template => ExprUnit` | Raw SQL expression (escape hatch). Interpolated values are auto-parameterized. |
|
|
16
|
+
|
|
17
|
+
**Example:**
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
expr.val("string", "active")
|
|
21
|
+
expr.val("number", 100)
|
|
22
|
+
expr.val("DateOnly", DateOnly.today())
|
|
23
|
+
expr.raw("string")`JSON_EXTRACT(${u.metadata}, '$.email')`
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Comparison Operators (WHERE)
|
|
27
|
+
|
|
28
|
+
| Method | Signature | Description |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `eq` | `(source, target) => WhereExprUnit` | Equality (NULL-safe: MySQL `<=>`) |
|
|
31
|
+
| `gt` | `(source, target) => WhereExprUnit` | Greater than (`>`) |
|
|
32
|
+
| `lt` | `(source, target) => WhereExprUnit` | Less than (`<`) |
|
|
33
|
+
| `gte` | `(source, target) => WhereExprUnit` | Greater than or equal (`>=`) |
|
|
34
|
+
| `lte` | `(source, target) => WhereExprUnit` | Less than or equal (`<=`) |
|
|
35
|
+
| `between` | `(source, from?, to?) => WhereExprUnit` | Range (BETWEEN). Undefined bounds are unbounded. |
|
|
36
|
+
|
|
37
|
+
### NULL Check
|
|
38
|
+
|
|
39
|
+
| Method | Signature | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `null` | `(source) => WhereExprUnit` | IS NULL check |
|
|
42
|
+
|
|
43
|
+
### String Search
|
|
44
|
+
|
|
45
|
+
| Method | Signature | Description |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `like` | `(source, pattern) => WhereExprUnit` | LIKE pattern matching (`%`, `_` wildcards) |
|
|
48
|
+
| `regexp` | `(source, pattern) => WhereExprUnit` | Regular expression matching |
|
|
49
|
+
|
|
50
|
+
### IN / EXISTS
|
|
51
|
+
|
|
52
|
+
| Method | Signature | Description |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `in` | `(source, values[]) => WhereExprUnit` | IN value list |
|
|
55
|
+
| `inQuery` | `(source, query: Queryable) => WhereExprUnit` | IN subquery (single-column SELECT) |
|
|
56
|
+
| `exists` | `(query: Queryable) => WhereExprUnit` | EXISTS subquery |
|
|
57
|
+
|
|
58
|
+
### Logical Operators
|
|
59
|
+
|
|
60
|
+
| Method | Signature | Description |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `not` | `(arg: WhereExprUnit) => WhereExprUnit` | NOT |
|
|
63
|
+
| `and` | `(conditions: WhereExprUnit[]) => WhereExprUnit` | AND (all must match) |
|
|
64
|
+
| `or` | `(conditions: WhereExprUnit[]) => WhereExprUnit` | OR (any must match) |
|
|
65
|
+
|
|
66
|
+
### String Functions (SELECT)
|
|
67
|
+
|
|
68
|
+
| Method | Signature | Description |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `concat` | `(...args) => ExprUnit<string>` | String concatenation (CONCAT) |
|
|
71
|
+
| `left` | `(source, length) => ExprUnit` | Left N characters |
|
|
72
|
+
| `right` | `(source, length) => ExprUnit` | Right N characters |
|
|
73
|
+
| `trim` | `(source) => ExprUnit` | Trim whitespace |
|
|
74
|
+
| `padStart` | `(source, length, fillString) => ExprUnit` | Left padding (LPAD) |
|
|
75
|
+
| `replace` | `(source, from, to) => ExprUnit` | String replacement |
|
|
76
|
+
| `upper` | `(source) => ExprUnit` | Uppercase |
|
|
77
|
+
| `lower` | `(source) => ExprUnit` | Lowercase |
|
|
78
|
+
| `length` | `(source) => ExprUnit<number>` | Character length |
|
|
79
|
+
| `byteLength` | `(source) => ExprUnit<number>` | Byte length |
|
|
80
|
+
| `substring` | `(source, start, length?) => ExprUnit` | Substring (1-based index) |
|
|
81
|
+
| `indexOf` | `(source, search) => ExprUnit<number>` | Find position (1-based, 0 if not found) |
|
|
82
|
+
|
|
83
|
+
### Number Functions (SELECT)
|
|
84
|
+
|
|
85
|
+
| Method | Signature | Description |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `abs` | `(source) => ExprUnit` | Absolute value |
|
|
88
|
+
| `round` | `(source, digits) => ExprUnit` | Round |
|
|
89
|
+
| `ceil` | `(source) => ExprUnit` | Ceiling |
|
|
90
|
+
| `floor` | `(source) => ExprUnit` | Floor |
|
|
91
|
+
|
|
92
|
+
### Date/Time Functions (SELECT)
|
|
93
|
+
|
|
94
|
+
| Method | Signature | Description |
|
|
95
|
+
|---|---|---|
|
|
96
|
+
| `year` | `(source) => ExprUnit<number>` | Extract year |
|
|
97
|
+
| `month` | `(source) => ExprUnit<number>` | Extract month |
|
|
98
|
+
| `day` | `(source) => ExprUnit<number>` | Extract day |
|
|
99
|
+
| `hour` | `(source) => ExprUnit<number>` | Extract hour |
|
|
100
|
+
| `minute` | `(source) => ExprUnit<number>` | Extract minute |
|
|
101
|
+
| `second` | `(source) => ExprUnit<number>` | Extract second |
|
|
102
|
+
| `isoWeek` | `(source) => ExprUnit<number>` | ISO week number |
|
|
103
|
+
| `isoWeekStartDate` | `(source) => ExprUnit<DateOnly>` | ISO week start date (Monday) |
|
|
104
|
+
| `isoYearMonth` | `(source) => ExprUnit<DateOnly>` | ISO year-month (YYYYMM format) |
|
|
105
|
+
| `dateDiff` | `(unit: DateUnit, from, to) => ExprUnit<number>` | Date difference |
|
|
106
|
+
| `dateAdd` | `(unit: DateUnit, source, value) => ExprUnit` | Date arithmetic |
|
|
107
|
+
| `formatDate` | `(source, format: string) => ExprUnit<string>` | Date formatting |
|
|
108
|
+
|
|
109
|
+
### Conditional
|
|
110
|
+
|
|
111
|
+
| Method | Signature | Description |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| `coalesce` | `(...args) => ExprUnit` | First non-null value (COALESCE) |
|
|
114
|
+
| `nullIf` | `(source, value) => ExprUnit` | NULL if equal (NULLIF) |
|
|
115
|
+
| `is` | `(condition: WhereExprUnit) => ExprUnit<boolean>` | Convert condition to boolean (0/1) |
|
|
116
|
+
| `switch` | `() => SwitchExprBuilder` | CASE WHEN expression (chain `.case().default()`) |
|
|
117
|
+
| `if` | `(condition, then, else?) => ExprUnit` | IIF conditional expression |
|
|
118
|
+
|
|
119
|
+
### Aggregate Functions
|
|
120
|
+
|
|
121
|
+
| Method | Signature | Description |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `count` | `(arg?, distinct?) => ExprUnit<number>` | COUNT |
|
|
124
|
+
| `sum` | `(arg) => ExprUnit<number \| undefined>` | SUM |
|
|
125
|
+
| `avg` | `(arg) => ExprUnit<number \| undefined>` | AVG |
|
|
126
|
+
| `max` | `(arg) => ExprUnit<T \| undefined>` | MAX |
|
|
127
|
+
| `min` | `(arg) => ExprUnit<T \| undefined>` | MIN |
|
|
128
|
+
|
|
129
|
+
### Utility
|
|
130
|
+
|
|
131
|
+
| Method | Signature | Description |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| `greatest` | `(...args) => ExprUnit` | Greatest of values |
|
|
134
|
+
| `least` | `(...args) => ExprUnit` | Least of values |
|
|
135
|
+
| `rowNum` | `() => ExprUnit<number>` | Simple row number |
|
|
136
|
+
| `random` | `() => ExprUnit<number>` | Random number (RAND/RANDOM) |
|
|
137
|
+
| `cast` | `(source, targetType: DataType) => ExprUnit` | Type cast |
|
|
138
|
+
| `subquery` | `(dataType, queryDef: SelectQueryDef) => ExprUnit` | Scalar subquery |
|
|
139
|
+
| `toExpr` | `(value: ExprInput) => Expr` | Convert ExprInput to raw Expr AST |
|
|
140
|
+
|
|
141
|
+
### Window Functions
|
|
142
|
+
|
|
143
|
+
All window functions accept a `WinSpecInput: { partitionBy?: ExprInput[]; orderBy?: [ExprInput, ("ASC" | "DESC")?][] }`.
|
|
144
|
+
|
|
145
|
+
| Method | Signature | Description |
|
|
146
|
+
|---|---|---|
|
|
147
|
+
| `rowNumber` | `(spec) => ExprUnit<number>` | ROW_NUMBER() OVER(...) |
|
|
148
|
+
| `rank` | `(spec) => ExprUnit<number>` | RANK() OVER(...) |
|
|
149
|
+
| `denseRank` | `(spec) => ExprUnit<number>` | DENSE_RANK() OVER(...) |
|
|
150
|
+
| `ntile` | `(n, spec) => ExprUnit<number>` | NTILE(n) OVER(...) |
|
|
151
|
+
| `lag` | `(column, spec, offset?, defaultValue?) => ExprUnit` | Previous row value |
|
|
152
|
+
| `lead` | `(column, spec, offset?, defaultValue?) => ExprUnit` | Next row value |
|
|
153
|
+
| `firstValue` | `(column, spec) => ExprUnit` | First value in partition |
|
|
154
|
+
| `lastValue` | `(column, spec) => ExprUnit` | Last value in partition |
|
|
155
|
+
| `sumOver` | `(column, spec) => ExprUnit<number \| undefined>` | Window SUM |
|
|
156
|
+
| `avgOver` | `(column, spec) => ExprUnit<number \| undefined>` | Window AVG |
|
|
157
|
+
| `countOver` | `(spec, column?) => ExprUnit<number>` | Window COUNT |
|
|
158
|
+
| `minOver` | `(column, spec) => ExprUnit` | Window MIN |
|
|
159
|
+
| `maxOver` | `(column, spec) => ExprUnit` | Window MAX |
|
|
160
|
+
|
|
161
|
+
## SwitchExprBuilder
|
|
162
|
+
|
|
163
|
+
Builder interface for CASE WHEN expressions. Created by `expr.switch()`.
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
interface SwitchExprBuilder<TPrimitive extends ColumnPrimitive> {
|
|
167
|
+
case(condition: WhereExprUnit, then: ExprInput<TPrimitive>): SwitchExprBuilder<TPrimitive>;
|
|
168
|
+
default(value: ExprInput<TPrimitive>): ExprUnit<TPrimitive>;
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Example:**
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
db.user().select((u) => ({
|
|
176
|
+
tier: expr.switch<string>()
|
|
177
|
+
.case(expr.gte(u.score, 90), "gold")
|
|
178
|
+
.case(expr.gte(u.score, 70), "silver")
|
|
179
|
+
.default("bronze"),
|
|
180
|
+
}))
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## ExprUnit
|
|
184
|
+
|
|
185
|
+
Type-safe expression wrapper that tracks the return type through TypeScript generics.
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
class ExprUnit<TPrimitive extends ColumnPrimitive> {
|
|
189
|
+
readonly $infer!: TPrimitive;
|
|
190
|
+
readonly dataType: ColumnPrimitiveStr;
|
|
191
|
+
readonly expr: Expr;
|
|
192
|
+
|
|
193
|
+
/** Non-nullable assertion accessor */
|
|
194
|
+
get n(): ExprUnit<NonNullable<TPrimitive>>;
|
|
195
|
+
|
|
196
|
+
constructor(dataType: ColumnPrimitiveStr, expr: Expr);
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## WhereExprUnit
|
|
201
|
+
|
|
202
|
+
WHERE clause expression wrapper.
|
|
203
|
+
|
|
204
|
+
```typescript
|
|
205
|
+
class WhereExprUnit {
|
|
206
|
+
readonly expr: WhereExpr;
|
|
207
|
+
constructor(expr: WhereExpr);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## ExprInput
|
|
212
|
+
|
|
213
|
+
Union type accepting either an `ExprUnit` or a literal value.
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
type ExprInput<TPrimitive extends ColumnPrimitive> = ExprUnit<TPrimitive> | TPrimitive;
|
|
217
|
+
```
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Query Builder
|
|
2
|
+
|
|
3
|
+
Transforms `QueryDef` AST into dialect-specific SQL strings.
|
|
4
|
+
|
|
5
|
+
## createQueryBuilder
|
|
6
|
+
|
|
7
|
+
Factory function that creates the appropriate `QueryBuilderBase` for a given dialect.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
function createQueryBuilder(dialect: Dialect): QueryBuilderBase;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Parameters:**
|
|
14
|
+
|
|
15
|
+
| Parameter | Type | Description |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `dialect` | `"mysql" \| "mssql" \| "postgresql"` | Target database dialect |
|
|
18
|
+
|
|
19
|
+
**Returns:** `QueryBuilderBase` instance (`MysqlQueryBuilder`, `MssqlQueryBuilder`, or `PostgresqlQueryBuilder`)
|
|
20
|
+
|
|
21
|
+
**Example:**
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
const builder = createQueryBuilder("mysql");
|
|
25
|
+
const result = builder.build(selectQueryDef);
|
|
26
|
+
console.log(result.sql);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## QueryBuilderBase
|
|
30
|
+
|
|
31
|
+
Abstract base class for QueryDef-to-SQL rendering. Implements dispatch logic shared across all dialects. Dialect-specific differences are delegated to abstract methods.
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
abstract class QueryBuilderBase {
|
|
35
|
+
abstract readonly exprRenderer: ExprRendererBase;
|
|
36
|
+
|
|
37
|
+
build(def: QueryDef): QueryBuildResult;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### build
|
|
42
|
+
|
|
43
|
+
The main entry point. Accepts any `QueryDef` (SELECT, INSERT, UPDATE, DELETE, UPSERT, DDL, etc.) and returns a `QueryBuildResult` containing the SQL string and optional result set metadata.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
build(def: QueryDef): QueryBuildResult;
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Returns:** `QueryBuildResult` with:
|
|
50
|
+
|
|
51
|
+
| Field | Type | Description |
|
|
52
|
+
|---|---|---|
|
|
53
|
+
| `sql` | `string` | Generated SQL |
|
|
54
|
+
| `resultSetIndex?` | `number` | Which result set to read (default: 0) |
|
|
55
|
+
| `resultSetStride?` | `number` | For multi-result sets, read every Nth |
|
|
56
|
+
|
|
57
|
+
## ExprRendererBase
|
|
58
|
+
|
|
59
|
+
Abstract base class for rendering `Expr` and `WhereExpr` AST nodes to SQL strings. Each dialect implements its own renderer for DBMS-specific syntax.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
abstract class ExprRendererBase {
|
|
63
|
+
render(expr: Expr): string;
|
|
64
|
+
renderWhere(expr: WhereExpr): string;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## MysqlQueryBuilder
|
|
69
|
+
|
|
70
|
+
MySQL-specific query builder. Extends `QueryBuilderBase`.
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
class MysqlQueryBuilder extends QueryBuilderBase {
|
|
74
|
+
readonly exprRenderer: MysqlExprRenderer;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
MySQL-specific behaviors:
|
|
79
|
+
- Uses `<=>` for NULL-safe equality
|
|
80
|
+
- Uses backtick quoting for identifiers
|
|
81
|
+
- INSERT OUTPUT via separate SELECT with `LAST_INSERT_ID()`
|
|
82
|
+
- UPSERT via `INSERT ... ON DUPLICATE KEY UPDATE`
|
|
83
|
+
|
|
84
|
+
## MssqlQueryBuilder
|
|
85
|
+
|
|
86
|
+
MSSQL-specific query builder. Extends `QueryBuilderBase`.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
class MssqlQueryBuilder extends QueryBuilderBase {
|
|
90
|
+
readonly exprRenderer: MssqlExprRenderer;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
MSSQL-specific behaviors:
|
|
95
|
+
- Uses `[` `]` for identifier quoting
|
|
96
|
+
- TOP instead of LIMIT
|
|
97
|
+
- OUTPUT clause for INSERT/UPDATE/DELETE
|
|
98
|
+
- `IDENTITY_INSERT` for auto-increment override
|
|
99
|
+
- `OFFSET...FETCH` for pagination
|
|
100
|
+
|
|
101
|
+
## PostgresqlQueryBuilder
|
|
102
|
+
|
|
103
|
+
PostgreSQL-specific query builder. Extends `QueryBuilderBase`.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
class PostgresqlQueryBuilder extends QueryBuilderBase {
|
|
107
|
+
readonly exprRenderer: PostgresqlExprRenderer;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
PostgreSQL-specific behaviors:
|
|
112
|
+
- Uses `"` for identifier quoting
|
|
113
|
+
- `RETURNING` clause for INSERT/UPDATE/DELETE output
|
|
114
|
+
- `LIMIT...OFFSET` for pagination
|
|
115
|
+
- `LATERAL` subquery JOINs
|
|
116
|
+
- `IS NOT DISTINCT FROM` for NULL-safe equality
|
|
117
|
+
|
|
118
|
+
## Dialect-Specific Expression Renderers
|
|
119
|
+
|
|
120
|
+
| Class | Dialect | Description |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| `MysqlExprRenderer` | MySQL | Renders Expr AST to MySQL SQL syntax |
|
|
123
|
+
| `MssqlExprRenderer` | MSSQL | Renders Expr AST to MSSQL SQL syntax |
|
|
124
|
+
| `PostgresqlExprRenderer` | PostgreSQL | Renders Expr AST to PostgreSQL SQL syntax |
|
|
125
|
+
|
|
126
|
+
Each renderer extends `ExprRendererBase` and overrides methods for dialect-specific expression rendering (e.g., date functions, string functions, type casting).
|