@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.
Files changed (59) hide show
  1. package/README.md +135 -0
  2. package/dist/exec/queryable.js +18 -18
  3. package/dist/exec/queryable.js.map +1 -1
  4. package/dist/expr/expr.d.ts +102 -102
  5. package/dist/expr/expr.js +105 -105
  6. package/dist/expr/expr.js.map +1 -1
  7. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +1 -1
  8. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  9. package/dist/query-builder/mssql/mssql-expr-renderer.js +17 -17
  10. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  11. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  12. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  13. package/dist/query-builder/mssql/mssql-query-builder.js +26 -26
  14. package/dist/query-builder/mssql/mssql-query-builder.js.map +1 -1
  15. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +1 -1
  16. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  17. package/dist/query-builder/mysql/mysql-expr-renderer.js +14 -14
  18. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  19. package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
  20. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  21. package/dist/query-builder/mysql/mysql-query-builder.js +67 -67
  22. package/dist/query-builder/mysql/mysql-query-builder.js.map +1 -1
  23. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +1 -1
  24. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  25. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +13 -13
  26. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  27. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
  28. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  29. package/dist/query-builder/postgresql/postgresql-query-builder.js +47 -47
  30. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  31. package/dist/schema/factory/relation-builder.d.ts +8 -8
  32. package/dist/schema/factory/relation-builder.js +9 -9
  33. package/dist/schema/factory/relation-builder.js.map +1 -1
  34. package/dist/schema/view-builder.js +2 -2
  35. package/dist/schema/view-builder.js.map +1 -1
  36. package/dist/types/column.d.ts +21 -21
  37. package/dist/types/column.js +5 -5
  38. package/dist/utils/result-parser.d.ts +11 -11
  39. package/dist/utils/result-parser.js +48 -48
  40. package/dist/utils/result-parser.js.map +1 -1
  41. package/docs/core.md +206 -0
  42. package/docs/expression.md +217 -0
  43. package/docs/query-builder.md +126 -0
  44. package/docs/queryable.md +236 -0
  45. package/docs/schema-builders.md +352 -0
  46. package/docs/types.md +501 -0
  47. package/package.json +7 -3
  48. package/src/exec/queryable.ts +18 -18
  49. package/src/expr/expr.ts +105 -105
  50. package/src/query-builder/mssql/mssql-expr-renderer.ts +17 -17
  51. package/src/query-builder/mssql/mssql-query-builder.ts +26 -26
  52. package/src/query-builder/mysql/mysql-expr-renderer.ts +14 -14
  53. package/src/query-builder/mysql/mysql-query-builder.ts +67 -67
  54. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +13 -13
  55. package/src/query-builder/postgresql/postgresql-query-builder.ts +47 -47
  56. package/src/schema/factory/relation-builder.ts +9 -9
  57. package/src/schema/view-builder.ts +2 -2
  58. package/src/types/column.ts +23 -23
  59. 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).