@pdg/drizzle-mysql 0.0.0-stage → 1.0.0
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 +371 -2
- package/dist/@types/MySqlConditions.d.cts +20 -0
- package/dist/@types/MySqlConditions.d.ts +20 -0
- package/dist/@types/MySqlInsertValues.d.cts +7 -0
- package/dist/@types/MySqlInsertValues.d.ts +7 -0
- package/dist/@types/MySqlUpdateValues.d.cts +7 -0
- package/dist/@types/MySqlUpdateValues.d.ts +7 -0
- package/dist/@types/common.d.cts +16 -0
- package/dist/@types/common.d.ts +16 -0
- package/dist/@types/index.d.cts +4 -0
- package/dist/@types/index.d.ts +4 -0
- package/dist/MySqlQuery.d.cts +264 -0
- package/dist/MySqlQuery.d.ts +264 -0
- package/dist/alias.d.cts +6 -0
- package/dist/alias.d.ts +6 -0
- package/dist/columns.d.cts +89 -0
- package/dist/columns.d.ts +89 -0
- package/dist/conditions.d.cts +106 -0
- package/dist/conditions.d.ts +106 -0
- package/dist/drizzleMySql.d.cts +166 -0
- package/dist/drizzleMySql.d.ts +166 -0
- package/dist/index.cjs +666 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.esm.js +666 -0
- package/package.json +88 -4
package/README.md
CHANGED
|
@@ -1,3 +1,372 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pdg/drizzle-mysql
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Drizzle ORM과 mysql2를 사용하는 Node.js용 MySQL 보조 라이브러리입니다. `drizzle-orm@1.0.0-rc.5`를 기준으로 합니다.
|
|
4
|
+
|
|
5
|
+
## 설치
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @pdg/drizzle-mysql drizzle-orm@1.0.0-rc.5 mysql2
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 사용
|
|
12
|
+
|
|
13
|
+
### 연결과 스키마
|
|
14
|
+
|
|
15
|
+
테이블 정의에는 Drizzle의 MySQL 스키마 API를 패키지 루트에서 가져올 수 있습니다. 연결은 `drizzleMySql`에 MySQL 연결 URL과 스키마를 전달해 만듭니다.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import {
|
|
19
|
+
drizzleMySql,
|
|
20
|
+
int,
|
|
21
|
+
mysqlTable,
|
|
22
|
+
varchar,
|
|
23
|
+
} from '@pdg/drizzle-mysql';
|
|
24
|
+
|
|
25
|
+
const users = mysqlTable('users', {
|
|
26
|
+
id: int('id').autoincrement().primaryKey(),
|
|
27
|
+
name: varchar('name', { length: 100 }).notNull(),
|
|
28
|
+
email: varchar('email', { length: 255 }),
|
|
29
|
+
created_at: varchar('created_at', { length: 30 }),
|
|
30
|
+
updated_at: varchar('updated_at', { length: 30 }),
|
|
31
|
+
});
|
|
32
|
+
const posts = mysqlTable('posts', {
|
|
33
|
+
id: int('id').autoincrement().primaryKey(),
|
|
34
|
+
user_id: int('user_id').notNull(),
|
|
35
|
+
title: varchar('title', { length: 200 }).notNull(),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const db = drizzleMySql({
|
|
39
|
+
url: process.env.DATABASE_URL!,
|
|
40
|
+
schema: { users, posts },
|
|
41
|
+
});
|
|
42
|
+
const user = db.query(users);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
`drizzleMySql` 옵션은 `url`, `schema`, 선택 사항인 `timestamp`, `timestampColumns`입니다. `db.query(table)`은 해당 테이블에 맞춰 타입이 지정된 쿼리 객체를 반환합니다. 연결을 다 사용한 뒤 `await db.close()`로 커넥션 풀을 닫습니다.
|
|
46
|
+
|
|
47
|
+
### 데이터 추가·수정·삭제
|
|
48
|
+
|
|
49
|
+
자동 증가 기본 키가 있는 테이블에서 `add`는 생성된 키를 반환합니다. 여러 행을 넣으면 키 배열을 반환합니다.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
const id = await user.add({ name: '홍길동', email: 'hong@example.com' });
|
|
53
|
+
const ids = await user.add([
|
|
54
|
+
{ name: '김민수', email: 'minsu@example.com' },
|
|
55
|
+
{ name: '이서연', email: 'seoyeon@example.com' },
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
await user.editByPrimaryKey({ name: '김민수' }, id);
|
|
59
|
+
await user.removeByPrimaryKey(id);
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
조건으로 수정·삭제할 때는 반드시 SQL 조건을 전달해야 합니다. 실수로 테이블 전체를 갱신하거나 삭제하지 않도록 조건이 없으면 오류가 발생합니다.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
await user.edit({ name: '수정된 이름' }, user.eq({ id }));
|
|
66
|
+
await user.remove(user.eq({ id }));
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
복합 기본 키 테이블은 기본 키 컬럼명을 모두 포함한 객체를 사용합니다. 단일 기본 키는 값 하나 또는 기본 키 객체를 전달할 수 있습니다.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const found = await user.findByPrimaryKey(id);
|
|
73
|
+
const exists = await user.existsByPrimaryKey(id);
|
|
74
|
+
const missing = await user.notExistsByPrimaryKey(id);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 조회와 컬럼 선택
|
|
78
|
+
|
|
79
|
+
`select`는 Drizzle 조회 빌더를 반환하므로 `where`, `orderBy`, `limit` 등 Drizzle의 빌더 메서드를 이어서 사용할 수 있습니다. `find`는 한 행을 조회하며, 결과가 없으면 `undefined`를 반환합니다.
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const rows = await user
|
|
83
|
+
.select(['id', 'name'])
|
|
84
|
+
.where(user.gt({ id: 0 }))
|
|
85
|
+
.orderBy(user.t.id)
|
|
86
|
+
.limit(20);
|
|
87
|
+
|
|
88
|
+
const found = await user.find(['id', 'name'], user.eq({ id }));
|
|
89
|
+
const count = await user.count(user.isNotNull('email'));
|
|
90
|
+
const exists = await user.exists(user.eq({ email: 'hong@example.com' }));
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
컬럼 선택에는 컬럼명 배열, Drizzle 선택 객체, 또는 `columns()`를 사용하는 콜백을 사용할 수 있습니다. `columns()`는 전체 컬럼 또는 지정한 컬럼만 가져오며, `as`로 결과 키를 지정할 수 있습니다.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const allColumns = user.columns();
|
|
97
|
+
const selectedColumns = user.columns('id', 'name as displayName');
|
|
98
|
+
|
|
99
|
+
const projected = await user.find(
|
|
100
|
+
(query) => [query.columns('id', 'name as displayName')],
|
|
101
|
+
user.eq({ id })
|
|
102
|
+
);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
테이블의 TypeScript 속성명과 SQL 컬럼명을 다르게 지정하면 기본 전체 조회 결과 키와 추론된 타입이 달라질 수 있습니다. 기본 컬럼 선택을 사용할 경우 스키마 속성명과 SQL 컬럼명을 같게 작성하는 것을 권장합니다. 이름이 다르면 필요한 컬럼을 명시적으로 선택하고 별칭을 지정하세요.
|
|
106
|
+
|
|
107
|
+
### 조건식
|
|
108
|
+
|
|
109
|
+
조건 함수는 `db` 연결 객체나 `db.query(table)`이 반환한 쿼리 객체에서 사용할 수 있습니다. 쿼리 객체 메서드는 해당 테이블의 컬럼을 기준으로 타입을 검사하고, `db` 메서드는 테이블 객체 또는 연결 스키마에 등록된 스키마 키를 함께 받습니다.
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
const byName = user.eq({ name: '홍길동' });
|
|
113
|
+
const bySchemaKey = db.eq('users', { name: '홍길동' });
|
|
114
|
+
const byTable = db.eq(users, { name: '홍길동' });
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`createConditions(schema)`를 직접 호출해도 같은 조건 함수를 만들 수 있습니다. 독립된 조건 빌더가 필요할 때 사용하며, 반환된 함수는 생성할 때 전달한 스키마의 키와 테이블을 기준으로 동작합니다.
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { createConditions } from '@pdg/drizzle-mysql';
|
|
121
|
+
|
|
122
|
+
const condition = createConditions({ users });
|
|
123
|
+
const where = condition.and('users', {
|
|
124
|
+
gte: { id: 1 },
|
|
125
|
+
isNotNull: 'email',
|
|
126
|
+
});
|
|
127
|
+
const rows = await user.select().where(where);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
#### 비교 연산자
|
|
131
|
+
|
|
132
|
+
`eq`, `ne`, `gt`, `gte`, `lt`, `lte`는 컬럼과 값을 비교합니다. 하나의 값 객체에 여러 컬럼을 넣으면 각 비교가 `AND`로 묶입니다. `undefined` 값은 생략되므로 선택적 검색 조건을 만들 때 유용합니다.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const filters = {
|
|
136
|
+
name: searchName,
|
|
137
|
+
email: searchEmail,
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const rows = await user.find((query) =>
|
|
141
|
+
query.eq({
|
|
142
|
+
name: filters.name,
|
|
143
|
+
email: filters.email,
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const changedIds = await user
|
|
148
|
+
.select(['id'])
|
|
149
|
+
.where(user.and({
|
|
150
|
+
gte: { id: 10 },
|
|
151
|
+
lte: { id: 50 },
|
|
152
|
+
}));
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`eq({ email: null })`은 `IS NULL`, `ne({ email: null })`은 `IS NOT NULL`로 변환됩니다. `gt` 등의 비교 연산자에는 `null`을 전달할 수 없습니다.
|
|
156
|
+
|
|
157
|
+
#### 배열과 범위
|
|
158
|
+
|
|
159
|
+
`inArray`와 `notInArray`는 컬럼별 허용·제외 값 배열을 받고, `between`과 `notBetween`은 `[시작, 끝]` 튜플을 받습니다. 한 객체에 여러 컬럼을 지정하면 각각의 조건은 `AND`로 결합됩니다.
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
const selected = await user.find((query) =>
|
|
163
|
+
query.and({
|
|
164
|
+
inArray: { id: [1, 3, 5, 7] },
|
|
165
|
+
notInArray: { name: ['차단 사용자', '삭제 사용자'] },
|
|
166
|
+
between: { id: [1, 100] },
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const recentIds = await user
|
|
171
|
+
.select(['id'])
|
|
172
|
+
.where(user.notBetween({ id: [1, 10] }));
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
범위 양 끝은 `null`이나 `undefined`가 아닌 값이어야 합니다. `inArray`와 `notInArray`의 값은 배열이어야 합니다.
|
|
176
|
+
|
|
177
|
+
#### 문자열 패턴
|
|
178
|
+
|
|
179
|
+
`like`, `notLike`, `ilike`, `notIlike`는 문자열 컬럼에 SQL 패턴을 적용합니다. `%`는 임의 길이 문자열, `_`는 한 문자에 대응합니다. `ilike` 계열은 대소문자를 구분하지 않는 `ILIKE` 연산자를 생성하지만, MySQL은 `ILIKE` 문법을 지원하지 않으므로 MySQL 쿼리에서는 사용하지 마세요. MySQL의 `LIKE` 대소문자 구분 여부는 컬럼 collation 설정에 따릅니다.
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
const matchingUsers = await user.find((query) =>
|
|
183
|
+
query.or({
|
|
184
|
+
like: { email: '%@example.com' },
|
|
185
|
+
eq: { name: 'Kim' },
|
|
186
|
+
})
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const excludedNames = await user
|
|
190
|
+
.select()
|
|
191
|
+
.where(user.notLike({ name: '테스트_%' }));
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
패턴 연산은 문자열 컬럼에만 사용할 수 있으며, 값은 `%홍길동%`처럼 SQL 패턴 문자열로 전달합니다. `ilike` / `notIlike`는 패키지의 조건 함수 목록에는 있지만 MySQL에서는 실행할 수 없습니다.
|
|
195
|
+
|
|
196
|
+
#### NULL 검사
|
|
197
|
+
|
|
198
|
+
`isNull`과 `isNotNull`은 컬럼명 하나 또는 컬럼명 배열을 받습니다. 배열 안의 컬럼 검사는 `AND`로 결합됩니다. 검색 조건에 따라 컬럼 검사를 생략하려면 `undefined`를 전달할 수 있습니다.
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
const noEmail = await user.find((query) => query.isNull('email'));
|
|
202
|
+
const hasNameAndEmail = await user.find((query) =>
|
|
203
|
+
query.isNotNull(['name', 'email'])
|
|
204
|
+
);
|
|
205
|
+
const optionalNullCheck = user.isNull(shouldCheckEmail ? 'email' : undefined);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
#### AND·OR 조합
|
|
209
|
+
|
|
210
|
+
`query.and({ ... })`와 `query.or({ ... })`는 여러 연산자 그룹을 객체로 구성합니다. 한 연산자 아래의 컬럼 비교는 먼저 `AND`로 묶이고, 바깥 함수가 각 연산자 그룹을 `AND` 또는 `OR`로 결합합니다. `and` / `or` 객체는 조건 그룹이며, 그 안에 다시 `and` / `or`를 중첩하는 형식은 지원하지 않습니다.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
const usersMatchingEither = await user.find((query) =>
|
|
214
|
+
query.or({
|
|
215
|
+
eq: { name: '홍길동' },
|
|
216
|
+
like: { email: '%@example.com' },
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
const activeCandidates = await user.find((query) =>
|
|
221
|
+
query.and({
|
|
222
|
+
isNotNull: 'email',
|
|
223
|
+
ne: { name: '탈퇴 사용자' },
|
|
224
|
+
})
|
|
225
|
+
);
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
여러 조건을 임의로 중첩하거나 이미 만든 SQL 조건을 결합할 때는 `db.and(...)` / `db.or(...)`의 Drizzle 호환 오버로드를 사용합니다. 이 형식에서는 함수 호출 인자로 SQL 조건을 직접 조합할 수 있습니다.
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const nameOrEmail = db.or(
|
|
232
|
+
user.eq({ name: '홍길동' }),
|
|
233
|
+
user.like({ email: '%@example.com' }),
|
|
234
|
+
);
|
|
235
|
+
const condition = db.and(
|
|
236
|
+
nameOrEmail,
|
|
237
|
+
db.isNotNull(users.email),
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
const matchingUsers = await user.select().where(condition);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
같은 함수는 테이블 객체와 조건 객체를 받아 그룹 조건을 만들 수도 있습니다.
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
const groupedCondition = db.and(users, {
|
|
247
|
+
gte: { id: 1 },
|
|
248
|
+
isNotNull: ['name', 'email'],
|
|
249
|
+
});
|
|
250
|
+
const groupedUsers = await user.select().where(groupedCondition);
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### Drizzle 컬럼 연산자와 함께 사용
|
|
254
|
+
|
|
255
|
+
`db`의 조건 함수는 테이블/객체 형식 외에도 Drizzle의 컬럼 기반 연산자 오버로드를 그대로 사용할 수 있습니다. `SQL` 조건은 래퍼 조회 메서드에 전달하거나 Drizzle 조회 빌더에서 조합할 수 있습니다.
|
|
256
|
+
|
|
257
|
+
```ts
|
|
258
|
+
const columnCondition = db.and(
|
|
259
|
+
db.eq(users.name, '홍길동'),
|
|
260
|
+
db.isNotNull(users.email),
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
const rows = await user.select().where(columnCondition);
|
|
264
|
+
const count = await user.count(columnCondition);
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
지원하는 객체 조건 함수는 `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `inArray`, `notInArray`, `between`, `notBetween`, `like`, `notLike`, `ilike`, `notIlike`, `isNull`, `isNotNull`, `and`, `or`입니다. 존재하지 않는 스키마 키나 컬럼, 잘못된 값 형식은 조건을 조용히 생략하지 않고 오류로 처리합니다.
|
|
268
|
+
|
|
269
|
+
### 별칭과 조인
|
|
270
|
+
|
|
271
|
+
`db.a`는 연결에 전달한 스키마의 테이블별 별칭 생성 함수입니다. 별칭 테이블은 선택 및 조건식에 사용할 수 있습니다. `select`가 반환하는 Drizzle 빌더에서 조인을 이어서 작성할 수 있습니다.
|
|
272
|
+
|
|
273
|
+
```ts
|
|
274
|
+
const u = db.a.users('u');
|
|
275
|
+
const rows = await user
|
|
276
|
+
.select(u, ['id', 'name'])
|
|
277
|
+
.where(db.eq(u, { name: '홍길동' }));
|
|
278
|
+
|
|
279
|
+
const userPosts = await user
|
|
280
|
+
.select()
|
|
281
|
+
.leftJoin(posts, db.eq(users.id, posts.user_id));
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
기본 별칭은 스키마 키의 첫 글자와 대문자 위치를 기준으로 만듭니다. 예를 들어 `userProfile`의 기본 별칭은 `up`이며, `db.a.userProfile('profile')`처럼 직접 지정할 수도 있습니다.
|
|
285
|
+
|
|
286
|
+
### 페이지네이션
|
|
287
|
+
|
|
288
|
+
`db.paginate(builder, page, limit)`은 조회 데이터와 페이지 정보를 함께 반환합니다. 페이지와 페이지 크기는 양의 정수여야 합니다. 페이지네이션에 전달하는 빌더는 사용할 트랜잭션 안에서 생성해야 합니다.
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
const page = await db.paginate(
|
|
292
|
+
user.select().where(user.isNotNull('email')).orderBy(user.t.id),
|
|
293
|
+
1,
|
|
294
|
+
20,
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
console.log(page.data);
|
|
298
|
+
console.log(page.paging); // current_page, per_page, last_page, total, from, to
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 트랜잭션과 원본 Drizzle API
|
|
302
|
+
|
|
303
|
+
`db.trans` 콜백 안의 쿼리 객체는 현재 트랜잭션을 자동으로 사용합니다. 중첩된 `db.trans`는 savepoint로 동작합니다. 트랜잭션 안에서 시작한 비동기 작업은 트랜잭션이 끝나기 전에 모두 `await`해야 합니다.
|
|
304
|
+
|
|
305
|
+
```ts
|
|
306
|
+
await db.trans(async () => {
|
|
307
|
+
const id = await user.add({ name: '트랜잭션 사용자' });
|
|
308
|
+
await user.editByPrimaryKey({ name: '이름 변경' }, id);
|
|
309
|
+
|
|
310
|
+
// 같은 트랜잭션을 사용하는 원본 Drizzle API
|
|
311
|
+
await db.current().select().from(users);
|
|
312
|
+
|
|
313
|
+
await db.trans(async () => {
|
|
314
|
+
await user.removeByPrimaryKey(id);
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
`db.current()`는 현재 문맥의 Drizzle 데이터베이스 인스턴스를 반환합니다. 래퍼가 제공하지 않는 Drizzle 기능은 이 API로 직접 사용할 수 있습니다.
|
|
320
|
+
|
|
321
|
+
### 생성·수정 시각
|
|
322
|
+
|
|
323
|
+
시각 자동 입력 메서드를 사용하려면 `timestamp` 생성 함수를 설정합니다. 기본 컬럼 이름은 `created_at`과 `updated_at`이며, `timestampColumns`의 `createdAt`과 `updatedAt`으로 변경할 수 있습니다.
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
const dbWithTimestamp = drizzleMySql({
|
|
327
|
+
url: process.env.DATABASE_URL!,
|
|
328
|
+
schema: { users },
|
|
329
|
+
timestamp: () => new Date(),
|
|
330
|
+
timestampColumns: { createdAt: 'created_at', updatedAt: 'updated_at' },
|
|
331
|
+
});
|
|
332
|
+
const timestampedUser = dbWithTimestamp.query(users);
|
|
333
|
+
|
|
334
|
+
await timestampedUser.addWithCreatedAt({ name: '생성 시각 입력' });
|
|
335
|
+
await timestampedUser.addWithCreatedUpdatedAt({ name: '생성·수정 시각 입력' });
|
|
336
|
+
await timestampedUser.editWithUpdatedAtByPrimaryKey({ name: '수정 시각 갱신' }, id);
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
시각 관련 메서드는 `addWithCreatedAt`, `addWithCreatedUpdatedAt`, `editWithUpdatedAt`, `editWithUpdatedAtByPrimaryKey`입니다. 직접 시각 값을 지정하는 대신 설정한 생성 함수의 값을 사용합니다.
|
|
340
|
+
|
|
341
|
+
### 집계·SQL 표현식
|
|
342
|
+
|
|
343
|
+
`db` 인스턴스는 `asc`, `desc`, `count`, `countDistinct`, `avg`, `avgDistinct`, `sum`, `sumDistinct`, `max`, `min`, `not`, `exists`, `notExists`, `arrayContains`, `arrayContained`, `arrayOverlaps` 등 Drizzle 함수를 제공합니다. `db.sqlNumber`, `db.sqlString`, `db.sqlBoolean`은 SQL 표현식 또는 기본 값을 해당 타입으로 매핑하는 표현식을 만듭니다.
|
|
344
|
+
|
|
345
|
+
```ts
|
|
346
|
+
const [summary] = await db.current()
|
|
347
|
+
.select({ total: db.count() })
|
|
348
|
+
.from(users);
|
|
349
|
+
|
|
350
|
+
const numericExpression = db.sqlNumber(db.sql`1`);
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### 공개 타입과 스키마 API
|
|
354
|
+
|
|
355
|
+
스키마 정의에 필요한 다음 API를 `@pdg/drizzle-mysql`에서 직접 가져올 수 있습니다.
|
|
356
|
+
|
|
357
|
+
| 구분 | 내보내기 |
|
|
358
|
+
| --- | --- |
|
|
359
|
+
| 테이블·스키마·뷰 | `mysqlTable`, `mysqlTableCreator`, `mysqlSchema`, `mysqlDatabase`, `mysqlView` |
|
|
360
|
+
| 정수·실수 | `tinyint`, `smallint`, `mediumint`, `int`, `bigint`, `serial`, `float`, `double`, `real`, `decimal` |
|
|
361
|
+
| 문자열 | `char`, `varchar`, `tinytext`, `text`, `mediumtext`, `longtext`, `mysqlEnum` |
|
|
362
|
+
| 날짜·시간 | `date`, `datetime`, `time`, `timestamp`, `year` |
|
|
363
|
+
| 바이너리 | `binary`, `varbinary`, `tinyblob`, `blob`, `mediumblob`, `longblob` |
|
|
364
|
+
| 기타 컬럼 | `boolean`, `json`, `customType` |
|
|
365
|
+
| 인덱스·제약조건 | `index`, `uniqueIndex`, `primaryKey`, `foreignKey`, `unique`, `check` |
|
|
366
|
+
| 타입 (`import type`) | `InferColumnsDataTypes`, `MySqlConditions`, `MySqlInsertValues`, `MySqlUpdateValues`, `MySqlAliasTable`, `MySqlSelectedColumns`, `MySqlSelectedTableColumns`, `MySqlColumnSelectionName`, `MySqlSelectedNamedColumnUnion`, `MySqlSelectedNamedColumns`, `MySqlCompareValues`, `MySqlColumnName`, `MySqlArrayCompareValues`, `MySqlRangeCompareValues`, `MySqlPatternCompareValues`, `MySqlNullConditionInput` |
|
|
367
|
+
|
|
368
|
+
`check`나 SQL 표현식 기반 기본값에 사용하는 `sql`은 `drizzle-orm`에서 가져옵니다. Drizzle의 `MySqlTable` 등 직접 필요한 타입도 `drizzle-orm/mysql-core`에서 가져올 수 있습니다.
|
|
369
|
+
|
|
370
|
+
## 라이선스
|
|
371
|
+
|
|
372
|
+
이 프로젝트는 [MIT 라이선스](https://opensource.org/licenses/MIT)에 따라 배포됩니다.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core';
|
|
2
|
+
import type { MySqlArrayCompareValues, MySqlCompareValues, MySqlNullConditionInput, MySqlPatternCompareValues, MySqlRangeCompareValues } from './common.cjs';
|
|
3
|
+
export type MySqlConditions<T extends MySqlTable> = {
|
|
4
|
+
eq?: MySqlCompareValues<T>;
|
|
5
|
+
ne?: MySqlCompareValues<T>;
|
|
6
|
+
gt?: MySqlCompareValues<T>;
|
|
7
|
+
gte?: MySqlCompareValues<T>;
|
|
8
|
+
lt?: MySqlCompareValues<T>;
|
|
9
|
+
lte?: MySqlCompareValues<T>;
|
|
10
|
+
inArray?: MySqlArrayCompareValues<T>;
|
|
11
|
+
notInArray?: MySqlArrayCompareValues<T>;
|
|
12
|
+
between?: MySqlRangeCompareValues<T>;
|
|
13
|
+
notBetween?: MySqlRangeCompareValues<T>;
|
|
14
|
+
like?: MySqlPatternCompareValues<T>;
|
|
15
|
+
notLike?: MySqlPatternCompareValues<T>;
|
|
16
|
+
ilike?: MySqlPatternCompareValues<T>;
|
|
17
|
+
notIlike?: MySqlPatternCompareValues<T>;
|
|
18
|
+
isNull?: MySqlNullConditionInput<T>;
|
|
19
|
+
isNotNull?: MySqlNullConditionInput<T>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core';
|
|
2
|
+
import type { MySqlArrayCompareValues, MySqlCompareValues, MySqlNullConditionInput, MySqlPatternCompareValues, MySqlRangeCompareValues } from './common.js';
|
|
3
|
+
export type MySqlConditions<T extends MySqlTable> = {
|
|
4
|
+
eq?: MySqlCompareValues<T>;
|
|
5
|
+
ne?: MySqlCompareValues<T>;
|
|
6
|
+
gt?: MySqlCompareValues<T>;
|
|
7
|
+
gte?: MySqlCompareValues<T>;
|
|
8
|
+
lt?: MySqlCompareValues<T>;
|
|
9
|
+
lte?: MySqlCompareValues<T>;
|
|
10
|
+
inArray?: MySqlArrayCompareValues<T>;
|
|
11
|
+
notInArray?: MySqlArrayCompareValues<T>;
|
|
12
|
+
between?: MySqlRangeCompareValues<T>;
|
|
13
|
+
notBetween?: MySqlRangeCompareValues<T>;
|
|
14
|
+
like?: MySqlPatternCompareValues<T>;
|
|
15
|
+
notLike?: MySqlPatternCompareValues<T>;
|
|
16
|
+
ilike?: MySqlPatternCompareValues<T>;
|
|
17
|
+
notIlike?: MySqlPatternCompareValues<T>;
|
|
18
|
+
isNull?: MySqlNullConditionInput<T>;
|
|
19
|
+
isNotNull?: MySqlNullConditionInput<T>;
|
|
20
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core/table';
|
|
2
|
+
import type { MySqlInsertValue as InsertValue } from 'drizzle-orm/mysql-core/query-builders/insert';
|
|
3
|
+
export type MySqlInsertValues<TTable extends MySqlTable, TBlocked extends keyof InsertValue<TTable> = never> = [
|
|
4
|
+
TBlocked
|
|
5
|
+
] extends [never] ? InsertValue<TTable> : Omit<InsertValue<TTable>, TBlocked> & {
|
|
6
|
+
[P in TBlocked]?: never;
|
|
7
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core/table';
|
|
2
|
+
import type { MySqlInsertValue as InsertValue } from 'drizzle-orm/mysql-core/query-builders/insert';
|
|
3
|
+
export type MySqlInsertValues<TTable extends MySqlTable, TBlocked extends keyof InsertValue<TTable> = never> = [
|
|
4
|
+
TBlocked
|
|
5
|
+
] extends [never] ? InsertValue<TTable> : Omit<InsertValue<TTable>, TBlocked> & {
|
|
6
|
+
[P in TBlocked]?: never;
|
|
7
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core/table';
|
|
2
|
+
import type { MySqlUpdateSetSource } from 'drizzle-orm/mysql-core/query-builders/update';
|
|
3
|
+
export type MySqlUpdateValues<TTable extends MySqlTable, TBlocked extends keyof MySqlUpdateSetSource<TTable> = never, TRequired extends Exclude<keyof MySqlUpdateSetSource<TTable>, TBlocked> = never> = Omit<MySqlUpdateSetSource<TTable>, TBlocked | TRequired> & {
|
|
4
|
+
[P in TBlocked]?: never;
|
|
5
|
+
} & {
|
|
6
|
+
[P in TRequired]-?: Exclude<MySqlUpdateSetSource<TTable>[P], undefined>;
|
|
7
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core/table';
|
|
2
|
+
import type { MySqlUpdateSetSource } from 'drizzle-orm/mysql-core/query-builders/update';
|
|
3
|
+
export type MySqlUpdateValues<TTable extends MySqlTable, TBlocked extends keyof MySqlUpdateSetSource<TTable> = never, TRequired extends Exclude<keyof MySqlUpdateSetSource<TTable>, TBlocked> = never> = Omit<MySqlUpdateSetSource<TTable>, TBlocked | TRequired> & {
|
|
4
|
+
[P in TBlocked]?: never;
|
|
5
|
+
} & {
|
|
6
|
+
[P in TRequired]-?: Exclude<MySqlUpdateSetSource<TTable>[P], undefined>;
|
|
7
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core';
|
|
2
|
+
import type { InferSelectModel, SQLWrapper } from 'drizzle-orm';
|
|
3
|
+
export type MySqlCompareValues<T extends MySqlTable> = {
|
|
4
|
+
[P in keyof InferSelectModel<T>]?: InferSelectModel<T>[P] | SQLWrapper;
|
|
5
|
+
};
|
|
6
|
+
export type MySqlColumnName<T extends MySqlTable> = keyof T['_']['columns'] & string;
|
|
7
|
+
export type MySqlArrayCompareValues<T extends MySqlTable> = {
|
|
8
|
+
[P in keyof InferSelectModel<T>]?: NonNullable<InferSelectModel<T>[P]>[];
|
|
9
|
+
};
|
|
10
|
+
export type MySqlRangeCompareValues<T extends MySqlTable> = {
|
|
11
|
+
[P in keyof InferSelectModel<T>]?: [NonNullable<InferSelectModel<T>[P]>, NonNullable<InferSelectModel<T>[P]>];
|
|
12
|
+
};
|
|
13
|
+
export type MySqlPatternCompareValues<T extends MySqlTable> = {
|
|
14
|
+
[P in keyof InferSelectModel<T> as NonNullable<InferSelectModel<T>[P]> extends string ? P : never]?: string;
|
|
15
|
+
};
|
|
16
|
+
export type MySqlNullConditionInput<T extends MySqlTable> = MySqlColumnName<T> | undefined | readonly (MySqlColumnName<T> | undefined)[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MySqlTable } from 'drizzle-orm/mysql-core';
|
|
2
|
+
import type { InferSelectModel, SQLWrapper } from 'drizzle-orm';
|
|
3
|
+
export type MySqlCompareValues<T extends MySqlTable> = {
|
|
4
|
+
[P in keyof InferSelectModel<T>]?: InferSelectModel<T>[P] | SQLWrapper;
|
|
5
|
+
};
|
|
6
|
+
export type MySqlColumnName<T extends MySqlTable> = keyof T['_']['columns'] & string;
|
|
7
|
+
export type MySqlArrayCompareValues<T extends MySqlTable> = {
|
|
8
|
+
[P in keyof InferSelectModel<T>]?: NonNullable<InferSelectModel<T>[P]>[];
|
|
9
|
+
};
|
|
10
|
+
export type MySqlRangeCompareValues<T extends MySqlTable> = {
|
|
11
|
+
[P in keyof InferSelectModel<T>]?: [NonNullable<InferSelectModel<T>[P]>, NonNullable<InferSelectModel<T>[P]>];
|
|
12
|
+
};
|
|
13
|
+
export type MySqlPatternCompareValues<T extends MySqlTable> = {
|
|
14
|
+
[P in keyof InferSelectModel<T> as NonNullable<InferSelectModel<T>[P]> extends string ? P : never]?: string;
|
|
15
|
+
};
|
|
16
|
+
export type MySqlNullConditionInput<T extends MySqlTable> = MySqlColumnName<T> | undefined | readonly (MySqlColumnName<T> | undefined)[];
|