@simplysm/orm-common 14.0.23 → 14.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/orm-common",
3
- "version": "14.0.23",
3
+ "version": "14.0.24",
4
4
  "description": "심플리즘 패키지 - ORM (common)",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",
@@ -14,14 +14,13 @@
14
14
  "types": "./dist/index.d.ts",
15
15
  "files": [
16
16
  "dist",
17
- "src",
18
- "docs"
17
+ "src"
19
18
  ],
20
19
  "sideEffects": false,
21
20
  "devDependencies": {
22
21
  "@types/node": "^20.19.39"
23
22
  },
24
23
  "dependencies": {
25
- "@simplysm/core-common": "14.0.23"
24
+ "@simplysm/core-common": "14.0.24"
26
25
  }
27
26
  }
package/README.md DELETED
@@ -1,170 +0,0 @@
1
- # @simplysm/orm-common
2
-
3
- Platform-neutral ORM module for the Simplysm framework. Provides type-safe query building, schema definition, expression building, and DDL generation for MySQL, MSSQL, and PostgreSQL.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @simplysm/orm-common
9
- # or
10
- pnpm add @simplysm/orm-common
11
- ```
12
-
13
- ## API Overview
14
-
15
- ### Core
16
-
17
- | Export | Type | Description |
18
- |--------|------|-------------|
19
- | [`DbContext`](./docs/core.md#dbcontext) | Abstract Class | Base class for database contexts with connection, transaction, DDL, and initialization |
20
- | [`SD_BUILDER`](./docs/core.md#sd_builder) | Symbol | Internal marker for queryable/executable builder identification |
21
- | [`DbTransactionError`](./docs/core.md#dbtransactionerror) | Class | Standardized database transaction error with DBMS-independent error codes |
22
- | [`DbErrorCode`](./docs/core.md#dberrorcode) | Enum | Transaction error codes |
23
- | [`DbContextBase`](./docs/core.md#dbcontextbase) | Interface | Core interface for Queryable/Executable internal use |
24
- | [`DbContextDdlMethods`](./docs/core.md#dbcontextddlmethods) | Interface | DDL execution and QueryDef generator methods |
25
- | [`DbContextStatus`](./docs/core.md#dbcontextstatus) | Type | Connection status: "ready", "connect", "transact" |
26
- | [`_Migration`](./docs/core.md#_migration) | Constant | System migration table definition (TableBuilder) |
27
-
28
- ### Queryable / Executable
29
-
30
- | Export | Type | Description |
31
- |--------|------|-------------|
32
- | [`Queryable`](./docs/queryable.md#queryable) | Class | Fluent query builder for SELECT, INSERT, UPDATE, DELETE, UPSERT |
33
- | [`queryable`](./docs/queryable.md#queryable-factory) | Function | Factory to create Queryable accessors for tables/views |
34
- | [`Executable`](./docs/queryable.md#executable) | Class | Stored procedure execution wrapper |
35
- | [`executable`](./docs/queryable.md#executable-factory) | Function | Factory to create Executable accessors for procedures |
36
- | [`parseSearchQuery`](./docs/queryable.md#parsesearchquery) | Function | Parse search query string into SQL LIKE patterns |
37
- | [`ParsedSearchQuery`](./docs/queryable.md#parsedsearchquery) | Interface | Parsed search query result |
38
- | [`getMatchedPrimaryKeys`](./docs/queryable.md#getmatchedprimarykeys) | Function | Match FK columns with target table PK columns |
39
- | [`QueryableRecord`](./docs/queryable.md#queryablerecord) | Type | Maps DataRecord fields to ExprUnit proxies |
40
- | [`QueryableWriteRecord`](./docs/queryable.md#queryablewriterecord) | Type | Maps DataRecord fields to ExprInput for writes |
41
- | [`NullableQueryableRecord`](./docs/queryable.md#nullablequeryablerecord) | Type | QueryableRecord with nullable primitives (for LEFT JOIN) |
42
- | [`UnwrapQueryableRecord`](./docs/queryable.md#unwrapqueryablerecord) | Type | Reverse-map QueryableRecord to DataRecord |
43
- | [`PathProxy`](./docs/queryable.md#pathproxy) | Type | Type-safe path proxy for `include()` |
44
-
45
- ### Expression Builder
46
-
47
- | Export | Type | Description |
48
- |--------|------|-------------|
49
- | [`expr`](./docs/expression.md#expr-object) | Object | Dialect-independent SQL expression builder (100+ methods) |
50
- | [`ExprUnit`](./docs/expression.md#exprunit) | Class | Type-safe expression wrapper |
51
- | [`WhereExprUnit`](./docs/expression.md#whereexprunit) | Class | WHERE clause expression wrapper |
52
- | [`ExprInput`](./docs/expression.md#exprinput) | Type | Union of ExprUnit or literal values |
53
- | [`SwitchExprBuilder`](./docs/expression.md#switchexprbuilder) | Interface | CASE WHEN builder (fluent API) |
54
- | [`toExpr`](./docs/expression.md#toexpr) | Function | Convert ExprInput to Expr JSON AST |
55
-
56
- ### Schema Builders
57
-
58
- | Export | Type | Description |
59
- |--------|------|-------------|
60
- | [`Table`](./docs/schema-builders.md#table-function) | Function | Create a TableBuilder |
61
- | [`TableBuilder`](./docs/schema-builders.md#tablebuilder) | Class | Fluent API for table definitions |
62
- | [`View`](./docs/schema-builders.md#view-function) | Function | Create a ViewBuilder |
63
- | [`ViewBuilder`](./docs/schema-builders.md#viewbuilder) | Class | Fluent API for view definitions |
64
- | [`Procedure`](./docs/schema-builders.md#procedure-function) | Function | Create a ProcedureBuilder |
65
- | [`ProcedureBuilder`](./docs/schema-builders.md#procedurebuilder) | Class | Fluent API for stored procedure definitions |
66
- | [`ColumnBuilder`](./docs/schema-builders.md#columnbuilder) | Class | Column definition builder |
67
- | [`createColumnFactory`](./docs/schema-builders.md#createcolumnfactory) | Function | Column type factory |
68
- | [`IndexBuilder`](./docs/schema-builders.md#indexbuilder) | Class | Index definition builder |
69
- | [`createIndexFactory`](./docs/schema-builders.md#createindexfactory) | Function | Index factory |
70
- | [`ForeignKeyBuilder`](./docs/schema-builders.md#foreignkeybuilder) | Class | FK relation builder (N:1, configured via factory opts) |
71
- | [`ForeignKeyTargetBuilder`](./docs/schema-builders.md#foreignkeytargetbuilder) | Class | FK reverse-reference builder (1:N/1:1, configured via factory opts) |
72
- | [`RelationKeyBuilder`](./docs/schema-builders.md#relationkeybuilder) | Class | Logical relation builder (no DB FK, configured via factory opts) |
73
- | [`RelationKeyTargetBuilder`](./docs/schema-builders.md#relationkeytargetbuilder) | Class | Logical reverse-reference builder (configured via factory opts) |
74
- | [`createRelationFactory`](./docs/schema-builders.md#createrelationfactory) | Function | Relation factory |
75
-
76
- ### Query Builder & Result Parsing
77
-
78
- | Export | Type | Description |
79
- |--------|------|-------------|
80
- | [`createQueryBuilder`](./docs/query-builder.md#createquerybuilder) | Function | Create a dialect-specific QueryBuilder |
81
- | [`QueryBuilderBase`](./docs/query-builder.md#querybuilderbase) | Abstract Class | Base for QueryDef to SQL rendering |
82
- | [`MysqlQueryBuilder`](./docs/query-builder.md#dialect-specific-query-builders) | Class | MySQL query builder |
83
- | [`MssqlQueryBuilder`](./docs/query-builder.md#dialect-specific-query-builders) | Class | MSSQL query builder |
84
- | [`PostgresqlQueryBuilder`](./docs/query-builder.md#dialect-specific-query-builders) | Class | PostgreSQL query builder |
85
- | [`ExprRendererBase`](./docs/query-builder.md#exprrendererbase) | Abstract Class | Base for Expr to SQL rendering |
86
- | [`MysqlExprRenderer`](./docs/query-builder.md#dialect-specific-expression-renderers) | Class | MySQL expression renderer |
87
- | [`MssqlExprRenderer`](./docs/query-builder.md#dialect-specific-expression-renderers) | Class | MSSQL expression renderer |
88
- | [`PostgresqlExprRenderer`](./docs/query-builder.md#dialect-specific-expression-renderers) | Class | PostgreSQL expression renderer |
89
- | [`parseQueryResult`](./docs/query-builder.md#parsequeryresult) | Function | Parse raw DB results into typed objects |
90
-
91
- ### Types
92
-
93
- See [Types documentation](./docs/types.md) for all type exports including:
94
- - Database: `Dialect`, `dialects`, `IsolationLevel`, `DataRecord`, `DbContextExecutor`, `ResultMeta`, `Migration`, `QueryBuildResult`
95
- - Column: `DataType`, `ColumnPrimitive`, `ColumnPrimitiveStr`, `ColumnPrimitiveMap`, `ColumnMeta`, `dataTypeStrToColumnPrimitiveStr`, `inferColumnPrimitiveStr`, `InferColumnPrimitiveFromDataType`
96
- - Column Builder: `ColumnBuilderRecord`, `InferColumns`, `InferColumnExprs`, `InferInsertColumns`, `InferUpdateColumns`, `RequiredInsertKeys`, `OptionalInsertKeys`, `DataToColumnBuilderRecord`
97
- - Relation: `RelationBuilderRecord`, `InferDeepRelations`, `ExtractRelationTarget`, `ExtractRelationTargetResult`
98
- - Expression: `Expr` (50+ variants), `WhereExpr`, `DateUnit`, `WinFn`, `WinSpec`, all `Expr*` interfaces
99
- - QueryDef: `QueryDef` (30+ variants), `QueryDefObjectName`, `DDL_TYPES`, `DdlType`, all `*QueryDef` interfaces
100
-
101
- ## Usage Examples
102
-
103
- ### Define Schema and DbContext
104
-
105
- ```typescript
106
- import { Table, DbContext, expr } from "@simplysm/orm-common";
107
-
108
- const User = Table("User")
109
- .columns((c) => ({
110
- id: c.bigint().autoIncrement(),
111
- name: c.varchar(100),
112
- email: c.varchar(200).nullable(),
113
- companyId: c.bigint(),
114
- }))
115
- .primaryKey("id")
116
- .indexes((i) => [i.index("email").unique()])
117
- .relations((r) => ({
118
- company: r.foreignKey(["companyId"], () => Company, { description: "Company" }),
119
- posts: r.foreignKeyTarget(() => Post, "author"),
120
- topPost: r.foreignKeyTarget(() => Post, "author", { single: true, description: "Top post" }),
121
- }));
122
-
123
- class MyDb extends DbContext {
124
- user = this.queryable(User);
125
- post = this.queryable(Post);
126
- company = this.queryable(Company);
127
- }
128
-
129
- const db = new MyDb(executor, { database: "mydb" });
130
- ```
131
-
132
- ### Query Data
133
-
134
- ```typescript
135
- await db.connect(async () => {
136
- const users = await db.user()
137
- .where((u) => [expr.eq(u.name, "Alice")])
138
- .orderBy((u) => u.name)
139
- .execute();
140
-
141
- const posts = await db.post().include((p) => p.author).execute();
142
-
143
- await db.user().insert([{ name: "New User", companyId: 1 }]);
144
-
145
- await db.user()
146
- .where((u) => [expr.eq(u.id, 1)])
147
- .update(() => ({ name: expr.val("string", "Updated") }));
148
- });
149
- ```
150
-
151
- ### Expression Builder
152
-
153
- ```typescript
154
- // Window functions
155
- db.order().select((o) => ({
156
- ...o,
157
- rowNum: expr.rowNumber({ partitionBy: [o.userId], orderBy: [[o.createdAt, "DESC"]] }),
158
- }));
159
-
160
- // CASE WHEN
161
- db.user().select((u) => ({
162
- grade: expr.switch<string>()
163
- .case(expr.gte(u.score, 90), "A")
164
- .default("C"),
165
- }));
166
-
167
- // Search parser
168
- const parsed = parseSearchQuery('+apple -banana "exact phrase"');
169
- // { must: ["%apple%", "%exact phrase%"], not: ["%banana%"], or: [] }
170
- ```
package/docs/core.md DELETED
@@ -1,217 +0,0 @@
1
- # Core
2
-
3
- DbContext abstract class, connection/transaction lifecycle, DDL execution, and initialization.
4
-
5
- ## DbContext
6
-
7
- ```typescript
8
- abstract class DbContext implements DbContextBase {
9
- status: DbContextStatus;
10
-
11
- constructor(
12
- executor: DbContextExecutor,
13
- opt: { database: string; schema?: string },
14
- )
15
-
16
- // Registration
17
- protected queryable<T extends TableBuilder | ViewBuilder>(builder: T): () => Queryable<...>
18
- protected executable<T extends ProcedureBuilder>(builder: T): () => Executable<...>
19
-
20
- // Connection
21
- connect<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>
22
- connectWithoutTransaction<R>(fn: () => Promise<R>): Promise<R>
23
- transaction<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel): Promise<R>
24
-
25
- // DDL execution (see DDL Execution Methods below)
26
- // DDL QueryDef generators (get*QueryDef methods)
27
-
28
- // Initialization
29
- initialize(options?: { dbs?: string[]; force?: boolean }): Promise<void>
30
-
31
- // Override in subclass
32
- migrations: Migration[];
33
- }
34
- ```
35
-
36
- Base class for database contexts. Subclass to define tables, views, and procedures as class properties.
37
-
38
- Each property registered via `queryable()` or `executable()` is independently serialized, avoiding TS7056 even with 40+ tables.
39
-
40
- | Constructor Parameter | Type | Description |
41
- |---|---|---|
42
- | `executor` | `DbContextExecutor` | Query execution engine (e.g., `NodeDbContextExecutor`) |
43
- | `opt.database` | `string` | Database name |
44
- | `opt.schema` | `string?` | Schema name (MSSQL: dbo, PostgreSQL: public) |
45
-
46
- ```typescript
47
- class MainDb extends DbContext {
48
- user = this.queryable(User);
49
- post = this.queryable(Post);
50
- getUserById = this.executable(GetUserById);
51
-
52
- migrations = [
53
- { name: "20260101_001_init", up: async (db) => { await db.createTable(User); } },
54
- ];
55
- }
56
-
57
- const db = new MainDb(executor, { database: "mydb", schema: "dbo" });
58
- ```
59
-
60
- ### Connection Methods
61
-
62
- | Method | Signature | Description |
63
- |--------|-----------|-------------|
64
- | `connect` | `<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel) => Promise<R>` | Connect, begin transaction, execute callback, commit (auto-rollback on error) |
65
- | `connectWithoutTransaction` | `<R>(fn: () => Promise<R>) => Promise<R>` | Connect without transaction, execute callback, close |
66
- | `transaction` | `<R>(fn: () => Promise<R>, isolationLevel?: IsolationLevel) => Promise<R>` | Begin transaction within existing connection (for use inside `connectWithoutTransaction`) |
67
-
68
- ### DDL Execution Methods
69
-
70
- | Method | Signature |
71
- |--------|-----------|
72
- | `createTable` | `(table: TableBuilder) => Promise<void>` |
73
- | `dropTable` | `(table: QueryDefObjectName) => Promise<void>` |
74
- | `renameTable` | `(table: QueryDefObjectName, newName: string) => Promise<void>` |
75
- | `createView` | `(view: ViewBuilder) => Promise<void>` |
76
- | `dropView` | `(view: QueryDefObjectName) => Promise<void>` |
77
- | `createProc` | `(procedure: ProcedureBuilder) => Promise<void>` |
78
- | `dropProc` | `(procedure: QueryDefObjectName) => Promise<void>` |
79
- | `addColumn` | `(table: QueryDefObjectName, columnName: string, column: ColumnBuilder) => Promise<void>` |
80
- | `dropColumn` | `(table: QueryDefObjectName, column: string) => Promise<void>` |
81
- | `modifyColumn` | `(table: QueryDefObjectName, columnName: string, column: ColumnBuilder) => Promise<void>` |
82
- | `renameColumn` | `(table: QueryDefObjectName, column: string, newName: string) => Promise<void>` |
83
- | `addPrimaryKey` | `(table: QueryDefObjectName, columns: string[]) => Promise<void>` |
84
- | `dropPrimaryKey` | `(table: QueryDefObjectName) => Promise<void>` |
85
- | `addForeignKey` | `(table: QueryDefObjectName, relationName: string, relationDef: ForeignKeyBuilder) => Promise<void>` |
86
- | `addIndex` | `(table: QueryDefObjectName, indexBuilder: IndexBuilder) => Promise<void>` |
87
- | `dropForeignKey` | `(table: QueryDefObjectName, relationName: string) => Promise<void>` |
88
- | `dropIndex` | `(table: QueryDefObjectName, columns: string[]) => Promise<void>` |
89
- | `clearSchema` | `(params: { database: string; schema?: string }) => Promise<void>` |
90
- | `schemaExists` | `(database: string, schema?: string) => Promise<boolean>` |
91
- | `truncate` | `(table: QueryDefObjectName) => Promise<void>` |
92
- | `switchFk` | `(table: QueryDefObjectName, enabled: boolean) => Promise<void>` |
93
-
94
- ### DDL QueryDef Generators
95
-
96
- Each DDL method has a corresponding `get*QueryDef` method that returns a `QueryDef` without executing it. For example: `getCreateTableQueryDef(table)`, `getDropTableQueryDef(table)`, `getCreateObjectQueryDef(builder)`, etc.
97
-
98
- ### Initialize
99
-
100
- ```typescript
101
- async initialize(options?: { dbs?: string[]; force?: boolean }): Promise<void>
102
- ```
103
-
104
- Code First database initialization. Creates all registered Table/View/Procedure objects and runs pending migrations.
105
-
106
- - **force=true**: Clear schema, recreate all objects, register all migrations as applied
107
- - **force=false** (default):
108
- - No `_Migration` table: Full creation + register all migrations
109
- - `_Migration` table exists: Run only pending migrations
110
-
111
- ## SD_BUILDER
112
-
113
- ```typescript
114
- const SD_BUILDER: unique symbol
115
- ```
116
-
117
- Internal symbol used to tag queryable/executable factory functions with their underlying builder. Used by `initialize()` to discover registered builders from DbContext instances.
118
-
119
- ## DbTransactionError
120
-
121
- ```typescript
122
- class DbTransactionError extends Error {
123
- readonly name = "DbTransactionError";
124
- constructor(
125
- public readonly code: DbErrorCode,
126
- message: string,
127
- public readonly originalError?: unknown,
128
- )
129
- }
130
- ```
131
-
132
- Wraps DBMS-native transaction errors into standardized error codes.
133
-
134
- | Field | Type | Description |
135
- |-------|------|-------------|
136
- | `code` | `DbErrorCode` | Standardized error code |
137
- | `message` | `string` | Error message |
138
- | `originalError` | `unknown?` | Original DBMS error (for debugging) |
139
-
140
- ## DbErrorCode
141
-
142
- ```typescript
143
- enum DbErrorCode {
144
- NO_ACTIVE_TRANSACTION = "NO_ACTIVE_TRANSACTION",
145
- TRANSACTION_ALREADY_STARTED = "TRANSACTION_ALREADY_STARTED",
146
- DEADLOCK = "DEADLOCK",
147
- LOCK_TIMEOUT = "LOCK_TIMEOUT",
148
- }
149
- ```
150
-
151
- | Value | Description |
152
- |-------|-------------|
153
- | `NO_ACTIVE_TRANSACTION` | No active transaction (e.g., rollback when no transaction) |
154
- | `TRANSACTION_ALREADY_STARTED` | Transaction already started |
155
- | `DEADLOCK` | Deadlock detected |
156
- | `LOCK_TIMEOUT` | Lock timeout exceeded |
157
-
158
- ## DbContextBase
159
-
160
- ```typescript
161
- interface DbContextBase {
162
- status: DbContextStatus;
163
- readonly database: string | undefined;
164
- readonly schema: string | undefined;
165
- getNextAlias(): string;
166
- resetAliasCounter(): void;
167
- executeDefs<T = DataRecord>(defs: QueryDef[], resultMetas?: (ResultMeta | undefined)[]): Promise<T[][]>;
168
- getQueryDefObjectName(tableOrView: TableBuilder | ViewBuilder): QueryDefObjectName;
169
- switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
170
- }
171
- ```
172
-
173
- Core interface implemented by DbContext. Used internally by Queryable, Executable, and ViewBuilder.
174
-
175
- | Field | Type | Description |
176
- |-------|------|-------------|
177
- | `status` | `DbContextStatus` | Current connection status |
178
- | `database` | `string \| undefined` | Database name |
179
- | `schema` | `string \| undefined` | Schema name |
180
- | `getNextAlias()` | `string` | Generate next table alias (T1, T2, ...) |
181
- | `resetAliasCounter()` | `void` | Reset alias counter |
182
- | `executeDefs()` | `Promise<T[][]>` | Execute QueryDef array, returns result per def |
183
- | `getQueryDefObjectName()` | `QueryDefObjectName` | Resolve table/view to qualified name |
184
- | `switchFk()` | `Promise<void>` | Enable/disable FK constraints |
185
-
186
- ## DbContextDdlMethods
187
-
188
- ```typescript
189
- interface DbContextDdlMethods {
190
- createTable(table: TableBuilder): Promise<void>;
191
- dropTable(table: QueryDefObjectName): Promise<void>;
192
- // ... all DDL methods listed in DbContext DDL Execution Methods above
193
- // ... plus all get*QueryDef generator methods
194
- }
195
- ```
196
-
197
- Interface for DDL execution and QueryDef generation methods. DbContext implements this interface. Used by the `initialize()` function and `Migration.up()` callback parameter type.
198
-
199
- ## DbContextStatus
200
-
201
- ```typescript
202
- type DbContextStatus = "ready" | "connect" | "transact";
203
- ```
204
-
205
- | Value | Description |
206
- |-------|-------------|
207
- | `"ready"` | Not connected |
208
- | `"connect"` | Connected, no active transaction |
209
- | `"transact"` | Connected with active transaction |
210
-
211
- ## _Migration
212
-
213
- ```typescript
214
- const _Migration: TableBuilder<{ code: ColumnBuilder<string, ...> }, {}>
215
- ```
216
-
217
- System migration tracking table. Automatically registered in every DbContext as `_migration`. Has a single `code` column (VARCHAR(255)) as primary key, storing executed migration names.
@@ -1,220 +0,0 @@
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
- ## ExprUnit
6
-
7
- ```typescript
8
- class ExprUnit<TPrimitive extends ColumnPrimitive> {
9
- readonly $infer!: TPrimitive;
10
- readonly dataType: ColumnPrimitiveStr;
11
- readonly expr: Expr;
12
- get n(): ExprUnit<NonNullable<TPrimitive>>;
13
- constructor(dataType: ColumnPrimitiveStr, expr: Expr);
14
- }
15
- ```
16
-
17
- Type-safe expression wrapper. Tracks the return type via the `TPrimitive` generic parameter.
18
-
19
- | Member | Type | Description |
20
- |--------|------|-------------|
21
- | `$infer` | `TPrimitive` | Type inference helper (phantom type) |
22
- | `dataType` | `ColumnPrimitiveStr` | Runtime type name (`"string"`, `"number"`, etc.) |
23
- | `expr` | `Expr` | Underlying JSON AST expression |
24
- | `n` | `ExprUnit<NonNullable<TPrimitive>>` | Getter that narrows nullable to non-nullable |
25
-
26
- ## WhereExprUnit
27
-
28
- ```typescript
29
- class WhereExprUnit {
30
- readonly expr: WhereExpr;
31
- constructor(expr: WhereExpr);
32
- }
33
- ```
34
-
35
- WHERE clause expression wrapper. Returned by comparison and logical methods on `expr`.
36
-
37
- ## ExprInput
38
-
39
- ```typescript
40
- type ExprInput<TPrimitive extends ColumnPrimitive> = ExprUnit<TPrimitive> | TPrimitive;
41
- ```
42
-
43
- Accepts either an `ExprUnit` or a literal value. Literal values are automatically wrapped.
44
-
45
- ## SwitchExprBuilder
46
-
47
- ```typescript
48
- interface SwitchExprBuilder<TPrimitive extends ColumnPrimitive> {
49
- case(condition: WhereExprUnit, then: ExprInput<TPrimitive>): SwitchExprBuilder<TPrimitive>;
50
- default(value: ExprInput<TPrimitive>): ExprUnit<TPrimitive>;
51
- }
52
- ```
53
-
54
- Fluent CASE WHEN builder. Chain `.case()` calls and terminate with `.default()`.
55
-
56
- ## expr Object
57
-
58
- The `expr` object provides all expression-building methods. Methods are grouped by category below.
59
-
60
- ### Value Creation
61
-
62
- | Method | Signature | Description |
63
- |--------|-----------|-------------|
64
- | `val` | `<TStr extends ColumnPrimitiveStr>(dataType: TStr, value: T) => ExprUnit` | Wrap a literal value into an ExprUnit |
65
- | `col` | `<TStr extends ColumnPrimitiveStr>(dataType: ColumnPrimitiveStr, ...path: string[]) => ExprUnit` | Create a column reference |
66
- | `raw` | `<T extends ColumnPrimitiveStr>(dataType: T) => (strings: TemplateStringsArray, ...values: ExprInput[]) => ExprUnit` | Raw SQL via tagged template literal; interpolated values become parameters |
67
-
68
- ### Comparison (WHERE)
69
-
70
- | Method | Signature | SQL | Description |
71
- |--------|-----------|-----|-------------|
72
- | `eq` | `(source: ExprUnit<T>, target: ExprInput<T>) => WhereExprUnit` | `<=>` / `IS NULL OR =` | NULL-safe equality |
73
- | `gt` | `(source: ExprUnit<T>, target: ExprInput<T>) => WhereExprUnit` | `>` | Greater than |
74
- | `lt` | `(source: ExprUnit<T>, target: ExprInput<T>) => WhereExprUnit` | `<` | Less than |
75
- | `gte` | `(source: ExprUnit<T>, target: ExprInput<T>) => WhereExprUnit` | `>=` | Greater than or equal |
76
- | `lte` | `(source: ExprUnit<T>, target: ExprInput<T>) => WhereExprUnit` | `<=` | Less than or equal |
77
- | `between` | `(source: ExprUnit<T>, from?: ExprInput<T>, to?: ExprInput<T>) => WhereExprUnit` | `BETWEEN` | Range comparison (undefined bounds omitted) |
78
-
79
- ### NULL Check (WHERE)
80
-
81
- | Method | Signature | SQL | Description |
82
- |--------|-----------|-----|-------------|
83
- | `null` | `(source: ExprUnit<T>) => WhereExprUnit` | `IS NULL` | NULL check |
84
-
85
- ### String Search (WHERE)
86
-
87
- | Method | Signature | SQL | Description |
88
- |--------|-----------|-----|-------------|
89
- | `like` | `(source: ExprUnit<string\|undefined>, pattern: ExprInput<string\|undefined>) => WhereExprUnit` | `LIKE ... ESCAPE '\'` | Pattern matching |
90
- | `regexp` | `(source: ExprUnit<string\|undefined>, pattern: ExprInput<string\|undefined>) => WhereExprUnit` | `REGEXP` | Regex matching |
91
-
92
- ### IN / EXISTS (WHERE)
93
-
94
- | Method | Signature | SQL | Description |
95
- |--------|-----------|-----|-------------|
96
- | `in` | `(source: ExprUnit<T>, values: ExprInput<T>[]) => WhereExprUnit` | `IN (...)` | List membership |
97
- | `inQuery` | `(source: ExprUnit<T>, query: Queryable<...>) => WhereExprUnit` | `IN (SELECT ...)` | Subquery membership (single column) |
98
- | `exists` | `(query: Queryable<any, any>) => WhereExprUnit` | `EXISTS (SELECT ...)` | Subquery existence check |
99
-
100
- ### Logical (WHERE)
101
-
102
- | Method | Signature | SQL | Description |
103
- |--------|-----------|-----|-------------|
104
- | `not` | `(arg: WhereExprUnit) => WhereExprUnit` | `NOT (...)` | Negate condition |
105
- | `and` | `(conditions: WhereExprUnit[]) => WhereExprUnit` | `... AND ...` | All conditions must match |
106
- | `or` | `(conditions: WhereExprUnit[]) => WhereExprUnit` | `... OR ...` | At least one condition must match |
107
-
108
- ### String Functions (SELECT)
109
-
110
- | Method | Signature | SQL | Description |
111
- |--------|-----------|-----|-------------|
112
- | `concat` | `(...args: ExprInput<string\|undefined>[]) => ExprUnit<string>` | `CONCAT(...)` | String concatenation (NULL becomes empty) |
113
- | `left` | `(source, length) => ExprUnit<T>` | `LEFT(source, n)` | Left substring |
114
- | `right` | `(source, length) => ExprUnit<T>` | `RIGHT(source, n)` | Right substring |
115
- | `trim` | `(source) => ExprUnit<T>` | `TRIM(source)` | Remove leading/trailing whitespace |
116
- | `padStart` | `(source, length, fillString) => ExprUnit<T>` | `LPAD(...)` | Left-pad to target length |
117
- | `replace` | `(source, from, to) => ExprUnit<T>` | `REPLACE(...)` | String replacement |
118
- | `upper` | `(source) => ExprUnit<T>` | `UPPER(source)` | Uppercase |
119
- | `lower` | `(source) => ExprUnit<T>` | `LOWER(source)` | Lowercase |
120
- | `length` | `(source) => ExprUnit<number>` | `CHAR_LENGTH(source)` | Character count |
121
- | `byteLength` | `(source) => ExprUnit<number>` | `OCTET_LENGTH(source)` | Byte count |
122
- | `substring` | `(source, start, length?) => ExprUnit<T>` | `SUBSTRING(source, start, length)` | Extract substring (1-based index) |
123
- | `indexOf` | `(source, search) => ExprUnit<number>` | `LOCATE(search, source)` | Find position (1-based, 0 if not found) |
124
-
125
- ### Math Functions (SELECT)
126
-
127
- | Method | Signature | SQL | Description |
128
- |--------|-----------|-----|-------------|
129
- | `abs` | `(source) => ExprUnit<T>` | `ABS(source)` | Absolute value |
130
- | `round` | `(source, digits) => ExprUnit<T>` | `ROUND(source, digits)` | Round to N decimal places |
131
- | `ceil` | `(source) => ExprUnit<T>` | `CEILING(source)` | Round up |
132
- | `floor` | `(source) => ExprUnit<T>` | `FLOOR(source)` | Round down |
133
-
134
- ### Date Functions (SELECT)
135
-
136
- | Method | Signature | SQL | Description |
137
- |--------|-----------|-----|-------------|
138
- | `year` | `(source) => ExprUnit<number>` | `YEAR(source)` | Extract year (4-digit) |
139
- | `month` | `(source) => ExprUnit<number>` | `MONTH(source)` | Extract month (1-12) |
140
- | `day` | `(source) => ExprUnit<number>` | `DAY(source)` | Extract day (1-31) |
141
- | `hour` | `(source) => ExprUnit<number>` | `HOUR(source)` | Extract hour (0-23) |
142
- | `minute` | `(source) => ExprUnit<number>` | `MINUTE(source)` | Extract minute (0-59) |
143
- | `second` | `(source) => ExprUnit<number>` | `SECOND(source)` | Extract second (0-59) |
144
- | `isoWeek` | `(source) => ExprUnit<number>` | `WEEK(source, 3)` | ISO week number (1-53) |
145
- | `isoWeekStartDate` | `(source) => ExprUnit<T>` | Computed | Monday of the source date's week |
146
- | `isoYearMonth` | `(source) => ExprUnit<T>` | Computed | First day of the source date's month |
147
- | `dateDiff` | `(unit: DateUnit, from, to) => ExprUnit<number>` | `DATEDIFF(unit, from, to)` | Date difference (to - from) |
148
- | `dateAdd` | `(unit: DateUnit, source, value) => ExprUnit<T>` | `DATEADD(unit, value, source)` | Add time to date |
149
- | `formatDate` | `(source, format: string) => ExprUnit<string>` | `DATE_FORMAT(...)` | Format date as string |
150
-
151
- ### Conditional (SELECT)
152
-
153
- | Method | Signature | SQL | Description |
154
- |--------|-----------|-----|-------------|
155
- | `coalesce` | `(...args) => ExprUnit<T>` | `COALESCE(...)` | First non-null value |
156
- | `nullIf` | `(source, value) => ExprUnit<T\|undefined>` | `NULLIF(source, value)` | Return NULL if source equals value |
157
- | `is` | `(condition: WhereExprUnit) => ExprUnit<boolean>` | Condition as boolean | Convert WHERE expression to boolean column |
158
- | `switch` | `<T>() => SwitchExprBuilder<T>` | `CASE WHEN ... END` | Fluent CASE WHEN builder |
159
- | `if` | `(condition, then, else_) => ExprUnit<T>` | `IF(...)` / `IIF(...)` | Ternary conditional |
160
-
161
- ### Aggregate (SELECT)
162
-
163
- | Method | Signature | SQL | Description |
164
- |--------|-----------|-----|-------------|
165
- | `count` | `(arg?, distinct?) => ExprUnit<number>` | `COUNT(...)` | Row count (all rows if arg omitted) |
166
- | `sum` | `(arg) => ExprUnit<number\|undefined>` | `SUM(arg)` | Sum (NULL if all values NULL) |
167
- | `avg` | `(arg) => ExprUnit<number\|undefined>` | `AVG(arg)` | Average (NULL if all values NULL) |
168
- | `max` | `(arg) => ExprUnit<T\|undefined>` | `MAX(arg)` | Maximum value |
169
- | `min` | `(arg) => ExprUnit<T\|undefined>` | `MIN(arg)` | Minimum value |
170
-
171
- ### Other (SELECT)
172
-
173
- | Method | Signature | SQL | Description |
174
- |--------|-----------|-----|-------------|
175
- | `greatest` | `(...args) => ExprUnit<T>` | `GREATEST(...)` | Greatest of multiple values |
176
- | `least` | `(...args) => ExprUnit<T>` | `LEAST(...)` | Least of multiple values |
177
- | `rowNum` | `() => ExprUnit<number>` | `ROW_NUMBER` variant | Simple row numbering |
178
- | `random` | `() => ExprUnit<number>` | `RAND()` / `RANDOM()` | Random number (0 to 1) |
179
- | `cast` | `(source, targetType: DataType) => ExprUnit` | `CAST(source AS type)` | Type conversion |
180
- | `subquery` | `(dataType, queryable) => ExprUnit` | `(SELECT ...)` | Scalar subquery in SELECT |
181
-
182
- ### Window Functions (SELECT)
183
-
184
- | Method | Signature | SQL | Description |
185
- |--------|-----------|-----|-------------|
186
- | `rowNumber` | `(spec: WinSpecInput) => ExprUnit<number>` | `ROW_NUMBER() OVER (...)` | Row number within partition |
187
- | `rank` | `(spec: WinSpecInput) => ExprUnit<number>` | `RANK() OVER (...)` | Rank (gaps after ties: 1,1,3) |
188
- | `denseRank` | `(spec: WinSpecInput) => ExprUnit<number>` | `DENSE_RANK() OVER (...)` | Dense rank (no gaps: 1,1,2) |
189
- | `ntile` | `(n: number, spec: WinSpecInput) => ExprUnit<number>` | `NTILE(n) OVER (...)` | Split into n groups |
190
- | `lag` | `(column, spec, options?) => ExprUnit<T\|undefined>` | `LAG(...) OVER (...)` | Previous row value |
191
- | `lead` | `(column, spec, options?) => ExprUnit<T\|undefined>` | `LEAD(...) OVER (...)` | Next row value |
192
- | `firstValue` | `(column, spec) => ExprUnit<T\|undefined>` | `FIRST_VALUE(...) OVER (...)` | First value in partition |
193
- | `lastValue` | `(column, spec) => ExprUnit<T\|undefined>` | `LAST_VALUE(...) OVER (...)` | Last value in partition |
194
- | `sumOver` | `(column, spec) => ExprUnit<number\|undefined>` | `SUM(...) OVER (...)` | Window sum |
195
- | `avgOver` | `(column, spec) => ExprUnit<number\|undefined>` | `AVG(...) OVER (...)` | Window average |
196
- | `countOver` | `(spec, column?) => ExprUnit<number>` | `COUNT(...) OVER (...)` | Window count |
197
- | `minOver` | `(column, spec) => ExprUnit<T\|undefined>` | `MIN(...) OVER (...)` | Window minimum |
198
- | `maxOver` | `(column, spec) => ExprUnit<T\|undefined>` | `MAX(...) OVER (...)` | Window maximum |
199
-
200
- **WinSpecInput** (window specification input):
201
-
202
- ```typescript
203
- interface WinSpecInput {
204
- partitionBy?: ExprInput<ColumnPrimitive>[];
205
- orderBy?: [ExprInput<ColumnPrimitive>, ("ASC" | "DESC")?][];
206
- }
207
- ```
208
-
209
- **lag/lead options**:
210
-
211
- | Option | Type | Default | Description |
212
- |--------|------|---------|-------------|
213
- | `offset` | `number` | `1` | Number of rows to look back/forward |
214
- | `default` | `ExprInput<T>` | `undefined` (NULL) | Default value when no row exists |
215
-
216
- ### Helper
217
-
218
- | Method | Signature | Description |
219
- |--------|-----------|-------------|
220
- | `toExpr` | `(value: ExprInput<ColumnPrimitive>) => Expr` | Convert ExprInput to Expr JSON AST (internal use) |