doix-db 1.0.10 → 1.0.11

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/index.js CHANGED
@@ -10,11 +10,12 @@ module.exports = {
10
10
  DbRelation: require ('./lib/model/DbRelation.js'),
11
11
  DbTable: require ('./lib/model/DbTable.js'),
12
12
  DbView: require ('./lib/model/DbView.js'),
13
- DbObjectMap: require ('./lib/model/DbObjectMap.js'),
13
+ DbSchemaSource: require ('./lib/model/DbSchemaSource.js'),
14
14
  DbObject: require ('./lib/model/DbObject.js'),
15
15
  DbProcedure: require ('./lib/model/DbProcedure.js'),
16
16
  DbFunction: require ('./lib/model/DbFunction.js'),
17
17
  DbModel: require ('./lib/model/DbModel.js'),
18
+ DbSchema: require ('./lib/model/DbSchema.js'),
18
19
 
19
20
  DbType: require ('./lib/model/types/DbType.js'),
20
21
  DbTypeArithmetic: require ('./lib/model/types/DbTypeArithmetic.js'),
@@ -22,12 +22,16 @@ class DbIndex extends DbObject {
22
22
 
23
23
  }
24
24
 
25
+ get schemaName () {
26
+
27
+ return this.relation.schemaName
28
+
29
+ }
30
+
25
31
  setLang (lang) {
26
32
 
27
33
  const {relation} = this
28
34
 
29
- this.schemaName = relation.schemaName
30
-
31
35
  this.localName = this.originalLocalName || lang.getIndexName (relation, this)
32
36
 
33
37
  super.setLang (lang)
@@ -2,12 +2,10 @@ const EventEmitter = require ('events')
2
2
 
3
3
  const DbPool = require ('../DbPool.js')
4
4
  const DbLang = require ('../DbLang.js')
5
- const DbObjectMap = require ('./DbObjectMap.js')
6
5
  const DbRelation = require ('./DbRelation.js')
6
+ const DbSchema = require ('./DbSchema.js')
7
7
  const DbQuery = require ('../query/DbQuery.js')
8
8
 
9
- const EV_MODULES_LOADED = 'modules-loaded'
10
- const EV_OBJECT_CREATED = 'object-created'
11
9
  const EV_OBJECTS_CREATED = 'objects-created'
12
10
 
13
11
  class DbModel extends EventEmitter {
@@ -16,14 +14,12 @@ class DbModel extends EventEmitter {
16
14
 
17
15
  super ()
18
16
 
19
- let mapOptions = {}
17
+ this.schemata = new Map ()
20
18
 
21
- for (const [k, v] of Object.entries (o)) if (v !== undefined) switch (k) {
19
+ let src = []; for (const [k, v] of Object.entries (o)) if (v !== undefined) switch (k) {
22
20
 
23
- case 'dir':
24
- case 'ext':
25
- case 'merger':
26
- mapOptions [k] = v
21
+ case 'src':
22
+ if (!Array.isArray (v)) src.push (v); else src = v
27
23
  break
28
24
 
29
25
  case 'db':
@@ -41,89 +37,111 @@ class DbModel extends EventEmitter {
41
37
 
42
38
  this.lang.model = this
43
39
 
44
- this.map = new DbObjectMap (mapOptions)
40
+ for (const s of src) this.addSchema (s)
45
41
 
46
- this.on (EV_MODULES_LOADED, ( ) => this.createObjects ())
42
+ if (!this.schemata.has (null)) this.addSchema ()
47
43
 
48
- this.on (EV_OBJECT_CREATED, o => o.setLang (this.lang))
49
-
50
- this.on (EV_OBJECTS_CREATED, ( ) => this.resolveReferences ())
44
+ this.on (EV_OBJECTS_CREATED, () => this.resolveReferences ())
51
45
 
52
46
  }
53
-
54
- loadModules () {
55
47
 
56
- this.map.load ()
57
-
58
- this.emit (EV_MODULES_LOADED)
48
+ addSchema (o = {}) {
59
49
 
60
- }
61
-
62
- createObjects () {
50
+ if (typeof o === 'string') o = {root: [o]}
63
51
 
64
- const {lang} = this, map = new Map ()
52
+ if (!o.name) o.name = null
65
53
 
66
- for (const [name, pojo] of this.map.entries ()) {
54
+ if (this.schemata.has (o.name)) throw Error (`DbModel: the schema called ${o.name} is already registered`)
67
55
 
68
- pojo.name = name
69
-
70
- const o = new (lang.getDbObjectClass (pojo)) (pojo)
71
-
72
- o.model = this
56
+ if (!o.schemaName) o.schemaName = o.name
73
57
 
74
- this.emit (EV_OBJECT_CREATED, o)
58
+ for (const {schemaName} of this.schemata.values ()) if (o.schemaName === schemaName) throw Error (`DbModel: the physical name ${schemaName} is already in use`)
75
59
 
76
- map.set (o.name, o)
60
+ o.model = this
77
61
 
78
- }
79
-
80
- this.map = map
62
+ this.schemata.set (o.name, new DbSchema (o))
81
63
 
82
- this.emit (EV_OBJECTS_CREATED)
64
+ }
65
+
66
+ getSchema (name) {
67
+
68
+ return this.schemata.get (name)
83
69
 
84
70
  }
85
71
 
86
- resolveReferences () {
72
+ get defaultSchema () {
87
73
 
88
- for (const {columns} of this.allInstancesOf (DbRelation))
74
+ return this.schemata.get (null)
89
75
 
90
- for (const column of Object.values (columns)) if ('reference' in column) {
76
+ }
91
77
 
92
- const {reference} = column, {targetRelationName} = reference
78
+ get map () {
93
79
 
94
- const targetRelation = this.map.get (targetRelationName); if (!targetRelation) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${targetRelationName}" not found`)
80
+ return this.defaultSchema.map
95
81
 
96
- reference.targetRelation = targetRelation
82
+ }
83
+
84
+ loadModules () {
97
85
 
98
- if (!reference.targetColumnName) {
86
+ for (const {src} of this.schemata.values ()) if (src) src.load ()
99
87
 
100
- const {pk} = targetRelation; if (!pk || pk.length !== 1) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${targetRelationName}"'s primary key must have exactly one column`)
88
+ this.emit (EV_OBJECTS_CREATED)
101
89
 
102
- reference.targetColumnName = pk [0]
90
+ }
103
91
 
104
- }
92
+ find (name) {
105
93
 
106
- const targetColumn = targetRelation.columns [reference.targetColumnName]; if (!targetColumn) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${reference.targetRelationName}.${reference.targetColumnName}" not found`)
94
+ if (this.map.has (name)) return this.map.get (name)
107
95
 
108
- reference.targetColumn = targetColumn
109
-
110
- column.type = targetColumn.type
111
- column.typeDim = targetColumn.typeDim
96
+ const dot = name.indexOf ('.'); if (dot < 1) return undefined
112
97
 
113
- }
98
+ const schema = this.getSchema (name.slice (0, dot)); if (!schema) return undefined
99
+
100
+ return schema.map.get (name.slice (dot + 1)) || undefined
114
101
 
115
102
  }
116
103
 
117
- * allInstancesOf (type) {
104
+ resolveReferences () {
118
105
 
119
- for (const o of this.map.values ())
120
-
121
- if (o instanceof type)
106
+ for (const schema of this.schemata.values ()) {
122
107
 
123
- yield o
108
+ for (const object of schema.map.values ()) if (object instanceof DbRelation) {
124
109
 
125
- }
110
+ for (const column of Object.values (object.columns)) if ('reference' in column) {
111
+
112
+ const {reference} = column, {targetSchemaName, targetRelationName} = reference
113
+
114
+ const targetSchema = targetSchemaName === undefined ? schema : this.getSchema (targetSchemaName); if (!targetSchema) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: schema "${targetSchemaName}" not found`)
115
+
116
+ reference.targetSchema = targetSchema
117
+
118
+ const targetRelation = targetSchema.map.get (targetRelationName); if (!targetRelation) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${targetRelationName}" not found`)
119
+
120
+ reference.targetRelation = targetRelation
121
+
122
+ if (!reference.targetColumnName) {
123
+
124
+ const {pk} = targetRelation; if (!pk || pk.length !== 1) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${targetRelationName}"'s primary key must have exactly one column`)
125
+
126
+ reference.targetColumnName = pk [0]
126
127
 
128
+ }
129
+
130
+ const targetColumn = targetRelation.columns [reference.targetColumnName]; if (!targetColumn) throw Error (`Cannot resolve reference from ${column.relation.name}.${column.name}: "${reference.targetRelationName}.${reference.targetColumnName}" not found`)
131
+
132
+ reference.targetColumn = targetColumn
133
+
134
+ column.type = targetColumn.type
135
+ column.typeDim = targetColumn.typeDim
136
+
137
+ }
138
+
139
+ }
140
+
141
+ }
142
+
143
+ }
144
+
127
145
  createQuery (from, options) {
128
146
 
129
147
  return new DbQuery (this, from, options)
@@ -132,8 +150,6 @@ class DbModel extends EventEmitter {
132
150
 
133
151
  }
134
152
 
135
- DbModel.EV_MODULES_LOADED = EV_MODULES_LOADED
136
- DbModel.EV_OBJECT_CREATED = EV_OBJECT_CREATED
137
153
  DbModel.EV_OBJECTS_CREATED = EV_OBJECTS_CREATED
138
154
 
139
155
  module.exports = DbModel
@@ -10,28 +10,19 @@ class DbObject {
10
10
 
11
11
  if (name.length === 0) throw Error (`name must be a non empty string`)
12
12
 
13
- const pos = name.indexOf ('.')
14
-
15
- if (pos < 0) {
16
-
17
- this.schemaName = null
18
-
19
- this.localName = name
20
-
21
- }
22
- else {
23
-
24
- this.schemaName = name.slice (0, pos)
25
-
26
- this.localName = name.slice (pos + 1)
27
-
28
- }
13
+ this.localName = name
29
14
 
30
15
  }
31
16
 
32
17
  for (const k in o) this [k] = o [k]
33
18
 
34
19
  }
20
+
21
+ get schemaName () {
22
+
23
+ return 'schema' in this ? this.schema.schemaName : null
24
+
25
+ }
35
26
 
36
27
  setLang (lang) {
37
28
 
@@ -47,8 +47,27 @@ class DbReference {
47
47
  this.on ['DELETE'] = ('default' in this.column) ? 'SET DEFAULT' : 'SET NULL'
48
48
  break
49
49
  }
50
+
51
+ const target = src.slice (start, -1).trim ()
52
+
53
+ const dot = target.indexOf ('.'); switch (dot) {
54
+
55
+ case -1:
56
+ this.targetRelationName = target
57
+ break
58
+
59
+ case 0:
60
+ this.targetSchemaName = null
61
+ this.targetRelationName = target.slice (1)
62
+ break
63
+
64
+ default:
65
+ this.targetSchemaName = target.slice (0, dot)
66
+ this.targetRelationName = target.slice (dot + 1)
67
+ break
68
+
69
+ }
50
70
 
51
- this.targetRelationName = src.slice (start, -1).trim ()
52
71
 
53
72
  }
54
73
 
@@ -0,0 +1,65 @@
1
+ const DbSchemaSource = require ('./DbSchemaSource.js')
2
+
3
+ class DbSchema extends require ('events') {
4
+
5
+ constructor (o) {
6
+
7
+ super ()
8
+
9
+ if (!o.name) o.name = null
10
+
11
+ if (!o.schemaName) o.schemaName = o.name
12
+
13
+ const src = {schema: this}; for (const [k, v] of Object.entries (o)) switch (k) {
14
+
15
+ case 'model':
16
+ case 'schemaName':
17
+ case 'name':
18
+ this [k] = v
19
+ break
20
+
21
+ case 'root':
22
+ case 'filter':
23
+ case 'ext':
24
+ case 'merger':
25
+ src [k] = v
26
+ break
27
+
28
+ default:
29
+ throw new Error ('Unknown DbSchema option: ' + k)
30
+
31
+ }
32
+
33
+ if (Object.keys (src).length !== 1) this.src = new DbSchemaSource (src)
34
+
35
+ this.map = new Map ()
36
+
37
+ const {schemaName} = this
38
+
39
+ this.prefix = schemaName ? this.model.lang.quoteName (schemaName) + '.' : ''
40
+
41
+ }
42
+
43
+ add (name, options) {
44
+
45
+ const {map, model} = this; if (map.has (name)) throw Error (`The schema already has the object named "${name}"`)
46
+
47
+ const {lang} = model, clazz = lang.getDbObjectClass (options)
48
+
49
+ const o = new clazz ({...options, name})
50
+
51
+ o.model = model
52
+
53
+ o.schema = this
54
+
55
+ o.setLang (lang)
56
+
57
+ this.emit ('object-created', o)
58
+
59
+ map.set (name, o)
60
+
61
+ }
62
+
63
+ }
64
+
65
+ module.exports = DbSchema
@@ -1,7 +1,7 @@
1
1
  const {ModuleLoader} = require ('doix')
2
2
  const DbObjectMerger = require ('./DbObjectMerger')
3
3
 
4
- class DbObjectMap extends Map {
4
+ class DbSchemaSource extends Map {
5
5
 
6
6
  constructor (o) {
7
7
 
@@ -9,7 +9,23 @@ class DbObjectMap extends Map {
9
9
 
10
10
  let loaderOptions = {}
11
11
 
12
- for (const [k, v] of Object.entries (o)) if (v !== undefined) switch (k) {
12
+ let {root, filter} = o; if (!root) throw Error (`DbSchemaSource: root must be provided`)
13
+
14
+ if (!Array.isArray (root)) root = [root]
15
+
16
+ o.dir = {root}
17
+
18
+ if (filter) o.dir.filter = filter
19
+
20
+ for (const [k, v] of Object.entries (o)) switch (k) {
21
+
22
+ case 'root':
23
+ case 'filter':
24
+ break
25
+
26
+ case 'schema':
27
+ this.schema = v
28
+ break
13
29
 
14
30
  case 'dir':
15
31
  case 'ext':
@@ -22,7 +38,7 @@ class DbObjectMap extends Map {
22
38
  break
23
39
 
24
40
  default:
25
- throw new Error ('Unknown DbObjectMap option: ' + k)
41
+ throw new Error ('Unknown DbSchemaSource option: ' + k)
26
42
 
27
43
  }
28
44
 
@@ -40,6 +56,10 @@ class DbObjectMap extends Map {
40
56
 
41
57
  for (const [k, v] of this.entries ()) merger.emit ('complete', v, k)
42
58
 
59
+ const {schema} = this
60
+
61
+ for (const [k, v] of this.entries ()) schema.add (k, v)
62
+
43
63
  }
44
64
 
45
65
  set (k, v) {
@@ -52,4 +72,4 @@ class DbObjectMap extends Map {
52
72
 
53
73
  }
54
74
 
55
- module.exports = DbObjectMap
75
+ module.exports = DbSchemaSource
@@ -14,8 +14,6 @@ class DbTrigger extends DbObject {
14
14
 
15
15
  setLang (lang) {
16
16
 
17
- this.schemaName = this.table.schemaName
18
-
19
17
  this.qName = lang.quoteName (this.name)
20
18
 
21
19
  }
@@ -1,5 +1,3 @@
1
- const DbRelation = require ('../model/DbRelation.js')
2
- const DbQueryColumn = require ('./DbQueryColumn.js')
3
1
  const DbQueryTableColumnComparison = require ('./DbQueryTableColumnComparison.js')
4
2
 
5
3
  const JOIN_TYPES_ALOWED = ['LEFT', 'INNER', 'CROSS']
@@ -7,24 +5,22 @@ const JOIN_TYPES_ALOWED = ['LEFT', 'INNER', 'CROSS']
7
5
  class DbQueryTable {
8
6
 
9
7
  constructor (query, sql, o = {}) {
10
-
11
- const {model, lang} = query, {map} = model
12
8
 
13
9
  this.isFirst = query.tables.length === 0
14
10
 
15
11
  this.query = query
16
12
 
17
- this.lang = lang
13
+ this.lang = query.lang
18
14
 
19
- if (map.has (sql)) {
15
+ const relation = query.model.find (sql); if (relation) {
20
16
 
21
- this.relation = map.get (sql)
22
-
23
- this.sql = this.relation.qName
17
+ this.relation = relation
24
18
 
25
- this.alias = o.as || sql
19
+ const {schema, qName, columns} = relation
26
20
 
27
- const {columns} = this.relation
21
+ this.sql = schema.prefix + qName
22
+
23
+ this.alias = o.as || sql
28
24
 
29
25
  const names = o.columns || Object.keys (columns)
30
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doix-db",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Shared database related code for doix",
5
5
  "main": "index.js",
6
6
  "files": [