@simplysm/sd-claude 14.0.98 → 14.0.99
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/claude/references/sd-simplysm14/README.md +16 -16
- package/claude/references/sd-simplysm14/apis/angular/README.md +81 -153
- package/claude/references/sd-simplysm14/apis/angular/controls.md +179 -205
- package/claude/references/sd-simplysm14/apis/angular/crud.md +71 -57
- package/claude/references/sd-simplysm14/apis/angular/directives.md +49 -109
- package/claude/references/sd-simplysm14/apis/angular/features.md +58 -86
- package/claude/references/sd-simplysm14/apis/angular/kanban.md +32 -40
- package/claude/references/sd-simplysm14/apis/angular/layout.md +38 -52
- package/claude/references/sd-simplysm14/apis/angular/overlay.md +86 -110
- package/claude/references/sd-simplysm14/apis/angular/routing-appstructure.md +54 -86
- package/claude/references/sd-simplysm14/apis/angular/shared-data.md +82 -74
- package/claude/references/sd-simplysm14/apis/angular/sheet.md +56 -80
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-auto-update/README.md +15 -15
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-file-system/README.md +21 -21
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-intent/README.md +79 -53
- package/claude/references/sd-simplysm14/apis/capacitor-plugin-usb-storage/README.md +9 -11
- package/claude/references/sd-simplysm14/apis/core-browser/README.md +15 -15
- package/claude/references/sd-simplysm14/apis/core-browser/dom-element.md +20 -20
- package/claude/references/sd-simplysm14/apis/core-browser/indexed-db.md +18 -18
- package/claude/references/sd-simplysm14/apis/core-common/README.md +20 -49
- package/claude/references/sd-simplysm14/apis/core-common/async-runtime.md +66 -55
- package/claude/references/sd-simplysm14/apis/core-common/collection-ext.md +83 -56
- package/claude/references/sd-simplysm14/apis/core-common/errors.md +32 -21
- package/claude/references/sd-simplysm14/apis/core-common/obj.md +57 -39
- package/claude/references/sd-simplysm14/apis/core-common/serialization.md +36 -30
- package/claude/references/sd-simplysm14/apis/core-common/value-types.md +69 -41
- package/claude/references/sd-simplysm14/apis/core-node/README.md +4 -4
- package/claude/references/sd-simplysm14/apis/core-node/consola.md +15 -13
- package/claude/references/sd-simplysm14/apis/core-node/cpx.md +11 -7
- package/claude/references/sd-simplysm14/apis/core-node/fs-watcher.md +8 -8
- package/claude/references/sd-simplysm14/apis/core-node/fsx.md +29 -20
- package/claude/references/sd-simplysm14/apis/core-node/pathx.md +14 -6
- package/claude/references/sd-simplysm14/apis/core-node/worker.md +3 -3
- package/claude/references/sd-simplysm14/apis/excel/README.md +3 -3
- package/claude/references/sd-simplysm14/apis/excel/cell.md +32 -32
- package/claude/references/sd-simplysm14/apis/excel/conditional-format.md +23 -24
- package/claude/references/sd-simplysm14/apis/excel/style.md +24 -30
- package/claude/references/sd-simplysm14/apis/excel/utils.md +20 -23
- package/claude/references/sd-simplysm14/apis/excel/workbook-worksheet.md +60 -71
- package/claude/references/sd-simplysm14/apis/excel/wrapper.md +36 -36
- package/claude/references/sd-simplysm14/apis/lint/README.md +7 -9
- package/claude/references/sd-simplysm14/apis/lint/recommended.md +59 -37
- package/claude/references/sd-simplysm14/apis/lint/rules.md +81 -74
- package/claude/references/sd-simplysm14/apis/orm-common/README.md +6 -6
- package/claude/references/sd-simplysm14/apis/orm-common/db-context.md +112 -78
- package/claude/references/sd-simplysm14/apis/orm-common/expr.md +131 -75
- package/claude/references/sd-simplysm14/apis/orm-common/queryable.md +126 -82
- package/claude/references/sd-simplysm14/apis/orm-common/schema.md +170 -113
- package/claude/references/sd-simplysm14/apis/orm-common/types.md +102 -48
- package/claude/references/sd-simplysm14/apis/orm-node/README.md +12 -13
- package/claude/references/sd-simplysm14/apis/orm-node/db-conn.md +3 -3
- package/claude/references/sd-simplysm14/apis/sd-cli/README.md +5 -5
- package/claude/references/sd-simplysm14/apis/sd-cli/SdTsCompiler.md +67 -65
- package/claude/references/sd-simplysm14/apis/sd-cli/sd-config-types.md +130 -123
- package/claude/references/sd-simplysm14/apis/service-client/README.md +63 -63
- package/claude/references/sd-simplysm14/apis/service-client/orm.md +22 -22
- package/claude/references/sd-simplysm14/apis/service-client/transport.md +30 -26
- package/claude/references/sd-simplysm14/apis/service-common/README.md +8 -8
- package/claude/references/sd-simplysm14/apis/service-common/app-structure.md +13 -6
- package/claude/references/sd-simplysm14/apis/service-common/protocol.md +1 -1
- package/claude/references/sd-simplysm14/apis/service-server/README.md +43 -47
- package/claude/references/sd-simplysm14/apis/service-server/built-in-services.md +35 -0
- package/claude/references/sd-simplysm14/apis/service-server/service-authoring.md +20 -19
- package/claude/references/sd-simplysm14/apis/service-server/transport-internals.md +23 -25
- package/claude/references/sd-simplysm14/apis/service-server/v1-legacy.md +9 -9
- package/claude/references/sd-simplysm14/apis/storage/README.md +26 -26
- package/claude/references/sd-simplysm14/manuals/client-component.md +9 -1
- package/claude/references/sd-simplysm14/manuals/client-crud.md +1 -1
- package/claude/references/sd-simplysm14/manuals/client-orm.md +1 -0
- package/claude/references/sd-simplysm14/manuals/client-service.md +1 -0
- package/claude/references/sd-simplysm14/manuals/client-shared-data.md +1 -0
- package/claude/references/sd-simplysm14/manuals/client-ssg.md +1 -0
- package/claude/sd-system-prompt.md +11 -26
- package/claude/skills/sd-docs/references/subagent-prompt.md +4 -3
- package/claude/skills/sd-spec/SKILL.md +87 -18
- package/claude/skills/sd-spec/references/format.md +2 -2
- package/package.json +1 -1
|
@@ -1,142 +1,186 @@
|
|
|
1
|
-
# @simplysm/orm-common —
|
|
1
|
+
# @simplysm/orm-common — queryable
|
|
2
2
|
|
|
3
|
-
`db.
|
|
3
|
+
`db.X()` 가 반환하는 `Queryable` 체이닝으로 SELECT/INSERT/UPDATE/DELETE/UPSERT 쿼리를 구성·실행하는 군. 모든 옵션 메서드는 새 `Queryable` 을 반환하는 불변 체이닝이며, 콜백은 컬럼 프록시(`QueryableRecord`)를 받아 `expr` 표현식을 만든다. 종단 메서드(`execute`/`single`/`count` 등)에서 QueryDef 를 빌드해 `db.executeDefs` 로 실행한다. 프로시저 실행은 `Executable`, 텍스트 검색 파싱은 `parseSearchQuery`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`Queryable<TData, TFrom>` — `TData` 는 결과 행 타입, `TFrom` 은 소스 TableBuilder(CUD 연산에 필요, 커스텀 컬럼/조인 결과는 `never`).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## SELECT 옵션 (체이닝)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
9
|
+
- `select(fn)` — SELECT 컬럼 매핑. `fn` 은 컬럼 프록시를 받아 새 구조(`{ alias: 컬럼/표현식 }`)를 반환. 결과 타입이 매핑 형태로 바뀌고 `TFrom` 은 `never`(이후 CUD 불가). 리터럴 상수도 자동으로 `ExprUnit` 으로 래핑됨.
|
|
10
|
+
- `distinct()` — 중복 행 제거(DISTINCT). 이후 `count()` 는 `wrap()` 필요.
|
|
11
|
+
- `lock()` — 선택 행에 배타적 잠금(FOR UPDATE). 트랜잭션 내에서만 의미.
|
|
12
|
+
- `top(count)` — 상위 N행. ORDER BY 없이도 가능.
|
|
13
|
+
- `limit(skip, take)` — OFFSET/LIMIT 페이지네이션. **먼저 `orderBy()` 가 있어야 함**(없으면 throw).
|
|
14
|
+
- `orderBy(fnOrKey, dir?)` — 정렬 추가(여러 번 누적). `fnOrKey` 는 컬럼 반환 함수 또는 체인 경로 문자열(`"id"`, `"user.name"` — `obj.getChainValue` 로 해석). `dir` 기본 `ASC`.
|
|
14
15
|
|
|
15
16
|
```typescript
|
|
16
|
-
|
|
17
|
+
const users = await db.user()
|
|
18
|
+
.select((u) => ({ userName: u.name, userEmail: u.email }))
|
|
19
|
+
.orderBy((u) => u.createdAt, "DESC")
|
|
20
|
+
.limit(0, 20)
|
|
21
|
+
.execute();
|
|
17
22
|
```
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
## WHERE / 검색
|
|
20
25
|
|
|
21
|
-
- `
|
|
22
|
-
- `
|
|
26
|
+
- `where(predicate)` — 조건 배열을 반환하는 콜백. 여러 번 호출 시 AND 누적. 배열 안 여러 조건도 AND.
|
|
27
|
+
- `search(fn, searchText)` — `fn` 이 반환한 문자열 컬럼들에 텍스트 검색을 적용. 구문은 `parseSearchQuery` 규칙(공백=OR, `+`=필수, `-`=제외, `"..."`=구문, `*`=와일드카드). 빈 검색어면 그대로 반환. 내부적으로 `LOWER(col) LIKE pattern` 조합.
|
|
23
28
|
|
|
24
29
|
```typescript
|
|
25
|
-
db.user()
|
|
30
|
+
db.user()
|
|
31
|
+
.where((u) => [expr.eq(u.isActive, true)])
|
|
32
|
+
.search((u) => [u.name, u.email], "John Doe -withdrawn");
|
|
26
33
|
```
|
|
27
34
|
|
|
28
|
-
|
|
35
|
+
## GROUP BY / HAVING
|
|
29
36
|
|
|
30
|
-
- `
|
|
31
|
-
|
|
32
|
-
### 필터 — where / search
|
|
33
|
-
|
|
34
|
-
- `where(predicate)` — WHERE 조건 추가(여러 번 호출 시 AND 결합). `predicate` 는 컬럼 프록시를 받아 `WhereExprUnit[]` 반환. select 로 만든 파생 컬럼 이름도 직접 참조 가능(framework 가 AST inline).
|
|
35
|
-
- `search(fn, searchText)` — 텍스트 검색. `fn`=검색 대상 문자열 컬럼 배열 반환, `searchText`=검색 구문(`parseSearchQuery` 규칙: 공백=OR, `+`=필수, `-`=제외, `"..."`=구문, `*`=와일드카드). 빈 문자열이면 조건 미추가. 내부적으로 `LOWER(col) LIKE pattern` 조합으로 변환.
|
|
37
|
+
- `groupBy(fn)` — 그룹화 컬럼 배열 반환. 반환 `TFrom` 은 `never`.
|
|
38
|
+
- `having(predicate)` — GROUP BY 이후 필터(여러 번 누적, AND). 반환 `TFrom` 은 `never`.
|
|
36
39
|
|
|
37
40
|
```typescript
|
|
38
|
-
db.
|
|
39
|
-
.
|
|
40
|
-
.
|
|
41
|
+
db.order()
|
|
42
|
+
.select((o) => ({ userId: o.userId, total: expr.sum(o.amount) }))
|
|
43
|
+
.groupBy((o) => [o.userId])
|
|
44
|
+
.having((o) => [expr.gte(o.total, 10000)]);
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- `groupBy(fn)` — GROUP BY. `fn` 은 그룹 컬럼 배열 반환. 이후 `count()` 하려면 `wrap()` 먼저(아니면 throw).
|
|
46
|
-
- `having(predicate)` — 그룹 필터(여러 번 호출 시 AND). 집계 컬럼 기준 필터링.
|
|
47
|
+
## JOIN
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
- `join(as, fn)` — 1:N LEFT JOIN. 결과에 `as` 프로퍼티가 **배열**로 추가됨. `fn(qr, cols)` 의 `qr.from(Table)` 로 조인 대상을 잡고 `where` 로 조건을 건다.
|
|
50
|
+
- `joinSingle(as, fn)` — N:1/1:1 LEFT JOIN. 결과에 `as` 가 **단일 객체(optional)** 로 추가됨. 집계·도출 컬럼을 outer 행에 부착하는 표준 수단(orm.md: SELECT 절 subquery/exists 금지).
|
|
51
|
+
- `include(fn)` — TableBuilder 의 FK/FKT 관계를 자동 JOIN. `fn` 은 타입 안전 path proxy 를 받아 관계 경로를 지정(`(p) => p.user.company` → 다단계). 비-컬럼(관계) 필드만 접근 가능. 관계 미정의 시 throw, TableBuilder 기반이 아니면 throw. 같은 경로 중복 호출은 무시.
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
- `joinSingle(as, fn)` — N:1/1:1 LEFT JOIN. 결과에 `as` 키로 단일 객체(또는 undefined) 추가. 도메인 boolean·집계는 SELECT subquery 대신 `joinSingle` 안 `from+where+select(aggregate)` 로 부착(orm.md).
|
|
52
|
-
- `include(fn)` — `TableBuilder` 의 FK/FKT 관계를 자동 조인. `fn(item)` 은 PathProxy 로 관계 경로만 접근(컬럼은 컴파일 에러). 다단계(`p.user.company`)·다중 호출 지원. 관계 미정의면 throw.
|
|
53
|
+
`join`/`joinSingle` 의 `fn` 첫 인자 `qr`(`JoinQueryable`)는 `from(Table)` / `select(columns)` / `union(...queries)` 를 제공한다.
|
|
53
54
|
|
|
54
55
|
```typescript
|
|
55
|
-
db.post()
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
db.post().include((p) => p.user.company);
|
|
57
|
+
|
|
58
|
+
db.product()
|
|
59
|
+
.joinSingle("state", (q, p) =>
|
|
60
|
+
q.from(StockLine).where((x) => [expr.eq(x.productId, p.id)])
|
|
61
|
+
.select((x) => ({ sumQty: expr.sum(x.qty), cnt: expr.count() })),
|
|
62
|
+
)
|
|
63
|
+
.select((p) => ({ id: p.id, totalQty: expr.coalesce(p.state!.sumQty, 0) }));
|
|
58
64
|
```
|
|
59
65
|
|
|
60
|
-
|
|
66
|
+
## 서브쿼리 / UNION / 재귀 CTE
|
|
61
67
|
|
|
62
|
-
- `wrap()` — 현재 Queryable 을 서브쿼리(
|
|
63
|
-
- `
|
|
64
|
-
- `recursive(fn)` —
|
|
68
|
+
- `wrap()` — 현재 Queryable 을 서브쿼리(파생 테이블)로 감쌈. `distinct()`/`groupBy()` 이후 `count()` 호출 전에 필요.
|
|
69
|
+
- `Queryable.union(...queries)` (static) — 2개 이상 Queryable 을 UNION(중복 제거). **2개 미만이면 `ArgumentError`**. 첫 쿼리의 컬럼 구조를 기준으로 alias 변환. 결과는 파생 테이블이라 이후 fluent 연산은 외부에 적용됨(예시 스타일은 orm-union.md).
|
|
70
|
+
- `recursive(fn)` — WITH RECURSIVE CTE. `fn(cte)` 의 `cte.from(Table)`/`cte.select(...)`/`cte.union(...)` 로 재귀 본문 정의. 재귀 대상에 `self` 프로퍼티(베이스 행 참조)가 추가됨. 계층(조직도·트리) 조회용.
|
|
65
71
|
|
|
66
72
|
```typescript
|
|
67
|
-
const
|
|
73
|
+
const combined = Queryable.union(
|
|
74
|
+
db.user().where((u) => [expr.eq(u.type, "admin")]),
|
|
75
|
+
db.user().where((u) => [expr.eq(u.type, "manager")]),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
db.employee()
|
|
79
|
+
.where((e) => [expr.null(e.managerId)])
|
|
80
|
+
.recursive((cte) => cte.from(Employee).where((e) => [expr.eq(e.managerId, e.self[0].id)]));
|
|
68
81
|
```
|
|
69
82
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
- `execute()` — SELECT 실행, 결과 배열 반환.
|
|
73
|
-
- `single()` — 단일 결과 또는 undefined. 2건 이상이면 `ArgumentError`.
|
|
74
|
-
- `first()` — 첫 결과 또는 undefined(`top(1)`).
|
|
75
|
-
- `exists()` — 조건 일치 행 존재 여부 `boolean`(`top(1)`).
|
|
76
|
-
- `count(fn?)` — 행 수. `fn`=셀 컬럼 지정(생략 시 전체). `distinct()`/`groupBy()` 직후 호출 시 throw(→ `wrap()` 먼저).
|
|
77
|
-
- `getSelectQueryDef()` / `getResultMeta(outputColumns?)` — 실행 없이 `SelectQueryDef` AST / 결과 변환 메타(`ResultMeta`) 산출. 서브쿼리 합성·저수준 실행용.
|
|
83
|
+
## 실행 — SELECT 종단
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- `
|
|
82
|
-
- `
|
|
83
|
-
- `
|
|
85
|
+
- `execute(): Promise<TData[]>` — SELECT 실행, 결과 배열 반환.
|
|
86
|
+
- `single(): Promise<TData | undefined>` — 단일 결과. 2건 이상이면 `ArgumentError`.
|
|
87
|
+
- `first(): Promise<TData | undefined>` — 첫 결과만(`top(1)`).
|
|
88
|
+
- `count(fn?): Promise<number>` — 행 수. `fn` 으로 특정 컬럼 카운트. `distinct()`/`groupBy()` 직후 호출 시 throw(먼저 `wrap()`). 결과 없으면 0.
|
|
89
|
+
- `exists(): Promise<boolean>` — 조건에 맞는 행 존재 여부(`top(1)` 후 길이 검사).
|
|
90
|
+
- `getSelectQueryDef(): SelectQueryDef` — 빌드된 SELECT AST. `getResultMeta(outputColumns?)` — 결과 파싱용 `ResultMeta`.
|
|
84
91
|
|
|
85
92
|
```typescript
|
|
86
|
-
const
|
|
93
|
+
const total = await db.user().where((u) => [expr.eq(u.isActive, true)]).count();
|
|
94
|
+
const user = await db.user().where((u) => [expr.eq(u.id, 1)]).single();
|
|
87
95
|
```
|
|
88
96
|
|
|
89
|
-
|
|
97
|
+
## 실행 — INSERT (TableBuilder 기반만)
|
|
90
98
|
|
|
91
|
-
- `
|
|
92
|
-
- `
|
|
93
|
-
- `
|
|
94
|
-
-
|
|
99
|
+
- `insert(records)` / `insert(records, outputColumns)` — 레코드 배열 삽입. MSSQL 1000행 제한 때문에 1000개 단위 청크로 분할. `outputColumns` 지정 시 삽입된 레코드 배열 반환(`Pick<columns, K>[]`). 빈 배열이면 즉시 반환. AI 컬럼에 명시값이 있으면 자동 `overrideIdentity`.
|
|
100
|
+
- `insertIfNotExists(record)` / `(record, outputColumns)` — WHERE 조건에 맞는 데이터가 없을 때만 단건 삽입. `outputColumns` 지정 시 단건 반환.
|
|
101
|
+
- `insertInto(targetTable)` / `(targetTable, outputColumns)` — 현재 SELECT 결과를 다른 테이블에 INSERT(INSERT INTO ... SELECT). 대상 테이블 컬럼이 현재 데이터와 호환되어야 함(타입 제약).
|
|
102
|
+
- `getInsertQueryDef` / `getInsertIfNotExistsQueryDef` / `getInsertIntoQueryDef` — 각 AST 생성기.
|
|
95
103
|
|
|
96
104
|
```typescript
|
|
97
|
-
await db.user().
|
|
98
|
-
|
|
105
|
+
const [inserted] = await db.user().insert([{ name: "Gildong Hong" }], ["id"]);
|
|
106
|
+
|
|
107
|
+
await db.user()
|
|
108
|
+
.where((u) => [expr.eq(u.email, "t@t.com")])
|
|
109
|
+
.insertIfNotExists({ name: "t", email: "t@t.com" });
|
|
99
110
|
```
|
|
100
111
|
|
|
101
|
-
|
|
112
|
+
## 실행 — UPDATE / DELETE / UPSERT (TableBuilder 기반만)
|
|
102
113
|
|
|
103
|
-
- `
|
|
114
|
+
- `update(recordFwd)` / `(recordFwd, outputColumns)` — `recordFwd(cols)` 가 갱신 컬럼/값을 반환. 값은 `ExprInput`(리터럴 직접 가능). `outputColumns` 지정 시 갱신된 레코드 배열 반환. WHERE/JOIN/limit 가 함께 반영됨.
|
|
115
|
+
- `delete()` / `delete(outputColumns)` — DELETE. `outputColumns` 지정 시 삭제된 레코드 배열 반환.
|
|
116
|
+
- `upsert(updateFn)` / `upsert(updateFn, insertFn?, outputColumns?)` — WHERE 매칭 시 UPDATE, 아니면 INSERT(MERGE). `insertFn(updateRecord)` 미지정 시 update 와 동일 데이터로 삽입. `insertFn` 은 update 레코드를 인자로 받아 변형 가능.
|
|
117
|
+
- `getUpdateQueryDef` / `getDeleteQueryDef` / `getUpsertQueryDef` — AST 생성기.
|
|
118
|
+
- `switchFk(enabled)` — 이 Queryable 소스 테이블의 FK 제약 활성/비활성(트랜잭션 내 가능).
|
|
104
119
|
|
|
105
|
-
|
|
120
|
+
```typescript
|
|
121
|
+
await db.user().where((u) => [expr.eq(u.id, 1)]).update((u) => ({ name: "새이름" }));
|
|
122
|
+
|
|
123
|
+
await db.user().where((u) => [expr.eq(u.isExpired, true)]).delete(["id", "name"]);
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
|
|
125
|
+
await db.user()
|
|
126
|
+
.where((u) => [expr.eq(u.email, "t@t.com")])
|
|
127
|
+
.upsert(() => ({ loginCount: 1 }), (update) => ({ ...update, email: "t@t.com" }));
|
|
128
|
+
```
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
## Executable (프로시저 실행)
|
|
111
131
|
|
|
112
|
-
|
|
132
|
+
`DbContext.executable(Procedure)` 가 반환하는 팩토리(`db.getUserById()`)가 `Executable` 을 만든다.
|
|
113
133
|
|
|
114
|
-
|
|
134
|
+
```typescript
|
|
135
|
+
class Executable<TParams, TReturns> {
|
|
136
|
+
execute(params: InferColumnExprs<TParams>): Promise<InferColumnExprs<TReturns>[][]>;
|
|
137
|
+
getExecProcQueryDef(params?): ExecProcQueryDef;
|
|
138
|
+
}
|
|
139
|
+
function executable(db, builder): () => Executable;
|
|
140
|
+
```
|
|
115
141
|
|
|
116
|
-
- `execute(params)` — 프로시저 실행. `
|
|
117
|
-
- `getExecProcQueryDef(params?)` — 실행 없이 `ExecProcQueryDef` 만 산출.
|
|
118
|
-
- `executable(db, builder)` — `Executable` 팩토리 생성(`DbContext` 멤버 등록용, 보통 `this.executable(...)`).
|
|
142
|
+
- `execute(params)` — 프로시저 실행. 파라미터는 `ExprInput`(리터럴 또는 `ExprUnit`). 결과는 다중 결과셋(`행[][]`). 파라미터 없는 프로시저에 params 를 주면 throw.
|
|
119
143
|
|
|
120
144
|
```typescript
|
|
121
145
|
const [rows] = await db.getUserById().execute({ userId: 1n });
|
|
122
146
|
```
|
|
123
147
|
|
|
124
|
-
##
|
|
125
|
-
|
|
126
|
-
`search()` 가 내부적으로 쓰는 검색 구문 파서. 검색 문자열을 SQL LIKE 패턴으로 변환한다. 커스텀 검색 UI 를 직접 만들 때 외부에서도 호출 가능.
|
|
148
|
+
## 검색 파서 — parseSearchQuery
|
|
127
149
|
|
|
128
150
|
```typescript
|
|
129
151
|
function parseSearchQuery(searchText: string): ParsedSearchQuery;
|
|
130
|
-
interface ParsedSearchQuery { or: string[]; must: string[]; not: string[]; }
|
|
152
|
+
interface ParsedSearchQuery { or: string[]; must: string[]; not: string[]; } // 각각 LIKE 패턴
|
|
131
153
|
```
|
|
132
154
|
|
|
133
|
-
|
|
134
|
-
- `must`: string[] — 필수 포함(AND 조건) LIKE 패턴. `+term` 또는 `"구문"`(따옴표 = 정확 일치 = 필수).
|
|
135
|
-
- `not`: string[] — 제외(NOT 조건) LIKE 패턴. `-term`.
|
|
155
|
+
검색 문자열을 SQL LIKE 패턴으로 파싱. `Queryable.search()` 내부에서 사용하지만 직접도 가능.
|
|
136
156
|
|
|
137
|
-
구문
|
|
157
|
+
| 구문 | 의미 |
|
|
158
|
+
| ---- | ---- |
|
|
159
|
+
| `term1 term2` | OR (하나 이상 일치) → `or` |
|
|
160
|
+
| `+term` | 필수 포함(AND) → `must` |
|
|
161
|
+
| `-term` | 제외(NOT) → `not` |
|
|
162
|
+
| `"exact phrase"` | 정확한 구문(필수) → `must` |
|
|
163
|
+
| `term*` / `*term` / `a*ple` | 와일드카드 `%` 로 변환(접두/접미/중간 일치) |
|
|
164
|
+
| 와일드카드 없는 `term` | `%term%` (부분 문자열) |
|
|
165
|
+
|
|
166
|
+
이스케이프: `\\` `\*` `\%` `\"` `\+` `\-` 는 각 리터럴 문자. 닫히지 않은 따옴표는 따옴표 포함 일반 텍스트로 처리.
|
|
138
167
|
|
|
139
168
|
```typescript
|
|
140
|
-
parseSearchQuery('apple "
|
|
141
|
-
// { or: ["%apple%"], must: ["
|
|
169
|
+
parseSearchQuery('apple "delicious fruit" -banana +strawberry');
|
|
170
|
+
// { or: ["%apple%"], must: ["%delicious fruit%", "%strawberry%"], not: ["%banana%"] }
|
|
142
171
|
```
|
|
172
|
+
|
|
173
|
+
## 관련 타입 / 헬퍼 export
|
|
174
|
+
|
|
175
|
+
- `QueryableRecord<TData>` — 컬럼이 `ExprUnit` 으로 래핑된 프록시 타입(콜백 인자).
|
|
176
|
+
- `QueryableWriteRecord<TData>` — 쓰기(update/upsert) 값 레코드(`ExprInput`).
|
|
177
|
+
- `UnwrapQueryableRecord<R>` — `select` 결과를 다시 데이터 타입으로 역변환.
|
|
178
|
+
- `PathProxy<TObject>` — `include()` 의 타입 안전 경로 프록시(관계 필드만 접근).
|
|
179
|
+
- `queryable(db, tableOrView, as?)` — Table/View 용 Queryable 팩토리 함수(`DbContext.queryable` 의 기반).
|
|
180
|
+
- `getMatchedPrimaryKeys(fkCols, targetTable)` — FK 컬럼 배열과 대상 PK 매칭(개수 불일치 시 throw, include 내부용).
|
|
181
|
+
|
|
182
|
+
## 주의사항
|
|
183
|
+
|
|
184
|
+
- CUD(insert/update/delete/upsert)·`insertInto` 는 `TFrom` 이 살아있는(=`select`/`groupBy`/join 결과가 아닌) TableBuilder 기반 Queryable 에서만. 아니면 throw.
|
|
185
|
+
- 도출 컬럼 위 필터·정렬은 `wrap()` 없이 `.select(...).where(...)` 로 — framework 가 projected AST 를 inline(orm.md). `wrap()` 은 `distinct`/`groupBy` 후 `count` 처럼 명시 요구 시에만.
|
|
186
|
+
- where 비교·CUD 값은 리터럴 그대로 — `expr.val` 로 감싸지 말 것(orm.md). `expr.val` 은 `select` 에서 상수 컬럼 만들 때처럼 `ExprUnit` 이 요구되는 자리에서만.
|