@starbemtech/star-db-query-builder 1.0.38 → 1.2.1
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/.github/workflows/publish.yml +118 -0
- package/ARCHITECTURE.md +313 -0
- package/CHANGELOG.md +65 -0
- package/README.md +1309 -129
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/lcov-report/block-navigation.js +1 -1
- package/coverage/lcov-report/index.html +41 -11
- package/coverage/lcov-report/mysqlClient.ts.html +685 -0
- package/coverage/lcov-report/pgClient.ts.html +823 -0
- package/coverage/lcov-report/sorter.js +21 -7
- package/coverage/lcov.info +533 -0
- package/coverage/mysqlClient.ts.html +685 -0
- package/coverage/pgClient.ts.html +823 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/dist/index.d.ts +5 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/core/repository.d.ts +374 -0
- package/dist/src/core/repository.js +677 -0
- package/dist/src/core/repository.js.map +1 -0
- package/dist/src/{default → core}/types.d.ts +9 -1
- package/dist/src/{default → core}/types.js.map +1 -1
- package/dist/src/core/utils.d.ts +133 -0
- package/dist/src/{default → core}/utils.js +167 -0
- package/dist/src/core/utils.js.map +1 -0
- package/dist/src/db/IDatabaseClient.d.ts +10 -1
- package/dist/src/db/initDb.d.ts +120 -1
- package/dist/src/db/initDb.js +119 -0
- package/dist/src/db/initDb.js.map +1 -1
- package/dist/src/db/mysqlClient.d.ts +23 -1
- package/dist/src/db/mysqlClient.js +115 -0
- package/dist/src/db/mysqlClient.js.map +1 -1
- package/dist/src/db/pgClient.d.ts +22 -1
- package/dist/src/db/pgClient.js +127 -0
- package/dist/src/db/pgClient.js.map +1 -1
- package/dist/src/monitor/monitor.d.ts +6 -1
- package/dist/src/monitor/monitor.js +5 -0
- package/dist/src/monitor/monitor.js.map +1 -1
- package/dist/src/setupTests.d.ts +26 -0
- package/dist/src/setupTests.js +43 -0
- package/dist/src/setupTests.js.map +1 -0
- package/docs/INDEX.md +145 -0
- package/docs/methods/findFirst.md +394 -0
- package/docs/methods/findMany.md +587 -0
- package/docs/methods/insert.md +536 -0
- package/docs/methods/insertMany.md +627 -0
- package/docs/methods/joins.md +781 -0
- package/docs/methods/rawQuery.md +284 -0
- package/docs/methods/transactions.md +737 -0
- package/eslint.config.mjs +77 -0
- package/index.ts +5 -4
- package/jest.config.ts +23 -28
- package/package.json +52 -29
- package/scripts/release.sh +123 -0
- package/src/core/repository.ts +865 -0
- package/src/{default → core}/types.ts +11 -2
- package/src/{default → core}/utils.ts +168 -0
- package/src/db/IDatabaseClient.ts +11 -1
- package/src/db/__tests__/mysqlClient.test.ts +262 -0
- package/src/db/__tests__/pgClient.test.ts +260 -0
- package/src/db/initDb.ts +120 -1
- package/src/db/mysqlClient.ts +119 -3
- package/src/db/pgClient.ts +131 -3
- package/src/monitor/monitor.ts +5 -0
- package/src/setupTests.ts +45 -0
- package/tsconfig.test.json +21 -0
- package/.eslintignore +0 -4
- package/.eslintrc.json +0 -32
- package/coverage/clover.xml +0 -6
- package/coverage/coverage-final.json +0 -1
- package/dist/.eslintrc.json +0 -32
- package/dist/src/default/genericRepository.d.ts +0 -20
- package/dist/src/default/genericRepository.js +0 -192
- package/dist/src/default/genericRepository.js.map +0 -1
- package/dist/src/default/utils.d.ts +0 -9
- package/dist/src/default/utils.js.map +0 -1
- package/index.d.ts +0 -60
- package/src/default/genericRepository.ts +0 -320
- /package/dist/src/{default → core}/types.js +0 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
# insert
|
|
2
|
+
|
|
3
|
+
Inserts a single record into a database table and returns the inserted record.
|
|
4
|
+
|
|
5
|
+
## Signature
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
insert<P, R>({
|
|
9
|
+
tableName: string,
|
|
10
|
+
dbClient: IDatabaseClient,
|
|
11
|
+
data: P,
|
|
12
|
+
returning?: string[]
|
|
13
|
+
}): Promise<R>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Parameters
|
|
17
|
+
|
|
18
|
+
| Parameter | Type | Required | Description |
|
|
19
|
+
| ----------- | ----------------- | -------- | ---------------------------------------------- |
|
|
20
|
+
| `tableName` | `string` | ✅ | Name of the database table |
|
|
21
|
+
| `dbClient` | `IDatabaseClient` | ✅ | Database client instance |
|
|
22
|
+
| `data` | `P` | ✅ | Object containing the data to insert |
|
|
23
|
+
| `returning` | `string[]` | ❌ | Array of field names to return after insertion |
|
|
24
|
+
|
|
25
|
+
## Return Value
|
|
26
|
+
|
|
27
|
+
- **Type**: `Promise<R>`
|
|
28
|
+
- **Description**: Returns the inserted record with all fields (including auto-generated ones like `id`, `created_at`, `updated_at`)
|
|
29
|
+
|
|
30
|
+
## Auto-Generated Fields
|
|
31
|
+
|
|
32
|
+
The `insert` method automatically adds the following fields to every record:
|
|
33
|
+
|
|
34
|
+
- **`id`**: A UUID v4 string
|
|
35
|
+
- **`updated_at`**: Current timestamp
|
|
36
|
+
|
|
37
|
+
## Examples
|
|
38
|
+
|
|
39
|
+
### Basic Usage
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { insert } from '@starbemtech/star-db-query-builder'
|
|
43
|
+
|
|
44
|
+
// Insert a new user
|
|
45
|
+
const user = await insert({
|
|
46
|
+
tableName: 'users',
|
|
47
|
+
dbClient,
|
|
48
|
+
data: {
|
|
49
|
+
name: 'John Doe',
|
|
50
|
+
email: 'john@example.com',
|
|
51
|
+
age: 30,
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
console.log(user)
|
|
56
|
+
// {
|
|
57
|
+
// id: '550e8400-e29b-41d4-a716-446655440000',
|
|
58
|
+
// name: 'John Doe',
|
|
59
|
+
// email: 'john@example.com',
|
|
60
|
+
// age: 30,
|
|
61
|
+
// created_at: '2023-12-01T10:00:00.000Z',
|
|
62
|
+
// updated_at: '2023-12-01T10:00:00.000Z'
|
|
63
|
+
// }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### With Specific Returning Fields
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// Return only specific fields after insertion
|
|
70
|
+
const user = await insert({
|
|
71
|
+
tableName: 'users',
|
|
72
|
+
dbClient,
|
|
73
|
+
data: {
|
|
74
|
+
name: 'Jane Doe',
|
|
75
|
+
email: 'jane@example.com',
|
|
76
|
+
age: 25,
|
|
77
|
+
},
|
|
78
|
+
returning: ['id', 'name', 'email', 'created_at'],
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
console.log(user)
|
|
82
|
+
// {
|
|
83
|
+
// id: '550e8400-e29b-41d4-a716-446655440001',
|
|
84
|
+
// name: 'Jane Doe',
|
|
85
|
+
// email: 'jane@example.com',
|
|
86
|
+
// created_at: '2023-12-01T10:00:00.000Z'
|
|
87
|
+
// }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### TypeScript Usage
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
interface UserData {
|
|
94
|
+
name: string
|
|
95
|
+
email: string
|
|
96
|
+
age: number
|
|
97
|
+
bio?: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface User {
|
|
101
|
+
id: string
|
|
102
|
+
name: string
|
|
103
|
+
email: string
|
|
104
|
+
age: number
|
|
105
|
+
bio?: string
|
|
106
|
+
created_at: Date
|
|
107
|
+
updated_at: Date
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Typed usage
|
|
111
|
+
const userData: UserData = {
|
|
112
|
+
name: 'John Doe',
|
|
113
|
+
email: 'john@example.com',
|
|
114
|
+
age: 30,
|
|
115
|
+
bio: 'Software developer',
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const user: User = await insert<UserData, User>({
|
|
119
|
+
tableName: 'users',
|
|
120
|
+
dbClient,
|
|
121
|
+
data: userData,
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
console.log(`Created user with ID: ${user.id}`)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Inserting with Optional Fields
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// Insert with some optional fields
|
|
131
|
+
const user = await insert({
|
|
132
|
+
tableName: 'users',
|
|
133
|
+
dbClient,
|
|
134
|
+
data: {
|
|
135
|
+
name: 'John Doe',
|
|
136
|
+
email: 'john@example.com',
|
|
137
|
+
age: 30,
|
|
138
|
+
bio: 'Software developer',
|
|
139
|
+
phone: '+1234567890',
|
|
140
|
+
website: 'https://johndoe.com',
|
|
141
|
+
},
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Inserting with Date Fields
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// Insert with custom date
|
|
149
|
+
const user = await insert({
|
|
150
|
+
tableName: 'users',
|
|
151
|
+
dbClient,
|
|
152
|
+
data: {
|
|
153
|
+
name: 'John Doe',
|
|
154
|
+
email: 'john@example.com',
|
|
155
|
+
birth_date: new Date('1990-01-01'),
|
|
156
|
+
last_login: new Date(),
|
|
157
|
+
},
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Inserting with Boolean Fields
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// Insert with boolean values
|
|
165
|
+
const user = await insert({
|
|
166
|
+
tableName: 'users',
|
|
167
|
+
dbClient,
|
|
168
|
+
data: {
|
|
169
|
+
name: 'John Doe',
|
|
170
|
+
email: 'john@example.com',
|
|
171
|
+
is_active: true,
|
|
172
|
+
is_verified: false,
|
|
173
|
+
newsletter_subscribed: true,
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Inserting with JSON Fields
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// Insert with JSON data
|
|
182
|
+
const user = await insert({
|
|
183
|
+
tableName: 'users',
|
|
184
|
+
dbClient,
|
|
185
|
+
data: {
|
|
186
|
+
name: 'John Doe',
|
|
187
|
+
email: 'john@example.com',
|
|
188
|
+
preferences: {
|
|
189
|
+
theme: 'dark',
|
|
190
|
+
language: 'en',
|
|
191
|
+
notifications: {
|
|
192
|
+
email: true,
|
|
193
|
+
push: false,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
metadata: {
|
|
197
|
+
source: 'web',
|
|
198
|
+
campaign: 'summer2023',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Error Handling
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
try {
|
|
208
|
+
const user = await insert({
|
|
209
|
+
tableName: 'users',
|
|
210
|
+
dbClient,
|
|
211
|
+
data: {
|
|
212
|
+
name: 'John Doe',
|
|
213
|
+
email: 'john@example.com',
|
|
214
|
+
},
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
console.log('User created successfully:', user.id)
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (error.message.includes('duplicate key')) {
|
|
220
|
+
console.error('User with this email already exists')
|
|
221
|
+
} else {
|
|
222
|
+
console.error('Failed to create user:', error.message)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Generated SQL Examples
|
|
228
|
+
|
|
229
|
+
### PostgreSQL
|
|
230
|
+
|
|
231
|
+
```sql
|
|
232
|
+
INSERT INTO users (id, name, email, age, updated_at)
|
|
233
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
234
|
+
RETURNING *
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### MySQL
|
|
238
|
+
|
|
239
|
+
```sql
|
|
240
|
+
INSERT INTO users (id, name, email, age, updated_at)
|
|
241
|
+
VALUES (?, ?, ?, ?, ?)
|
|
242
|
+
|
|
243
|
+
SELECT * FROM users WHERE id = ?
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### With Specific Returning Fields (PostgreSQL)
|
|
247
|
+
|
|
248
|
+
```sql
|
|
249
|
+
INSERT INTO users (id, name, email, age, updated_at)
|
|
250
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
251
|
+
RETURNING id, name, email, created_at
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Best Practices
|
|
255
|
+
|
|
256
|
+
### 1. Use TypeScript for Type Safety
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
interface CreateUserRequest {
|
|
260
|
+
name: string
|
|
261
|
+
email: string
|
|
262
|
+
age: number
|
|
263
|
+
bio?: string
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
interface User {
|
|
267
|
+
id: string
|
|
268
|
+
name: string
|
|
269
|
+
email: string
|
|
270
|
+
age: number
|
|
271
|
+
bio?: string
|
|
272
|
+
created_at: Date
|
|
273
|
+
updated_at: Date
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const createUser = async (userData: CreateUserRequest): Promise<User> => {
|
|
277
|
+
return insert<CreateUserRequest, User>({
|
|
278
|
+
tableName: 'users',
|
|
279
|
+
dbClient,
|
|
280
|
+
data: userData,
|
|
281
|
+
})
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### 2. Validate Data Before Insertion
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
const createUser = async (userData: any) => {
|
|
289
|
+
// Validate required fields
|
|
290
|
+
if (!userData.name || !userData.email) {
|
|
291
|
+
throw new Error('Name and email are required')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Validate email format
|
|
295
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
296
|
+
if (!emailRegex.test(userData.email)) {
|
|
297
|
+
throw new Error('Invalid email format')
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Validate age
|
|
301
|
+
if (userData.age && (userData.age < 0 || userData.age > 150)) {
|
|
302
|
+
throw new Error('Age must be between 0 and 150')
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return insert({
|
|
306
|
+
tableName: 'users',
|
|
307
|
+
dbClient,
|
|
308
|
+
data: userData,
|
|
309
|
+
})
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 3. Handle Duplicate Key Errors
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
const createUser = async (userData: any) => {
|
|
317
|
+
try {
|
|
318
|
+
return await insert({
|
|
319
|
+
tableName: 'users',
|
|
320
|
+
dbClient,
|
|
321
|
+
data: userData,
|
|
322
|
+
})
|
|
323
|
+
} catch (error) {
|
|
324
|
+
if (
|
|
325
|
+
error.message.includes('duplicate key') ||
|
|
326
|
+
error.message.includes('UNIQUE constraint')
|
|
327
|
+
) {
|
|
328
|
+
throw new Error('User with this email already exists')
|
|
329
|
+
}
|
|
330
|
+
throw error
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### 4. Use Specific Returning Fields
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// Good: Return only needed fields
|
|
339
|
+
const user = await insert({
|
|
340
|
+
tableName: 'users',
|
|
341
|
+
dbClient,
|
|
342
|
+
data: userData,
|
|
343
|
+
returning: ['id', 'name', 'email', 'created_at'],
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
// Avoid: Returning all fields when not needed
|
|
347
|
+
const user = await insert({
|
|
348
|
+
tableName: 'users',
|
|
349
|
+
dbClient,
|
|
350
|
+
data: userData,
|
|
351
|
+
})
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### 5. Sanitize Input Data
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
const sanitizeUserData = (data: any) => {
|
|
358
|
+
return {
|
|
359
|
+
name: data.name?.trim(),
|
|
360
|
+
email: data.email?.toLowerCase().trim(),
|
|
361
|
+
age: data.age ? parseInt(data.age) : undefined,
|
|
362
|
+
bio: data.bio?.trim(),
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const createUser = async (rawData: any) => {
|
|
367
|
+
const sanitizedData = sanitizeUserData(rawData)
|
|
368
|
+
|
|
369
|
+
return insert({
|
|
370
|
+
tableName: 'users',
|
|
371
|
+
dbClient,
|
|
372
|
+
data: sanitizedData,
|
|
373
|
+
})
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
## Common Use Cases
|
|
378
|
+
|
|
379
|
+
### 1. User Registration
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
const registerUser = async (registrationData: {
|
|
383
|
+
name: string
|
|
384
|
+
email: string
|
|
385
|
+
password: string
|
|
386
|
+
age?: number
|
|
387
|
+
}) => {
|
|
388
|
+
// Hash password before storing
|
|
389
|
+
const hashedPassword = await hashPassword(registrationData.password)
|
|
390
|
+
|
|
391
|
+
const user = await insert({
|
|
392
|
+
tableName: 'users',
|
|
393
|
+
dbClient,
|
|
394
|
+
data: {
|
|
395
|
+
name: registrationData.name,
|
|
396
|
+
email: registrationData.email,
|
|
397
|
+
password: hashedPassword,
|
|
398
|
+
age: registrationData.age,
|
|
399
|
+
status: 'pending',
|
|
400
|
+
verification_token: generateVerificationToken(),
|
|
401
|
+
},
|
|
402
|
+
returning: ['id', 'name', 'email', 'status', 'created_at'],
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
// Send verification email
|
|
406
|
+
await sendVerificationEmail(user.email, user.verification_token)
|
|
407
|
+
|
|
408
|
+
return user
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### 2. Creating Related Records
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
const createUserWithProfile = async (userData: any, profileData: any) => {
|
|
416
|
+
// Create user first
|
|
417
|
+
const user = await insert({
|
|
418
|
+
tableName: 'users',
|
|
419
|
+
dbClient,
|
|
420
|
+
data: userData,
|
|
421
|
+
returning: ['id'],
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
// Create user profile
|
|
425
|
+
const profile = await insert({
|
|
426
|
+
tableName: 'user_profiles',
|
|
427
|
+
dbClient,
|
|
428
|
+
data: {
|
|
429
|
+
...profileData,
|
|
430
|
+
user_id: user.id,
|
|
431
|
+
},
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
return { user, profile }
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### 3. Audit Trail
|
|
439
|
+
|
|
440
|
+
```typescript
|
|
441
|
+
const createAuditLog = async (action: string, userId: string, details: any) => {
|
|
442
|
+
return insert({
|
|
443
|
+
tableName: 'audit_logs',
|
|
444
|
+
dbClient,
|
|
445
|
+
data: {
|
|
446
|
+
action,
|
|
447
|
+
user_id: userId,
|
|
448
|
+
details: JSON.stringify(details),
|
|
449
|
+
ip_address: details.ipAddress,
|
|
450
|
+
user_agent: details.userAgent,
|
|
451
|
+
timestamp: new Date(),
|
|
452
|
+
},
|
|
453
|
+
})
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### 4. Configuration Management
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
const createConfiguration = async (
|
|
461
|
+
key: string,
|
|
462
|
+
value: any,
|
|
463
|
+
description?: string
|
|
464
|
+
) => {
|
|
465
|
+
return insert({
|
|
466
|
+
tableName: 'configurations',
|
|
467
|
+
dbClient,
|
|
468
|
+
data: {
|
|
469
|
+
key,
|
|
470
|
+
value: JSON.stringify(value),
|
|
471
|
+
description,
|
|
472
|
+
is_active: true,
|
|
473
|
+
},
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
## Database-Specific Considerations
|
|
479
|
+
|
|
480
|
+
### PostgreSQL
|
|
481
|
+
|
|
482
|
+
- Uses `RETURNING` clause for efficient data retrieval
|
|
483
|
+
- Supports complex data types (JSON, arrays, etc.)
|
|
484
|
+
- Better performance with `RETURNING` clause
|
|
485
|
+
|
|
486
|
+
### MySQL
|
|
487
|
+
|
|
488
|
+
- Requires separate `SELECT` query after `INSERT`
|
|
489
|
+
- Good performance for simple inserts
|
|
490
|
+
- Limited support for complex data types
|
|
491
|
+
|
|
492
|
+
## Performance Considerations
|
|
493
|
+
|
|
494
|
+
### 1. Index Impact
|
|
495
|
+
|
|
496
|
+
```sql
|
|
497
|
+
-- Ensure proper indexes exist for unique constraints
|
|
498
|
+
CREATE UNIQUE INDEX idx_users_email ON users(email);
|
|
499
|
+
CREATE INDEX idx_users_created_at ON users(created_at);
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 2. Batch Operations
|
|
503
|
+
|
|
504
|
+
For multiple inserts, consider using `insertMany` instead:
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
// Good: Use insertMany for multiple records
|
|
508
|
+
const users = await insertMany({
|
|
509
|
+
tableName: 'users',
|
|
510
|
+
dbClient,
|
|
511
|
+
data: [
|
|
512
|
+
{ name: 'John', email: 'john@example.com' },
|
|
513
|
+
{ name: 'Jane', email: 'jane@example.com' },
|
|
514
|
+
],
|
|
515
|
+
})
|
|
516
|
+
|
|
517
|
+
// Avoid: Multiple individual inserts
|
|
518
|
+
for (const userData of usersData) {
|
|
519
|
+
await insert({ tableName: 'users', dbClient, data: userData })
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### 3. Connection Pooling
|
|
524
|
+
|
|
525
|
+
Ensure your database client is properly configured with connection pooling for better performance in high-traffic applications.
|
|
526
|
+
|
|
527
|
+
## Error Messages
|
|
528
|
+
|
|
529
|
+
Common error messages you might encounter:
|
|
530
|
+
|
|
531
|
+
- `Table name is required` - The `tableName` parameter is missing
|
|
532
|
+
- `DB client is required` - The `dbClient` parameter is missing
|
|
533
|
+
- `Data object is required` - The `data` parameter is missing
|
|
534
|
+
- `duplicate key value violates unique constraint` - Attempting to insert duplicate unique values
|
|
535
|
+
- `column "field_name" of relation "table_name" does not exist` - Invalid field name
|
|
536
|
+
- `null value in column "field_name" violates not-null constraint` - Required field is missing
|