doix-db 1.0.72 → 1.0.74
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/lib/DbClient.js +16 -6
- package/lib/DbCsvPrinter.js +2 -0
- package/lib/DbLang.js +212 -0
- package/lib/model/DbColumn.js +6 -158
- package/lib/model/DbSchema.js +2 -4
- package/package.json +1 -1
package/lib/DbClient.js
CHANGED
|
@@ -250,15 +250,25 @@ class DbClient extends EventEmitter {
|
|
|
250
250
|
|
|
251
251
|
const executor = this.batch (options)
|
|
252
252
|
|
|
253
|
-
|
|
253
|
+
try {
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
executor.on ('error', fail)
|
|
257
|
-
executor.on ('close', ok)
|
|
255
|
+
await new Promise ((ok, fail) => {
|
|
258
256
|
|
|
259
|
-
|
|
257
|
+
statements.on ('error', fail)
|
|
258
|
+
executor.on ('error', fail)
|
|
259
|
+
executor.on ('close', ok)
|
|
260
|
+
|
|
261
|
+
statements.pipe (executor)
|
|
262
|
+
|
|
263
|
+
})
|
|
264
|
+
|
|
260
265
|
|
|
261
|
-
}
|
|
266
|
+
}
|
|
267
|
+
catch (cause) {
|
|
268
|
+
|
|
269
|
+
throw Error (cause.message, {cause})
|
|
270
|
+
|
|
271
|
+
}
|
|
262
272
|
|
|
263
273
|
}
|
|
264
274
|
|
package/lib/DbCsvPrinter.js
CHANGED
|
@@ -59,6 +59,8 @@ class DbCsvPrinter extends Transform {
|
|
|
59
59
|
|
|
60
60
|
if (!Array.isArray (columns)) columns = Object.entries (columns).map (([name, def]) => {
|
|
61
61
|
|
|
62
|
+
if (typeof def === 'string') def = this.lang.parseColumn (def)
|
|
63
|
+
|
|
62
64
|
const col = new DbColumn (def)
|
|
63
65
|
|
|
64
66
|
col.name = name
|
package/lib/DbLang.js
CHANGED
|
@@ -14,6 +14,17 @@ const DbTypeCharacter = require ('./model/types/DbTypeCharacter.js')
|
|
|
14
14
|
const DbTypeDate = require ('./model/types/DbTypeDate.js')
|
|
15
15
|
const DbTypeTimestamp = require ('./model/types/DbTypeTimestamp.js')
|
|
16
16
|
|
|
17
|
+
const CH_ROUND_CLOSE = ')'.charCodeAt (0)
|
|
18
|
+
const CH_SQUARE_CLOSE = ']'.charCodeAt (0)
|
|
19
|
+
const CH_CURLY_OPEN = '{'.charCodeAt (0)
|
|
20
|
+
const CH_CURLY_CLOSE = '}'.charCodeAt (0)
|
|
21
|
+
const CH_SLASH = '/'.charCodeAt (0)
|
|
22
|
+
const CH_BACK_SLASH = '\\'.charCodeAt (0)
|
|
23
|
+
const CH_QUESTION = '?'.charCodeAt (0)
|
|
24
|
+
const CH_EXCLAMATION = '!'.charCodeAt (0)
|
|
25
|
+
|
|
26
|
+
const RE_INT = /^[1-9][0-9]*$/
|
|
27
|
+
|
|
17
28
|
const CH_Q = "'", CH_QQ = '"'
|
|
18
29
|
|
|
19
30
|
const Q_ESC = new stringEscape ([
|
|
@@ -93,6 +104,30 @@ class DbLang {
|
|
|
93
104
|
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
createDbObject (options) {
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
|
|
111
|
+
const {columns} = options; if (columns)
|
|
112
|
+
|
|
113
|
+
for (const name in columns)
|
|
114
|
+
|
|
115
|
+
if (typeof columns [name] === 'string')
|
|
116
|
+
|
|
117
|
+
columns [name] = this.parseColumn (columns [name])
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const clazz = this.getDbObjectClass (options)
|
|
122
|
+
|
|
123
|
+
const dbObject = new clazz (options)
|
|
124
|
+
|
|
125
|
+
dbObject.setLang (this)
|
|
126
|
+
|
|
127
|
+
return dbObject
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
96
131
|
getDbObjectClassesToDiscover () {
|
|
97
132
|
|
|
98
133
|
return [DbTable]
|
|
@@ -548,6 +583,183 @@ class DbLang {
|
|
|
548
583
|
|
|
549
584
|
}
|
|
550
585
|
|
|
586
|
+
parseColumn (src) {
|
|
587
|
+
|
|
588
|
+
const o = {src: src.trim ()}
|
|
589
|
+
|
|
590
|
+
try {
|
|
591
|
+
|
|
592
|
+
this.parseColumnComment (o)
|
|
593
|
+
this.parseColumnExtra (o)
|
|
594
|
+
this.parseColumnPattern (o)
|
|
595
|
+
this.parseColumnRange (o)
|
|
596
|
+
this.parseColumnDefault (o)
|
|
597
|
+
|
|
598
|
+
if (o.src.length === 0) throw Error (`Cannot determine the type`)
|
|
599
|
+
|
|
600
|
+
this.parseColumnNullable (o)
|
|
601
|
+
|
|
602
|
+
o.isReference = o.type.startsWith ('(')
|
|
603
|
+
|
|
604
|
+
if (!o.isReference) {
|
|
605
|
+
this.parseColumnDimension (o)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
o.src = src
|
|
609
|
+
|
|
610
|
+
return o
|
|
611
|
+
|
|
612
|
+
}
|
|
613
|
+
catch (cause) {
|
|
614
|
+
|
|
615
|
+
if (o.src.length === 0) throw Error (`Invalid column definition: '${src}'`, {cause})
|
|
616
|
+
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
parseColumnComment (o) {
|
|
622
|
+
|
|
623
|
+
const {src} = o, pos = src.lastIndexOf ('//'); if (pos < 0) return
|
|
624
|
+
|
|
625
|
+
o.comment = src.substring (pos + 2).trimStart ()
|
|
626
|
+
|
|
627
|
+
o.src = src.substring (0, pos).trimEnd ()
|
|
628
|
+
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
parseColumnExtra (o) {
|
|
632
|
+
|
|
633
|
+
const {src} = o
|
|
634
|
+
|
|
635
|
+
let pos = src.length - 1; if (src.charCodeAt (pos) !== CH_CURLY_CLOSE) return
|
|
636
|
+
|
|
637
|
+
let level = 1; while (level !== 0) {
|
|
638
|
+
|
|
639
|
+
if (-- pos < 0) throw Error ('Unbalanced "}"')
|
|
640
|
+
|
|
641
|
+
switch (src.charCodeAt (pos)) {
|
|
642
|
+
|
|
643
|
+
case CH_CURLY_CLOSE:
|
|
644
|
+
level ++
|
|
645
|
+
break
|
|
646
|
+
|
|
647
|
+
case CH_CURLY_OPEN:
|
|
648
|
+
level --
|
|
649
|
+
break
|
|
650
|
+
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
for (const [k, v] of Object.entries (new Function ('return ' + src.substring (pos)) ())) o [k] = v
|
|
656
|
+
|
|
657
|
+
o.src = src.substring (0, pos).trimEnd ()
|
|
658
|
+
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
parseColumnPattern (o) {
|
|
662
|
+
|
|
663
|
+
const {src} = o
|
|
664
|
+
|
|
665
|
+
let pos = src.length - 1; if (src.charCodeAt (pos) !== CH_SLASH) return
|
|
666
|
+
|
|
667
|
+
while (true) {
|
|
668
|
+
|
|
669
|
+
pos = src.lastIndexOf ('/', pos - 1); if (pos < 0) throw Error (`Cannot find opening '/' for the pattern`)
|
|
670
|
+
|
|
671
|
+
if (src.charCodeAt (pos - 1) !== CH_BACK_SLASH) break
|
|
672
|
+
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
o.pattern = src.slice (pos + 1, -1)
|
|
676
|
+
|
|
677
|
+
o.src = src.substring (0, pos).trimEnd ()
|
|
678
|
+
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
parseColumnRange (o) {
|
|
682
|
+
|
|
683
|
+
const {src} = o
|
|
684
|
+
|
|
685
|
+
if (src.charCodeAt (src.length - 1) !== CH_SQUARE_CLOSE) return
|
|
686
|
+
|
|
687
|
+
const begin = src.lastIndexOf ('['); if (begin < 0) throw Error (`Cannot find the opening '[' for range`)
|
|
688
|
+
|
|
689
|
+
const range = src.slice (begin + 1, -1)
|
|
690
|
+
|
|
691
|
+
o.src = src.substring (0, begin).trimEnd ()
|
|
692
|
+
|
|
693
|
+
const pos = range.indexOf ('..'); if (pos < 0) throw Error (`Cannot find '..' between '[' and ']'`)
|
|
694
|
+
|
|
695
|
+
const min = range.substring (0, pos).trim (); if (min.length !== 0) o.min = min
|
|
696
|
+
|
|
697
|
+
const max = range.substring (pos + 2).trim (); if (max.length !== 0) o.max = max
|
|
698
|
+
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
parseColumnDefault (o) {
|
|
702
|
+
|
|
703
|
+
const {src} = o, pos = src.indexOf ('='); if (pos < 0) return
|
|
704
|
+
|
|
705
|
+
o.default = src.substring (pos + 1).trimStart ()
|
|
706
|
+
|
|
707
|
+
if (o.default.length === 0) throw Error (`Empty (but not NULL neither '') default definition`)
|
|
708
|
+
|
|
709
|
+
o.src = src.substring (0, pos).trimEnd ()
|
|
710
|
+
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
parseColumnNullable (o) {
|
|
714
|
+
|
|
715
|
+
let nullable = !('default' in o)
|
|
716
|
+
|
|
717
|
+
const {src} = o, {length} = src, override = nullable ? CH_EXCLAMATION : CH_QUESTION
|
|
718
|
+
|
|
719
|
+
if (src.charCodeAt (length - 1) === override) {
|
|
720
|
+
|
|
721
|
+
nullable = !nullable
|
|
722
|
+
|
|
723
|
+
o.src = src.slice (0, -1).trim ()
|
|
724
|
+
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
o.nullable = nullable
|
|
728
|
+
|
|
729
|
+
o.type = o.src
|
|
730
|
+
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
parseColumnDimension (o) {
|
|
734
|
+
|
|
735
|
+
const src = o.type
|
|
736
|
+
|
|
737
|
+
if (src.charCodeAt (src.length - 1) !== CH_ROUND_CLOSE) return
|
|
738
|
+
|
|
739
|
+
const begin = src.lastIndexOf ('('); if (begin < 0) throw Error (`Cannot find opening '(' for dimension`)
|
|
740
|
+
|
|
741
|
+
let dimension = src.slice (begin + 1, -1)
|
|
742
|
+
|
|
743
|
+
o.type = src.slice (0, begin).trim ()
|
|
744
|
+
|
|
745
|
+
const pos = dimension.indexOf (','); if (pos >= 0) {
|
|
746
|
+
|
|
747
|
+
const scale = dimension.slice (pos + 1).trim ()
|
|
748
|
+
|
|
749
|
+
if (!RE_INT.test (scale)) throw Error (`Not a positive integer as scale`)
|
|
750
|
+
|
|
751
|
+
o.scale = parseInt (scale)
|
|
752
|
+
|
|
753
|
+
dimension = dimension.slice (0, pos).trim ()
|
|
754
|
+
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
if (!RE_INT.test (dimension)) throw Error (`Not a positive integer as column dimension`)
|
|
758
|
+
|
|
759
|
+
o.size = parseInt (dimension)
|
|
760
|
+
|
|
761
|
+
}
|
|
762
|
+
|
|
551
763
|
}
|
|
552
764
|
|
|
553
765
|
module.exports = DbLang
|
package/lib/model/DbColumn.js
CHANGED
|
@@ -1,175 +1,23 @@
|
|
|
1
1
|
const DbReference = require ('./DbReference.js')
|
|
2
2
|
|
|
3
|
-
const CH_ROUND_OPEN = '('.charCodeAt (0)
|
|
4
|
-
const CH_ROUND_CLOSE = ')'.charCodeAt (0)
|
|
5
|
-
const CH_CURLY_CLOSE = '}'.charCodeAt (0)
|
|
6
|
-
const CH_SLASH = '/'.charCodeAt (0)
|
|
7
|
-
const CH_BACK_SLASH = '\\'.charCodeAt (0)
|
|
8
|
-
const CH_QUESTION = '?'.charCodeAt (0)
|
|
9
|
-
const CH_EXCLAMATION = '!'.charCodeAt (0)
|
|
10
|
-
|
|
11
|
-
const RE_INT = /^[1-9][0-9]*$/
|
|
12
|
-
|
|
13
3
|
class DbColumn {
|
|
14
4
|
|
|
15
5
|
constructor (o) {
|
|
16
6
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.src = o
|
|
20
|
-
|
|
21
|
-
this.parse ()
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
|
|
26
|
-
for (const k in o) this [k] = o [k]
|
|
27
|
-
|
|
28
|
-
if (!('nullable' in this)) this.nullable = !('default' in this)
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
parse () {
|
|
35
|
-
|
|
36
|
-
const {src} = this, pos = src.lastIndexOf ('//')
|
|
37
|
-
|
|
38
|
-
if (pos < 0) {
|
|
39
|
-
|
|
40
|
-
this.type = src.trim ()
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
|
|
45
|
-
this.type = src.slice (0, pos).trim ()
|
|
7
|
+
const {isReference} = o
|
|
46
8
|
|
|
47
|
-
|
|
9
|
+
for (const k in o) if (k !== 'isReference') this [k] = o [k]
|
|
48
10
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.parseDefault ()
|
|
52
|
-
this.parsePattern ()
|
|
53
|
-
this.parseRange ()
|
|
54
|
-
this.parseNullable ()
|
|
55
|
-
|
|
56
|
-
if (this.type.charCodeAt (0) === CH_ROUND_OPEN) {
|
|
11
|
+
if (isReference) {
|
|
57
12
|
|
|
58
13
|
this.reference = new DbReference (this.type, this)
|
|
59
|
-
|
|
14
|
+
|
|
60
15
|
this.type = undefined
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
|
|
65
|
-
this.parseDimension ()
|
|
66
|
-
|
|
67
|
-
}
|
|
68
16
|
|
|
69
|
-
|
|
17
|
+
}
|
|
70
18
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const pos = this.type.indexOf ('='); if (pos < 0) return
|
|
74
|
-
|
|
75
|
-
this.default = this.type.slice (pos + 1).trim ()
|
|
76
|
-
|
|
77
|
-
this.type = this.type.slice (0, pos).trim ()
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
parsePattern () {
|
|
82
|
-
|
|
83
|
-
const last = this.default ? 'default' : 'type', src = this [last]
|
|
84
|
-
|
|
85
|
-
let pos = src.length - 1; if (src.charCodeAt (pos) !== CH_SLASH) return
|
|
86
|
-
|
|
87
|
-
while (true) {
|
|
88
|
-
|
|
89
|
-
pos = src.lastIndexOf ('/', pos - 1)
|
|
90
|
-
|
|
91
|
-
if (pos < 0) throw Error (`Invalid column definition: cannot find opening '/' for pattern in '${this.src}'`)
|
|
92
|
-
|
|
93
|
-
if (pos === 0) throw Error (`Invalid column definition: the ${last} is empty in '${this.src}'`)
|
|
94
|
-
|
|
95
|
-
if (src.charCodeAt (pos - 1) !== CH_BACK_SLASH) break
|
|
19
|
+
if (!('nullable' in this)) this.nullable = !('default' in this)
|
|
96
20
|
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.pattern = src.slice (pos + 1, -1)
|
|
100
|
-
|
|
101
|
-
this [last] = src.slice (0, pos).trim ()
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
parseRange () {
|
|
106
|
-
|
|
107
|
-
const last = this.default ? 'default' : 'type', src = this [last]
|
|
108
|
-
|
|
109
|
-
if (src.charCodeAt (src.length - 1) !== CH_CURLY_CLOSE) return
|
|
110
|
-
|
|
111
|
-
const begin = src.lastIndexOf ('{'); if (begin < 0) throw Error (`Invalid column definition: cannot find opening '{' for range in '${this.src}'`)
|
|
112
|
-
|
|
113
|
-
const range = src.slice (begin + 1, -1)
|
|
114
|
-
|
|
115
|
-
this [last] = src.slice (0, begin).trim ()
|
|
116
|
-
|
|
117
|
-
const pos = range.indexOf ('..'); if (pos < 0) throw Error (`Invalid column definition: cannot find '..' between '{' and '}' in '${this.src}'`)
|
|
118
|
-
|
|
119
|
-
const min = range.slice (0, pos).trim (); if (min.length !== 0) this.min = min
|
|
120
|
-
|
|
121
|
-
const max = range.slice (pos + 2).trim (); if (max.length !== 0) this.max = max
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
parseNullable () {
|
|
126
|
-
|
|
127
|
-
let nullable = !('default' in this)
|
|
128
|
-
|
|
129
|
-
const src = this.type, {length} = src; if (length === 0) throw Error (`Invalid column definition: cannot determine type in '${this.src}'`)
|
|
130
|
-
|
|
131
|
-
const override = nullable ? CH_EXCLAMATION : CH_QUESTION
|
|
132
|
-
|
|
133
|
-
if (src.charCodeAt (length - 1) === override) {
|
|
134
|
-
|
|
135
|
-
nullable = !nullable
|
|
136
|
-
|
|
137
|
-
this.type = src.slice (0, -1).trim ()
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
this.nullable = nullable
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
parseDimension () {
|
|
146
|
-
|
|
147
|
-
const src = this.type
|
|
148
|
-
|
|
149
|
-
if (src.charCodeAt (src.length - 1) !== CH_ROUND_CLOSE) return
|
|
150
|
-
|
|
151
|
-
const begin = src.lastIndexOf ('('); if (begin < 0) throw Error (`Invalid column definition: cannot find opening '(' for dimension in '${this.src}'`)
|
|
152
|
-
|
|
153
|
-
let dimension = src.slice (begin + 1, -1)
|
|
154
|
-
|
|
155
|
-
this.type = src.slice (0, begin).trim ()
|
|
156
|
-
|
|
157
|
-
const pos = dimension.indexOf (','); if (pos >= 0) {
|
|
158
|
-
|
|
159
|
-
const scale = dimension.slice (pos + 1).trim ()
|
|
160
|
-
|
|
161
|
-
if (!RE_INT.test (scale)) throw Error (`Invalid column definition: not a positive integer as scale in '${this.src}'`)
|
|
162
|
-
|
|
163
|
-
this.scale = parseInt (scale)
|
|
164
|
-
|
|
165
|
-
dimension = dimension.slice (0, pos).trim ()
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (!RE_INT.test (dimension)) throw Error (`Invalid column definition: not a positive integer as column dimension in '${this.src}'`)
|
|
170
|
-
|
|
171
|
-
this.size = parseInt (dimension)
|
|
172
|
-
|
|
173
21
|
}
|
|
174
22
|
|
|
175
23
|
setLang (lang) {
|
package/lib/model/DbSchema.js
CHANGED
|
@@ -42,14 +42,12 @@ class DbSchema extends require ('events') {
|
|
|
42
42
|
|
|
43
43
|
create (options) {
|
|
44
44
|
|
|
45
|
-
const {model} = this, {lang}
|
|
45
|
+
const {model} = this, {lang} = model
|
|
46
46
|
|
|
47
47
|
options.model = model
|
|
48
48
|
options.schema = this
|
|
49
49
|
|
|
50
|
-
const dbObject
|
|
51
|
-
|
|
52
|
-
dbObject.setLang (lang)
|
|
50
|
+
const dbObject = lang.createDbObject (options)
|
|
53
51
|
|
|
54
52
|
this.emit ('object-created', dbObject)
|
|
55
53
|
|