querize 1.0.9 → 1.1.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 +755 -583
- package/cjs/drivers/drv_mariadb.js +16 -1
- package/cjs/drivers/drv_mariadb.js.map +1 -1
- package/cjs/drivers/drv_mysql2.js +17 -1
- package/cjs/drivers/drv_mysql2.js.map +1 -1
- package/cjs/drivers/drv_oracledb.js +13 -6
- package/cjs/drivers/drv_oracledb.js.map +1 -1
- package/cjs/drivers/index.js +1 -14
- package/cjs/drivers/index.js.map +1 -1
- package/cjs/types/drivers/drv_mariadb.d.ts +1 -1
- package/cjs/types/drivers/drv_mariadb.d.ts.map +1 -1
- package/cjs/types/drivers/drv_mysql2.d.ts +1 -1
- package/cjs/types/drivers/drv_mysql2.d.ts.map +1 -1
- package/cjs/types/drivers/drv_oracledb.d.ts +1 -1
- package/cjs/types/drivers/drv_oracledb.d.ts.map +1 -1
- package/cjs/types/drivers/index.d.ts +6 -0
- package/cjs/types/drivers/index.d.ts.map +1 -1
- package/esm/drivers/drv_mariadb.js +16 -1
- package/esm/drivers/drv_mariadb.js.map +1 -1
- package/esm/drivers/drv_mysql2.js +17 -1
- package/esm/drivers/drv_mysql2.js.map +1 -1
- package/esm/drivers/drv_oracledb.js +13 -6
- package/esm/drivers/drv_oracledb.js.map +1 -1
- package/esm/drivers/index.js +1 -14
- package/esm/drivers/index.js.map +1 -1
- package/esm/types/drivers/drv_mariadb.d.ts +1 -1
- package/esm/types/drivers/drv_mariadb.d.ts.map +1 -1
- package/esm/types/drivers/drv_mysql2.d.ts +1 -1
- package/esm/types/drivers/drv_mysql2.d.ts.map +1 -1
- package/esm/types/drivers/drv_oracledb.d.ts +1 -1
- package/esm/types/drivers/drv_oracledb.d.ts.map +1 -1
- package/esm/types/drivers/index.d.ts +6 -0
- package/esm/types/drivers/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,583 +1,755 @@
|
|
|
1
|
-
# Querize.js
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
.
|
|
242
|
-
.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
.
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
.
|
|
268
|
-
.
|
|
269
|
-
|
|
270
|
-
.execute();
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
} catch (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
query.
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
.where({
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
.
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
//
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
.
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
//
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
1
|
+
# Querize.js
|
|
2
|
+
|
|
3
|
+
> **MySQL / MariaDB / Oracle** query builder for Node.js
|
|
4
|
+
> Promise-based · Fluent API · Connection Pool / Cluster · Transaction support
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/querize)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Table of Contents
|
|
12
|
+
|
|
13
|
+
- [Overview](#overview)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [initialize()](#initialize)
|
|
17
|
+
- [Connection Modes](#connection-modes)
|
|
18
|
+
- [createConnect](#createconnect)
|
|
19
|
+
- [createPool](#createpool)
|
|
20
|
+
- [createCluster](#createcluster)
|
|
21
|
+
- [Operation Modes](#operation-modes)
|
|
22
|
+
- [transaction()](#transaction)
|
|
23
|
+
- [singleton()](#singleton)
|
|
24
|
+
- [Query API](#query-api)
|
|
25
|
+
- [Table / JOIN](#table--join)
|
|
26
|
+
- [WHERE](#where)
|
|
27
|
+
- [SELECT](#select)
|
|
28
|
+
- [INSERT](#insert)
|
|
29
|
+
- [UPDATE](#update)
|
|
30
|
+
- [DELETE](#delete)
|
|
31
|
+
- [Modifiers](#modifiers)
|
|
32
|
+
- [Sub-queries](#sub-queries)
|
|
33
|
+
- [ResultSet](#resultset)
|
|
34
|
+
- [Oracle Driver](#oracle-driver)
|
|
35
|
+
- [Trace / Logging](#trace--logging)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Overview
|
|
40
|
+
|
|
41
|
+
Querize.js is a lightweight, promise-based SQL query builder for Node.js targeting MySQL, MariaDB, and Oracle databases.
|
|
42
|
+
It lets you compose queries through a fluent chaining API without writing raw SQL strings.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Querize → MQDatabase → MQQuery → MQWhere → execute()
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Install Querize
|
|
54
|
+
npm install querize
|
|
55
|
+
|
|
56
|
+
# Install your database driver
|
|
57
|
+
npm install mysql2 # MySQL
|
|
58
|
+
npm install mariadb # MariaDB
|
|
59
|
+
npm install oracledb # Oracle
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> Drivers are loaded dynamically — install only the one you need.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { Querize } from 'querize';
|
|
70
|
+
|
|
71
|
+
// 1. Create a Querize instance with your driver
|
|
72
|
+
const qz = new Querize('mysql2'); // 'mysql2' | 'mariadb' | 'oracle'
|
|
73
|
+
|
|
74
|
+
// 2. Initialize the driver (always recommended)
|
|
75
|
+
await qz.initialize();
|
|
76
|
+
|
|
77
|
+
// 3. Create a connection pool
|
|
78
|
+
const Database = await qz.createPool({
|
|
79
|
+
alias: 'main',
|
|
80
|
+
host: 'localhost',
|
|
81
|
+
user: 'root',
|
|
82
|
+
password: 'password',
|
|
83
|
+
database: 'mydb',
|
|
84
|
+
connectionLimit: 10,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// 4. Run a query
|
|
88
|
+
const query = await Database.singleton();
|
|
89
|
+
const result = await query.table('users').where({ id: 1 }).select().execute();
|
|
90
|
+
console.log(result.rows); // [{ id: 1, name: 'Alice', ... }]
|
|
91
|
+
|
|
92
|
+
// 5. Shutdown
|
|
93
|
+
await Database.destroy();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## initialize()
|
|
99
|
+
|
|
100
|
+
`qz.initialize(option?)` initializes the driver. Call it **once at application startup**, before creating any connection.
|
|
101
|
+
|
|
102
|
+
**It is recommended to always call `initialize()` regardless of which driver you use.**
|
|
103
|
+
For mysql2 and mariadb, it resolves immediately with no side effects.
|
|
104
|
+
For Oracle, it sets up the Instant Client path at this stage.
|
|
105
|
+
This keeps your initialization flow consistent and makes driver swaps seamless.
|
|
106
|
+
|
|
107
|
+
### Signature
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
qz.initialize(option?: { libDir?: string }): Promise<void>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Parameters
|
|
114
|
+
|
|
115
|
+
| Parameter | Driver | Description |
|
|
116
|
+
|-----------|--------|-------------|
|
|
117
|
+
| `option.libDir` | Oracle only | Path to the Oracle Instant Client library. Required for Thick mode. |
|
|
118
|
+
| _(none)_ | mysql2 / mariadb | Call with no arguments. Resolves immediately with no internal processing. |
|
|
119
|
+
|
|
120
|
+
### Behavior by Driver
|
|
121
|
+
|
|
122
|
+
| Driver | Behavior |
|
|
123
|
+
|--------|----------|
|
|
124
|
+
| `mysql2` | Resolves immediately. No initialization required. |
|
|
125
|
+
| `mariadb` | Resolves immediately. No initialization required. |
|
|
126
|
+
| `oracle` | Calls `oracledb.initOracleClient()` if `libDir` is provided (Thick mode). Otherwise runs in Thin mode. |
|
|
127
|
+
|
|
128
|
+
### Examples
|
|
129
|
+
|
|
130
|
+
```javascript
|
|
131
|
+
import { Querize } from 'querize';
|
|
132
|
+
|
|
133
|
+
// mysql2 / mariadb — call with no arguments
|
|
134
|
+
const qz = new Querize('mysql2');
|
|
135
|
+
await qz.initialize();
|
|
136
|
+
const Database = await qz.createPool({ ... });
|
|
137
|
+
|
|
138
|
+
// Oracle — Thin mode (no Instant Client required, oracledb v6+)
|
|
139
|
+
const qz = new Querize('oracle');
|
|
140
|
+
await qz.initialize();
|
|
141
|
+
const Database = await qz.createPool({ ... });
|
|
142
|
+
|
|
143
|
+
// Oracle — Thick mode (provide Instant Client path)
|
|
144
|
+
const qz = new Querize('oracle');
|
|
145
|
+
await qz.initialize({ libDir: '/oracle' });
|
|
146
|
+
const Database = await qz.createPool({ ... });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
> 💡 **Always call `initialize()` regardless of driver — it is the recommended pattern.**
|
|
150
|
+
> Even when using mysql2 or mariadb, the call is a no-op and exits immediately.
|
|
151
|
+
> Fix it in your app startup routine as shown below for portability:
|
|
152
|
+
>
|
|
153
|
+
> ```javascript
|
|
154
|
+
> const qz = new Querize(process.env.DB_DRIVER);
|
|
155
|
+
> await qz.initialize({ libDir: process.env.ORACLE_LIB_DIR });
|
|
156
|
+
> // → mysql2/mariadb: libDir is ignored, resolves immediately
|
|
157
|
+
> // → oracle: initializes in Thick mode
|
|
158
|
+
> ```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Connection Modes
|
|
163
|
+
|
|
164
|
+
Choose how the `Querize` instance manages database connections. All three return `Promise<MQDatabase>`.
|
|
165
|
+
|
|
166
|
+
### createConnect
|
|
167
|
+
|
|
168
|
+
**Single direct connection.** Opens a new TCP connection for every operation and closes it when done.
|
|
169
|
+
Best suited for scripts, CLIs, and migration tools where connection overhead is not a concern.
|
|
170
|
+
|
|
171
|
+
```javascript
|
|
172
|
+
const Database = await qz.createConnect({
|
|
173
|
+
alias: 'main',
|
|
174
|
+
host: 'localhost',
|
|
175
|
+
user: 'dbuser',
|
|
176
|
+
password: 'secret',
|
|
177
|
+
database: 'mydb',
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> ⚠️ Avoid in web servers — each request opens and closes its own TCP connection, which is expensive under concurrent load.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### createPool
|
|
186
|
+
|
|
187
|
+
**Connection pool.** Maintains a set of reusable connections. **Recommended for web servers and APIs.**
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
const Database = await qz.createPool({
|
|
191
|
+
alias: 'main',
|
|
192
|
+
host: 'localhost',
|
|
193
|
+
user: 'dbuser',
|
|
194
|
+
password: 'secret',
|
|
195
|
+
database: 'mydb',
|
|
196
|
+
connectionLimit: 10, // max simultaneous connections
|
|
197
|
+
});
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
| Option | Description |
|
|
201
|
+
|--------|-------------|
|
|
202
|
+
| `alias` | Logical name used for cluster routing |
|
|
203
|
+
| `host` | Database server hostname or IP |
|
|
204
|
+
| `user` / `password` | Authentication credentials |
|
|
205
|
+
| `database` | Default schema |
|
|
206
|
+
| `connectionLimit` | Maximum pool size (recommended: 10–50) |
|
|
207
|
+
| `dateStrings` | Return DATE/DATETIME columns as strings instead of JS Date objects |
|
|
208
|
+
| `supportBigNumbers` | Handle BIGINT columns without precision loss |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### createCluster
|
|
213
|
+
|
|
214
|
+
**Pool cluster.** Groups multiple pools (e.g. primary + replicas) behind a single database object.
|
|
215
|
+
Used for read/write splitting and high-availability setups. Each entry must have a unique `alias`.
|
|
216
|
+
|
|
217
|
+
```javascript
|
|
218
|
+
const Database = await qz.createCluster([
|
|
219
|
+
{
|
|
220
|
+
alias: 'MASTER',
|
|
221
|
+
host: '10.0.0.1',
|
|
222
|
+
user: 'dbuser',
|
|
223
|
+
password: 'secret',
|
|
224
|
+
database: 'mydb',
|
|
225
|
+
connectionLimit: 5,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
alias: 'SLAVE01',
|
|
229
|
+
host: '10.0.0.2',
|
|
230
|
+
user: 'dbuser',
|
|
231
|
+
password: 'secret',
|
|
232
|
+
database: 'mydb',
|
|
233
|
+
connectionLimit: 10,
|
|
234
|
+
},
|
|
235
|
+
]);
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Pass `dbmode` to `transaction()` / `singleton()` to route to a specific node.
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const trx = await Database.transaction('mydb', 'MASTER'); // writes → MASTER
|
|
242
|
+
const q = await Database.singleton('mydb', 'SLAVE01'); // reads → SLAVE01
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Operation Modes
|
|
248
|
+
|
|
249
|
+
Controls how connections are acquired and released during query execution.
|
|
250
|
+
|
|
251
|
+
### transaction()
|
|
252
|
+
|
|
253
|
+
Acquires a dedicated connection, executes `BEGIN`, and returns an `MQQuery` instance.
|
|
254
|
+
All subsequent queries through this object run on the **same connection inside the same transaction**.
|
|
255
|
+
You must call `commit()` or `rollback()` explicitly to end the transaction and release the connection.
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
console.log(`# querize : transaction`);
|
|
259
|
+
{
|
|
260
|
+
const query = await Database.transaction('example', 'master');
|
|
261
|
+
|
|
262
|
+
let result;
|
|
263
|
+
|
|
264
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
265
|
+
console.log('student select1 schid:', result.rows);
|
|
266
|
+
|
|
267
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).update({ schid: 10 }).execute();
|
|
268
|
+
console.log('student update1:', result.affected);
|
|
269
|
+
|
|
270
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
271
|
+
console.log('student select2 schid:', result.rows[0].schid);
|
|
272
|
+
|
|
273
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).update({ schid: 1 }).execute();
|
|
274
|
+
console.log('student update2:', result.affected);
|
|
275
|
+
|
|
276
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
277
|
+
console.log('student select3 schid:', result.rows[0].schid);
|
|
278
|
+
|
|
279
|
+
await query.commit();
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Always wrap in `try/catch` and call `rollback()` on error.
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
const query = await Database.transaction('mydb', 'master');
|
|
287
|
+
try {
|
|
288
|
+
await query.table('accounts').where({ id: 1 }).update({ balance: '= balance - 100' }).execute();
|
|
289
|
+
await query.table('accounts').where({ id: 2 }).update({ balance: '= balance + 100' }).execute();
|
|
290
|
+
await query.commit();
|
|
291
|
+
} catch (err) {
|
|
292
|
+
await query.rollback();
|
|
293
|
+
throw err;
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Signature**
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
Database.transaction(dbname?: string, dbmode?: string): Promise<MQQuery>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
| Parameter | Description |
|
|
304
|
+
|-----------|-------------|
|
|
305
|
+
| `dbname` | If provided, executes `USE <dbname>` immediately after connecting |
|
|
306
|
+
| `dbmode` | Selects a specific cluster node by alias |
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### singleton()
|
|
311
|
+
|
|
312
|
+
Returns an `MQQuery` instance.
|
|
313
|
+
Each call to `execute()` **independently** acquires a connection, runs the SQL, and releases it back to the pool.
|
|
314
|
+
There is no persistent connection between calls. Use this for independent, non-transactional queries.
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
const query = await Database.singleton();
|
|
318
|
+
|
|
319
|
+
// Each execute() uses its own connection
|
|
320
|
+
const result1 = await query.table('users').where({ active: 1 }).select().execute();
|
|
321
|
+
const result2 = await query.table('orders').where({ user_id: 1 }).select().execute();
|
|
322
|
+
|
|
323
|
+
console.log(result1.rows);
|
|
324
|
+
console.log(result2.rows);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Signature**
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
Database.singleton(dbname?: string, dbmode?: string): Promise<MQQuery>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Query API
|
|
336
|
+
|
|
337
|
+
### Table / JOIN
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
query.table('users') // FROM users
|
|
341
|
+
query.table('users', 'u') // FROM users u (alias)
|
|
342
|
+
|
|
343
|
+
query.table('users', 'u')
|
|
344
|
+
.inner('orders', 'o', { 'u.id': 'o.user_id' }) // INNER JOIN
|
|
345
|
+
|
|
346
|
+
query.table('users', 'u')
|
|
347
|
+
.left('orders', 'o', { 'u.id': 'o.user_id' }) // LEFT OUTER JOIN
|
|
348
|
+
|
|
349
|
+
query.table('users', 'u')
|
|
350
|
+
.right('orders', 'o', { 'u.id': 'o.user_id' }) // RIGHT OUTER JOIN
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
### WHERE
|
|
356
|
+
|
|
357
|
+
Pass a plain object to `where()`. Keys are column names, values are match conditions.
|
|
358
|
+
|
|
359
|
+
```javascript
|
|
360
|
+
// Equality
|
|
361
|
+
query.table('users').where({ id: 1, active: 1 })
|
|
362
|
+
// → WHERE (id = 1 AND active = 1)
|
|
363
|
+
|
|
364
|
+
// Comparison operators — prefix the value with the operator
|
|
365
|
+
query.table('orders').where({ amount: '> 1000' })
|
|
366
|
+
// → WHERE (amount > 1000)
|
|
367
|
+
|
|
368
|
+
// OR condition — use an array of objects
|
|
369
|
+
query.table('users').where([{ status: 'active' }, { status: 'pending' }])
|
|
370
|
+
// → WHERE ((status = 'active') OR (status = 'pending'))
|
|
371
|
+
|
|
372
|
+
// IS NULL — use literal()
|
|
373
|
+
query.table('users').where({ deleted_at: query.literal('IS NULL') })
|
|
374
|
+
// → WHERE (deleted_at IS NULL)
|
|
375
|
+
|
|
376
|
+
// AND / OR chaining
|
|
377
|
+
const w = query.table('products').where({ category: 'electronics' });
|
|
378
|
+
w.and({ price: '< 500' });
|
|
379
|
+
w.or({ featured: 1 });
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
### SELECT
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
// All columns
|
|
388
|
+
const result = await query.table('users').where({ active: 1 }).select().execute();
|
|
389
|
+
|
|
390
|
+
// Specific columns
|
|
391
|
+
const result = await query.table('users').select('id', 'name', 'email').execute();
|
|
392
|
+
|
|
393
|
+
// With ORDER BY / GROUP BY / LIMIT
|
|
394
|
+
const result = await query
|
|
395
|
+
.table('orders')
|
|
396
|
+
.where({ user_id: 42 })
|
|
397
|
+
.order_by('created_at DESC')
|
|
398
|
+
.limit(0, 20)
|
|
399
|
+
.select('id', 'total')
|
|
400
|
+
.execute();
|
|
401
|
+
|
|
402
|
+
// FOR UPDATE (use inside a transaction)
|
|
403
|
+
const result = await query.table('items').where({ id: 1 }).select().for_update().execute();
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
### INSERT
|
|
409
|
+
|
|
410
|
+
```javascript
|
|
411
|
+
// Standard INSERT
|
|
412
|
+
const result = await query
|
|
413
|
+
.table('users')
|
|
414
|
+
.insert({ name: 'Alice', email: 'alice@example.com', active: 1 })
|
|
415
|
+
.execute();
|
|
416
|
+
console.log(result.affected); // 1
|
|
417
|
+
console.log(result.insertId); // generated PK
|
|
418
|
+
|
|
419
|
+
// INSERT IGNORE
|
|
420
|
+
const result = await query
|
|
421
|
+
.table('users')
|
|
422
|
+
.insert({ email: 'bob@example.com' }, { ignore: true })
|
|
423
|
+
.execute();
|
|
424
|
+
|
|
425
|
+
// Upsert — ON DUPLICATE KEY UPDATE
|
|
426
|
+
const result = await query
|
|
427
|
+
.table('user_stats')
|
|
428
|
+
.insert({ user_id: 7, login_count: 1 })
|
|
429
|
+
.on('DUPLICATE', { login_count: '= login_count + 1' })
|
|
430
|
+
.execute();
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
### UPDATE
|
|
436
|
+
|
|
437
|
+
```javascript
|
|
438
|
+
// Standard UPDATE
|
|
439
|
+
const result = await query
|
|
440
|
+
.table('users')
|
|
441
|
+
.where({ id: 1 })
|
|
442
|
+
.update({ name: 'Bob', email: 'bob@example.com' })
|
|
443
|
+
.execute();
|
|
444
|
+
console.log(result.affected); // number of rows changed
|
|
445
|
+
|
|
446
|
+
// Arithmetic update — prefix value with =
|
|
447
|
+
const result = await query
|
|
448
|
+
.table('accounts')
|
|
449
|
+
.where({ id: 1 })
|
|
450
|
+
.update({ balance: '= balance - 100' })
|
|
451
|
+
.execute();
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
---
|
|
455
|
+
|
|
456
|
+
### DELETE
|
|
457
|
+
|
|
458
|
+
```javascript
|
|
459
|
+
const result = await query
|
|
460
|
+
.table('sessions')
|
|
461
|
+
.where({ user_id: 1 })
|
|
462
|
+
.delete()
|
|
463
|
+
.execute();
|
|
464
|
+
console.log(result.affected);
|
|
465
|
+
// → DELETE FROM sessions WHERE (user_id = 1)
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
> ⚠️ Calling `.delete()` without `.where()` returns an error query that rejects on `execute()`. (Safety guard)
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
### Modifiers
|
|
473
|
+
|
|
474
|
+
| Method | Description |
|
|
475
|
+
|--------|-------------|
|
|
476
|
+
| `.order_by('col ASC')` | ORDER BY |
|
|
477
|
+
| `.group_by('col')` | GROUP BY |
|
|
478
|
+
| `.limit(count)` | Limit number of rows returned |
|
|
479
|
+
| `.limit(offset, count)` | Limit with offset (pagination) |
|
|
480
|
+
| `.for_update()` | Append `FOR UPDATE` to SELECT (transaction only) |
|
|
481
|
+
| `.on(event, fields)` | Set `ON DUPLICATE KEY UPDATE` fields for INSERT |
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
### Sub-queries
|
|
486
|
+
|
|
487
|
+
Pass a `MQQuery` instance directly as a table source. Build the sub-query inline on the same `query` object to avoid creating a separate variable — a separate instance could cause a memory leak since it holds its own connector reference.
|
|
488
|
+
|
|
489
|
+
```javascript
|
|
490
|
+
const query = await Database.singleton();
|
|
491
|
+
|
|
492
|
+
// Build the sub-query inline on the same query instance
|
|
493
|
+
const result = await query
|
|
494
|
+
.table('users', 'u')
|
|
495
|
+
.inner(
|
|
496
|
+
query.table('orders').where({ status: 'paid' }).select('user_id', 'SUM(total) AS revenue'),
|
|
497
|
+
'o',
|
|
498
|
+
{ 'u.id': 'o.user_id' }
|
|
499
|
+
)
|
|
500
|
+
.select('u.name', 'o.revenue')
|
|
501
|
+
.execute();
|
|
502
|
+
|
|
503
|
+
console.log(result.rows);
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
> ⚠️ Do **not** create a separate `sub` instance for sub-queries.
|
|
507
|
+
> A separate `MQQuery` instance retains its own connector reference and may cause a memory leak if not properly closed.
|
|
508
|
+
> Always compose sub-queries using the same `query` object.
|
|
509
|
+
|
|
510
|
+
---
|
|
511
|
+
|
|
512
|
+
## ResultSet
|
|
513
|
+
|
|
514
|
+
When `execute()` resolves it returns a **ResultSet object**.
|
|
515
|
+
The available fields depend on the type of query.
|
|
516
|
+
|
|
517
|
+
### SELECT — `result.rows`
|
|
518
|
+
|
|
519
|
+
```javascript
|
|
520
|
+
const result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
521
|
+
|
|
522
|
+
result.rows; // full array of row objects
|
|
523
|
+
result.rows[0]; // first row
|
|
524
|
+
result.rows[0].schid; // column value
|
|
525
|
+
result.rows.length; // row count
|
|
526
|
+
|
|
527
|
+
// Example output:
|
|
528
|
+
// [
|
|
529
|
+
// { stdid: 10, name: 'Alice', schid: 1 },
|
|
530
|
+
// ...
|
|
531
|
+
// ]
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Handling empty results:
|
|
535
|
+
|
|
536
|
+
```javascript
|
|
537
|
+
const result = await query.table('users').where({ id: 9999 }).select().execute();
|
|
538
|
+
if (!result.rows || result.rows.length === 0) {
|
|
539
|
+
console.log('Not found');
|
|
540
|
+
} else {
|
|
541
|
+
console.log(result.rows[0].name);
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
---
|
|
546
|
+
|
|
547
|
+
### INSERT / UPDATE / DELETE — `result.affected`
|
|
548
|
+
|
|
549
|
+
```javascript
|
|
550
|
+
// UPDATE
|
|
551
|
+
const result = await query
|
|
552
|
+
.table('tbl_student')
|
|
553
|
+
.where({ stdid: 10 })
|
|
554
|
+
.update({ schid: 10 })
|
|
555
|
+
.execute();
|
|
556
|
+
|
|
557
|
+
result.affected; // number of rows changed
|
|
558
|
+
|
|
559
|
+
// INSERT
|
|
560
|
+
const result = await query
|
|
561
|
+
.table('users')
|
|
562
|
+
.insert({ name: 'Alice' })
|
|
563
|
+
.execute();
|
|
564
|
+
|
|
565
|
+
result.affected; // number of rows inserted
|
|
566
|
+
result.insertId; // generated auto-increment PK
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
---
|
|
570
|
+
|
|
571
|
+
### ResultSet Field Reference
|
|
572
|
+
|
|
573
|
+
| Field | Query Type | Description |
|
|
574
|
+
|-------|------------|-------------|
|
|
575
|
+
| `rows` | SELECT | Array of row objects. Empty result returns `[]`. |
|
|
576
|
+
| `rows[n]` | SELECT | The nth row object. Column names are keys. |
|
|
577
|
+
| `affected` | INSERT / UPDATE / DELETE | Number of rows affected |
|
|
578
|
+
| `insertId` | INSERT | Auto-increment PK of the inserted row. `0` if no AI column. |
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
### Real-world Pattern — ResultSet inside a transaction
|
|
583
|
+
|
|
584
|
+
```javascript
|
|
585
|
+
const query = await Database.transaction('example', 'master');
|
|
586
|
+
|
|
587
|
+
let result;
|
|
588
|
+
|
|
589
|
+
// SELECT → read rows
|
|
590
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
591
|
+
console.log('select1:', result.rows); // full array
|
|
592
|
+
console.log('schid:', result.rows[0].schid); // column access
|
|
593
|
+
|
|
594
|
+
// UPDATE → check affected
|
|
595
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).update({ schid: 10 }).execute();
|
|
596
|
+
console.log('update1 affected:', result.affected);
|
|
597
|
+
|
|
598
|
+
// SELECT again to verify the change
|
|
599
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
600
|
+
console.log('select2 schid:', result.rows[0].schid); // 10
|
|
601
|
+
|
|
602
|
+
// Revert
|
|
603
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).update({ schid: 1 }).execute();
|
|
604
|
+
console.log('update2 affected:', result.affected);
|
|
605
|
+
|
|
606
|
+
result = await query.table('tbl_student').where({ stdid: 10 }).select().execute();
|
|
607
|
+
console.log('select3 schid:', result.rows[0].schid); // 1
|
|
608
|
+
|
|
609
|
+
await query.commit();
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## Oracle Driver
|
|
615
|
+
|
|
616
|
+
Driver identifier: `'oracle'` (uses the `oracledb` package internally)
|
|
617
|
+
|
|
618
|
+
### Installation
|
|
619
|
+
|
|
620
|
+
```bash
|
|
621
|
+
npm install oracledb
|
|
622
|
+
|
|
623
|
+
# For Thick mode, install Oracle Instant Client then call:
|
|
624
|
+
oracledb.initOracleClient({ libDir: '/opt/oracle/instantclient_21_9' });
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
> **Thin vs Thick Mode**
|
|
628
|
+
> oracledb v6+ supports a pure-JS Thin mode that does not require Oracle Instant Client.
|
|
629
|
+
> Use Thick mode only when you need advanced features such as Advanced Queuing or LDAP authentication.
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
### Connection Option
|
|
634
|
+
|
|
635
|
+
Oracle uses the `database` field for an Easy Connect string or TNS alias instead of a `host`/`port` pair.
|
|
636
|
+
|
|
637
|
+
```javascript
|
|
638
|
+
// Easy Connect
|
|
639
|
+
const option = {
|
|
640
|
+
alias: 'main',
|
|
641
|
+
user: 'hr',
|
|
642
|
+
password: 'oracle',
|
|
643
|
+
connectString: 'localhost/XEPDB1', // <host>/<service_name>
|
|
644
|
+
poolMax: 10,
|
|
645
|
+
poolMin: 0,
|
|
646
|
+
poolIncrement: 1,
|
|
647
|
+
poolTimeout: 30,
|
|
648
|
+
poolPingInterval: 10,
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// TNS alias (requires tnsnames.ora or TNS_ADMIN env var)
|
|
652
|
+
const option = {
|
|
653
|
+
alias: 'prod',
|
|
654
|
+
user: 'app_user',
|
|
655
|
+
password: 'secret',
|
|
656
|
+
connectString: 'PROD_DB',
|
|
657
|
+
};
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
### Usage Example
|
|
663
|
+
|
|
664
|
+
```javascript
|
|
665
|
+
const qz = new Querize('oracle');
|
|
666
|
+
await qz.initialize({ libDir: '/oracle' }); // omit for Thin mode
|
|
667
|
+
const Database = await qz.createPool({
|
|
668
|
+
alias: 'main', user: 'hr', password: 'oracle',
|
|
669
|
+
connectString: 'localhost/XEPDB1', poolMax: 10,
|
|
670
|
+
});
|
|
671
|
+
|
|
672
|
+
const query = await Database.singleton();
|
|
673
|
+
const result = await query.table('EMPLOYEES').where({ DEPARTMENT_ID: 90 }).select().execute();
|
|
674
|
+
console.log(result.rows);
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
---
|
|
678
|
+
|
|
679
|
+
### Oracle-specific Notes
|
|
680
|
+
|
|
681
|
+
**Table and column names are UPPERCASE by default** (Oracle default behavior)
|
|
682
|
+
|
|
683
|
+
```javascript
|
|
684
|
+
query.table('EMPLOYEES').where({ DEPARTMENT_ID: 10 }).select('FIRST_NAME', 'SALARY')
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
**DUAL table**
|
|
688
|
+
|
|
689
|
+
```javascript
|
|
690
|
+
const result = await query.table('DUAL').select('SYSDATE').execute();
|
|
691
|
+
// → SELECT SYSDATE FROM DUAL
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
**Pagination** — `.limit()` is not supported in Oracle; use raw SQL
|
|
695
|
+
|
|
696
|
+
```javascript
|
|
697
|
+
// Oracle 12c+
|
|
698
|
+
const result = await Database.query(
|
|
699
|
+
'SELECT * FROM EMPLOYEES ORDER BY EMPLOYEE_ID FETCH FIRST 20 ROWS ONLY'
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
// Oracle 11g and below
|
|
703
|
+
const result = await Database.query(
|
|
704
|
+
'SELECT * FROM (SELECT * FROM EMPLOYEES ORDER BY EMPLOYEE_ID) WHERE ROWNUM <= 20'
|
|
705
|
+
);
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
**SEQUENCE (auto-increment substitute)**
|
|
709
|
+
|
|
710
|
+
```javascript
|
|
711
|
+
const result = await query.table('ORDERS').insert({
|
|
712
|
+
ORDER_ID: query.literal('ORDER_SEQ.NEXTVAL'),
|
|
713
|
+
STATUS: 'NEW',
|
|
714
|
+
USER_ID: 42,
|
|
715
|
+
}).execute();
|
|
716
|
+
```
|
|
717
|
+
|
|
718
|
+
**Oracle ResultSet field differences**
|
|
719
|
+
|
|
720
|
+
| Field | Description |
|
|
721
|
+
|-------|-------------|
|
|
722
|
+
| `rows` | SELECT result array (same shape as mysql2) |
|
|
723
|
+
| `affected` | INSERT/UPDATE/DELETE affected row count (mapped from `rowsAffected`) |
|
|
724
|
+
| `insertId` | Oracle ROWID string of the inserted row (mapped from `lastRowid`) |
|
|
725
|
+
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
## Trace / Logging
|
|
729
|
+
|
|
730
|
+
```javascript
|
|
731
|
+
import { Querize } from 'querize';
|
|
732
|
+
|
|
733
|
+
Querize.setTrace((level, tag, msg) => {
|
|
734
|
+
console.log(`[${level}] ${tag}: ${msg}`);
|
|
735
|
+
});
|
|
736
|
+
// level: 'log' | 'err' | 'sql'
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## Connection Mode Summary
|
|
742
|
+
|
|
743
|
+
| Mode | Connection Handling | Best For |
|
|
744
|
+
|------|---------------------|----------|
|
|
745
|
+
| `createConnect` | New TCP connection per operation | Scripts, CLIs, migrations |
|
|
746
|
+
| `createPool` | Reusable connection pool | Web servers, APIs (recommended default) |
|
|
747
|
+
| `createCluster` | Multiple pools as one object | Read/write splitting, HA setups |
|
|
748
|
+
| `transaction()` | Dedicated connection + BEGIN | Multi-statement atomicity |
|
|
749
|
+
| `singleton()` | Acquire → execute → release per call | Independent single queries |
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
## License
|
|
754
|
+
|
|
755
|
+
MIT © 2020 lClasser — [Querize](https://github.com/itfin-git/Querize)
|