doix-db 0.0.37 → 0.0.42

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
@@ -1,4 +1,5 @@
1
1
  module.exports = {
2
+
2
3
  DbEventLogger : require ('./lib/DbEventLogger.js'),
3
4
  DbClient: require ('./lib/DbClient.js'),
4
5
  DbPool: require ('./lib/DbPool.js'),
@@ -12,9 +13,18 @@ module.exports = {
12
13
  DbObjectMap: require ('./lib/model/DbObjectMap.js'),
13
14
  DbObject: require ('./lib/model/DbObject.js'),
14
15
  DbModel: require ('./lib/model/DbModel.js'),
16
+
17
+ DbType: require ('./lib/model/types/DbType.js'),
18
+ DbTypeArithmetic: require ('./lib/model/types/DbTypeArithmetic.js'),
19
+ DbTypeArithmeticFixed: require ('./lib/model/types/DbTypeArithmeticFixed.js'),
20
+ DbTypeArithmeticFloat: require ('./lib/model/types/DbTypeArithmeticFloat.js'),
21
+ DbTypeArithmeticInt: require ('./lib/model/types/DbTypeArithmeticInt.js'),
22
+ DbTypeCharacter: require ('./lib/model/types/DbTypeCharacter.js'),
23
+
15
24
  DbMigrationPlan:require ('./lib/migration/DbMigrationPlan.js'),
16
25
  DbQuery: require ('./lib/query/DbQuery.js'),
17
26
  DbQueryTable: require ('./lib/query/DbQueryTable.js'),
18
27
  DbQueryColumn: require ('./lib/query/DbQueryColumn.js'),
19
28
  DbQueryOr: require ('./lib/query/DbQueryOr.js'),
29
+
20
30
  }
package/lib/DbLang.js CHANGED
@@ -3,6 +3,13 @@ const stringEscape = require ('string-escape-map')
3
3
  const DbTable = require ('./model/DbTable.js')
4
4
  const DbView = require ('./model/DbView.js')
5
5
 
6
+ const DbType = require ('./model/types/DbType.js')
7
+ const DbTypeArithmetic = require ('./model/types/DbTypeArithmetic.js')
8
+ const DbTypeArithmeticFixed = require ('./model/types/DbTypeArithmeticFixed.js')
9
+ const DbTypeArithmeticFloat = require ('./model/types/DbTypeArithmeticFloat.js')
10
+ const DbTypeArithmeticInt = require ('./model/types/DbTypeArithmeticInt.js')
11
+ const DbTypeCharacter = require ('./model/types/DbTypeCharacter.js')
12
+
6
13
  const CH_Q = "'", CH_QQ = '"'
7
14
 
8
15
  const Q_ESC = new stringEscape ([
@@ -17,6 +24,49 @@ const DELIM_UPDATE = [',', ' AND ']
17
24
 
18
25
  class DbLang {
19
26
 
27
+ static TP_SMALLINT = new DbTypeArithmeticInt ({name: 'SMALLINT', bytes: 2})
28
+ static TP_INT = new DbTypeArithmeticInt ({name: 'INT', bytes: 4})
29
+ static TP_BIGINT = new DbTypeArithmeticInt ({name: 'BIGINT', bytes: 8})
30
+ static TP_REAL = new DbTypeArithmeticFloat ({name: 'REAL'})
31
+ static TP_NUMERIC = new DbTypeArithmeticFixed ({name: 'NUMERIC'})
32
+ static TP_CHAR = new DbTypeCharacter ({name: 'CHAR'})
33
+ static TP_VARCHAR = new DbTypeCharacter ({name: 'VARCHAR'})
34
+
35
+ getTypeDefinition (name) {
36
+
37
+ name = name.toUpperCase ()
38
+
39
+ switch (name) {
40
+
41
+ case 'INT':
42
+ case 'INTEGER':
43
+ return DbLang.TP_INT
44
+
45
+ case 'BIGINT':
46
+ return DbLang.TP_BIGINT
47
+
48
+ case 'SMALLINT':
49
+ return DbLang.TP_SMALLINT
50
+
51
+ case 'CHAR':
52
+ return DbLang.TP_CHAR
53
+
54
+ case 'VARCHAR':
55
+ return DbLang.TP_VARCHAR
56
+
57
+ case 'NUMERIC':
58
+ case 'DECIMAL':
59
+ return DbLang.TP_NUMERIC
60
+
61
+ case 'REAL':
62
+ return DbLang.TP_REAL
63
+
64
+ }
65
+
66
+ return new DbType ({name})
67
+
68
+ }
69
+
20
70
  getDbObjectClass (o) {
21
71
 
22
72
  if (o == null) throw Error ('Empty definition')
@@ -34,13 +84,64 @@ class DbLang {
34
84
  return [DbTable]
35
85
 
36
86
  }
87
+
88
+ isEqualColumnDefault (column, existing) {
89
+
90
+ return column.default == existing.default
91
+
92
+ }
93
+
94
+ isAdequateColumnType (typeAsIs, typeToBe) {
95
+
96
+ if (typeToBe instanceof DbTypeArithmeticInt && typeAsIs instanceof DbTypeArithmeticInt) return (
97
+ typeAsIs.isSigned === typeToBe.isSigned &&
98
+ typeAsIs.bytes >= typeToBe.bytes
99
+ )
100
+
101
+ return typeAsIs.name === typeToBe.name
102
+
103
+ }
104
+
105
+ isAdequateColumnTypeDim (asIs, toBe) {
106
+
107
+ const typeToBe = this.getTypeDefinition (toBe.type), typeAsIs = this.getTypeDefinition (asIs.type)
108
+
109
+ if (typeToBe !== typeAsIs && !this.isAdequateColumnType (typeAsIs, typeToBe)) return false
110
+
111
+ if (toBe.size > 0 && toBe.size > asIs.size) return false
112
+
113
+ if (typeToBe instanceof DbTypeArithmeticFixed && toBe.scale > asIs.scale) return false
114
+
115
+ return true
116
+
117
+ }
118
+
119
+ compareColumns (asIs, toBe) {
37
120
 
121
+ const diff = []
122
+
123
+ if (asIs.nullable !== toBe.nullable) diff.push ('nullable')
124
+
125
+ if (!this.isEqualColumnDefault (asIs, toBe)) diff.push ('default')
126
+
127
+ if (!this.isAdequateColumnTypeDim (asIs, toBe)) diff.push ('typeDim')
128
+
129
+ return diff
130
+
131
+ }
132
+
38
133
  getRequiredMutation (asIs, toBe) {
39
134
 
40
135
  return null
41
136
 
42
137
  }
43
138
 
139
+ getRequiredColumnMutation (asIs, toBe) {
140
+
141
+ return asIs.diff.length === 0 ? null : 'alter-column'
142
+
143
+ }
144
+
44
145
  quoteName (s) {
45
146
 
46
147
  return CH_QQ + QQ_ESC.escape (s) + CH_QQ
@@ -77,14 +178,8 @@ class DbLang {
77
178
 
78
179
  }
79
180
 
80
- }
81
-
82
- getCanonicalTypeName (type) {
83
-
84
- return type.toUpperCase ()
85
-
86
181
  }
87
-
182
+
88
183
  getDbObjectName (o) {
89
184
 
90
185
  const {schemaName, localName} = o
@@ -1,12 +1,28 @@
1
+ const DbRelation = require ('../model/DbRelation.js')
2
+
1
3
  const EventEmitter = require ('events')
2
4
 
3
- const ACTIONS = [
5
+ const OBJECT_ACTIONS = [
4
6
  'create',
5
7
  'alter',
6
8
  'migrate',
7
9
  'recreate',
8
10
  ]
9
11
 
12
+ const COLUMN_ACTIONS = [
13
+ 'add-column',
14
+ 'alter-column',
15
+ 'migrate-column',
16
+ ]
17
+
18
+ const add = (toDo, action, object) => {
19
+
20
+ if (!toDo.has (action)) toDo.set (action, [])
21
+
22
+ toDo.get (action).push (object)
23
+
24
+ }
25
+
10
26
  class DbMigrationPlan extends EventEmitter {
11
27
 
12
28
  constructor (db) {
@@ -22,16 +38,59 @@ class DbMigrationPlan extends EventEmitter {
22
38
 
23
39
  this.on ('existing', o => this.asIs.set (o.name, o))
24
40
 
25
- this.toDo = new Map; for (const a of ACTIONS) this.on (a, o => {
41
+ this.toDo = new Map
26
42
 
27
- if (!this.toDo.has (a)) this.toDo.set (a, [])
43
+ for (const action of OBJECT_ACTIONS)
44
+
45
+ this.on (action, object => add (
46
+ this.toDo,
47
+ action, object))
48
+
49
+ for (const action of COLUMN_ACTIONS)
28
50
 
29
- this.toDo.get (a).push (o)
51
+ this.on (action, column => add (
52
+ this.asIs.get (column.relation.name).toDo,
53
+ action, column))
54
+
55
+ }
56
+
57
+ compareRelation (asIs, toBe) {
58
+
59
+ const {lang} = this, {columns} = toBe, existingColumns = asIs.columns
30
60
 
31
- })
61
+ for (const [name, column] of Object.entries (columns)) {
62
+
63
+ if (name in existingColumns) {
64
+
65
+ const existingColumn = existingColumns [name]
66
+
67
+ existingColumn.diff = lang.compareColumns (existingColumn, column)
68
+
69
+ const action = lang.getRequiredColumnMutation (existingColumn, column)
70
+
71
+ if (action !== null) this.emit (action, column)
72
+
73
+ }
74
+ else {
75
+
76
+ this.emit ('add-column', column)
77
+
78
+ }
79
+
80
+ }
32
81
 
33
82
  }
34
-
83
+
84
+ compareObject (asIs, toBe) {
85
+
86
+ if (asIs.constructor === toBe.constructor && toBe instanceof DbRelation)
87
+
88
+ this.compareRelation (asIs, toBe)
89
+
90
+ return this.lang.getRequiredMutation (asIs, toBe)
91
+
92
+ }
93
+
35
94
  inspectStructure () {
36
95
 
37
96
  const {asIs} = this; if (!asIs) throw Error ('Existing database objects not discovered, call loadStructure () first')
@@ -46,12 +105,12 @@ class DbMigrationPlan extends EventEmitter {
46
105
 
47
106
  !asIs.has (name) ? 'create' :
48
107
 
49
- lang.getRequiredMutation (asIs.get (name), object)
50
-
51
- if (action) this.emit (action, object)
108
+ this.compareObject (asIs.get (name), object)
109
+
110
+ if (action !== null) this.emit (action, object)
52
111
 
53
112
  }
54
-
113
+
55
114
  }
56
115
 
57
116
  async loadStructure () {
@@ -73,11 +132,16 @@ class DbMigrationPlan extends EventEmitter {
73
132
  s.on ('error', fail)
74
133
 
75
134
  s.on ('end', ok)
135
+
136
+ s.on ('data', object => {
76
137
 
77
- s.on ('data', table => this.emit (
78
- toBe.has (table.name) ? 'existing' : 'unknown',
79
- table
80
- ))
138
+ object.toDo = new Map
139
+
140
+ const event = toBe.has (object.name) ? 'existing' : 'unknown'
141
+
142
+ this.emit (event, object)
143
+
144
+ })
81
145
 
82
146
  })
83
147
 
@@ -198,7 +198,9 @@ class DbColumn {
198
198
 
199
199
  if (this.type) {
200
200
 
201
- this.type = lang.getCanonicalTypeName (this.type)
201
+ this.typeDef = lang.getTypeDefinition (this.type)
202
+
203
+ this.type = this.typeDef.name
202
204
 
203
205
  this.typeDim = lang.getDbColumnTypeDim (this)
204
206
 
@@ -0,0 +1,11 @@
1
+ class DbType {
2
+
3
+ constructor (o) {
4
+
5
+ for (const k in o) this [k] = o [k]
6
+
7
+ }
8
+
9
+ }
10
+
11
+ module.exports = DbType
@@ -0,0 +1,13 @@
1
+ const DbType = require ('./DbType.js')
2
+
3
+ class DbTypeArithmetic extends DbType {
4
+
5
+ constructor (o) {
6
+
7
+ super (o)
8
+
9
+ }
10
+
11
+ }
12
+
13
+ module.exports = DbTypeArithmetic
@@ -0,0 +1,13 @@
1
+ const DbTypeArithmetic = require ('./DbTypeArithmetic.js')
2
+
3
+ class DbTypeArithmeticFixed extends DbTypeArithmetic {
4
+
5
+ constructor (o) {
6
+
7
+ super (o)
8
+
9
+ }
10
+
11
+ }
12
+
13
+ module.exports = DbTypeArithmeticFixed
@@ -0,0 +1,13 @@
1
+ const DbTypeArithmetic = require ('./DbTypeArithmetic.js')
2
+
3
+ class DbTypeArithmeticFloat extends DbTypeArithmetic {
4
+
5
+ constructor (o) {
6
+
7
+ super (o)
8
+
9
+ }
10
+
11
+ }
12
+
13
+ module.exports = DbTypeArithmeticFloat
@@ -0,0 +1,15 @@
1
+ const DbTypeArithmetic = require ('./DbTypeArithmetic.js')
2
+
3
+ class DbTypeArithmeticInt extends DbTypeArithmetic {
4
+
5
+ constructor (o) {
6
+
7
+ super (o)
8
+
9
+ if (!('isSigned' in this)) this.isSigned = true
10
+
11
+ }
12
+
13
+ }
14
+
15
+ module.exports = DbTypeArithmeticInt
@@ -0,0 +1,13 @@
1
+ const DbType = require ('./DbType.js')
2
+
3
+ class DbTypeCharacter extends DbType {
4
+
5
+ constructor (o) {
6
+
7
+ super (o)
8
+
9
+ }
10
+
11
+ }
12
+
13
+ module.exports = DbTypeCharacter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doix-db",
3
- "version": "0.0.37",
3
+ "version": "0.0.42",
4
4
  "description": "Shared database related code for doix",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "homepage": "https://github.com/do-/node-doix-db#readme",
42
42
  "peerDependencies": {
43
- "doix": "^0.0.43"
43
+ "doix": "^0.0.44"
44
44
  },
45
45
  "devDependencies": {
46
46
  "jest": "^29.3.1"