masterrecord 0.0.24 → 0.0.26
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/DeleteManager.js +51 -0
- package/Entity/EntityModel.js +94 -30
- package/Entity/EntityModelBuilder.js +6 -28
- package/Entity/EntityTrackerModel.js +200 -20
- package/InsertManager.js +138 -0
- package/MYSQLEngine.js +409 -0
- package/Masterrecord.js +178 -119
- package/Migrations/cli.js +3 -2
- package/Migrations/migrations.js +45 -26
- package/QueryLanguage/queryManager.js +66 -0
- package/QueryLanguage/queryMethods.js +171 -0
- package/QueryLanguage/queryScript.js +331 -0
- package/SQLLiteEngine.js +409 -0
- package/Tools.js +97 -34
- package/package.json +7 -11
- package/QueryLanguage/_Expression.js +0 -322
- package/QueryLanguage/_LogicalQuery.js +0 -23
- package/QueryLanguage/_OperatorList.js +0 -88
- package/QueryLanguage/_QueryModel.js +0 -442
- package/QueryLanguage/_Tokenization.js +0 -173
- package/QueryLanguage/__Query.js +0 -386
- package/QueryLanguage/_simpleQuery.js +0 -184
- package/QueryLanguage/queryBuilder.js +0 -52
- package/SQLiteEngine.js +0 -56
package/Masterrecord.js
CHANGED
|
@@ -3,102 +3,123 @@
|
|
|
3
3
|
// https://www.learnentityframeworkcore.com/dbset/deleting-data
|
|
4
4
|
// version 1.0.14
|
|
5
5
|
|
|
6
|
-
var modelBuilder = require('
|
|
7
|
-
var query = require('masterrecord/QueryLanguage/
|
|
6
|
+
var modelBuilder = require('./Entity/EntityModelBuilder');
|
|
7
|
+
var query = require('masterrecord/QueryLanguage/queryMethods');
|
|
8
8
|
var tools = require('./Tools');
|
|
9
|
-
var
|
|
9
|
+
var SQLLiteEngine = require('masterrecord/SQLLiteEngine');
|
|
10
|
+
var MYSQLEngine = require('masterrecord/MYSQLEngine');
|
|
11
|
+
var insertManager = require('./InsertManager');
|
|
12
|
+
var deleteManager = require('./DeleteManager');
|
|
10
13
|
|
|
11
14
|
class Context {
|
|
12
|
-
|
|
13
15
|
_isModelValid = {
|
|
14
16
|
isValid: true,
|
|
15
17
|
errors: []
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
+
};
|
|
19
|
+
__entities = [];
|
|
20
|
+
__builderEntities = [];
|
|
18
21
|
__trackedEntities = [];
|
|
19
|
-
__relationshipModels = []
|
|
22
|
+
__relationshipModels = [];
|
|
20
23
|
|
|
21
24
|
constructor(){
|
|
22
|
-
|
|
25
|
+
// TODO when we build the sql engine it depends on the which type.
|
|
26
|
+
|
|
27
|
+
this._SQLEngine = "";
|
|
28
|
+
this.__name = this.constructor.name;
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
SQLite expected model
|
|
33
|
+
{
|
|
34
|
+
"type": "better-sqlite3",
|
|
35
|
+
"connection" : "/db/",
|
|
36
|
+
"password": "",
|
|
37
|
+
"username": ""
|
|
38
|
+
}
|
|
39
|
+
*/
|
|
40
|
+
__SQLiteInit(env, sqlName){
|
|
41
|
+
try{
|
|
42
|
+
const sqlite3 = require(sqlName);
|
|
43
|
+
let DBAddress = `${env.completeConnection}${env.env}.sqlite3`;
|
|
44
|
+
var db = new sqlite3(DBAddress, env);
|
|
45
|
+
db.__name = sqlName;
|
|
46
|
+
this._SQLEngine = new SQLLiteEngine();
|
|
47
|
+
return db;
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.log("error SQL", e);
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
/*
|
|
55
|
+
mysql expected model
|
|
56
|
+
{
|
|
57
|
+
"type": "mysql",
|
|
58
|
+
host : 'localhost',
|
|
59
|
+
user : 'me',
|
|
60
|
+
password : 'secret',
|
|
61
|
+
database : 'my_db'
|
|
62
|
+
}
|
|
63
|
+
*/
|
|
64
|
+
__mysqlInit(env, sqlName){
|
|
65
|
+
try{
|
|
66
|
+
const mysql = require(sqlName);
|
|
67
|
+
const connection = mysql.createConnection(env);
|
|
68
|
+
connection.connect();
|
|
69
|
+
db.__name = sqlName;
|
|
70
|
+
this._SQLEngine = new MYSQLEngine();
|
|
71
|
+
return connection;
|
|
64
72
|
|
|
65
73
|
}
|
|
66
|
-
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.log("error SQL", e);
|
|
76
|
+
}
|
|
67
77
|
}
|
|
68
78
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
__clearErrorHandler(){
|
|
82
|
+
this._isModelValid = {
|
|
83
|
+
isValid: true,
|
|
84
|
+
errors: []
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
setup(options, rootFolderLocation){
|
|
89
|
+
|
|
90
|
+
if(options !== undefined){
|
|
91
|
+
if(options.type !== undefined){
|
|
92
|
+
switch(options.type) {
|
|
93
|
+
case "better-sqlite3":
|
|
94
|
+
options.completeConnection = rootFolderLocation + options.connection;
|
|
95
|
+
this.db = this.__SQLiteInit(options, options.type);
|
|
96
|
+
this._SQLEngine.setDB(this.db, "better-sqlite3");
|
|
97
|
+
return this;
|
|
98
|
+
break;
|
|
99
|
+
case "mysql":
|
|
100
|
+
this.db = this.__mysqlInit(options, options.type);
|
|
101
|
+
this._SQLEngine.setDB(this.db, "mysql");
|
|
102
|
+
return this;
|
|
103
|
+
break;
|
|
87
104
|
}
|
|
88
105
|
}
|
|
89
|
-
|
|
106
|
+
else{
|
|
107
|
+
console.log("database type not defined - Master Record");
|
|
108
|
+
}
|
|
90
109
|
}
|
|
110
|
+
else{
|
|
111
|
+
console.log("database information not added - Master Record");
|
|
112
|
+
}
|
|
113
|
+
|
|
91
114
|
}
|
|
92
115
|
|
|
93
|
-
dbset(model){
|
|
94
|
-
var validModel = modelBuilder.
|
|
95
|
-
validModel.__name = model.name;
|
|
96
|
-
this.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
createNewInstance(validModel){
|
|
101
|
-
this[validModel.__name] = new query(validModel, this);
|
|
116
|
+
dbset(model, name){
|
|
117
|
+
var validModel = modelBuilder.create(model);
|
|
118
|
+
validModel.__name = name === undefined ? model.name : name;
|
|
119
|
+
this.__entities.push(validModel); // model object
|
|
120
|
+
var buildMod = tools.createNewInstance(validModel, query, this);
|
|
121
|
+
this.__builderEntities.push(buildMod); // query builder entites
|
|
122
|
+
this[validModel.__name] = buildMod;
|
|
102
123
|
}
|
|
103
124
|
|
|
104
125
|
modelState(){
|
|
@@ -106,59 +127,63 @@ class Context {
|
|
|
106
127
|
}
|
|
107
128
|
|
|
108
129
|
saveChanges(){
|
|
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
|
-
var sqlUpdate = {tableName: currentModel.__entity.__name, primaryKey : primaryKey, value : currentModel[primaryKey] };
|
|
143
|
-
this._SQLEngine.delete(sqlUpdate);
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
130
|
+
try{
|
|
131
|
+
var tracked = this.__trackedEntities;
|
|
132
|
+
// start transaction
|
|
133
|
+
this._SQLEngine.startTransaction();
|
|
134
|
+
for (var model in tracked) {
|
|
135
|
+
var currentModel = tracked[model];
|
|
136
|
+
switch(currentModel.__state) {
|
|
137
|
+
case "insert":
|
|
138
|
+
var insert = new insertManager(this._SQLEngine, this._isModelValid, this.__entities);
|
|
139
|
+
insert.init(currentModel);
|
|
140
|
+
|
|
141
|
+
break;
|
|
142
|
+
case "modified":
|
|
143
|
+
if(currentModel.__dirtyFields.length > 0){
|
|
144
|
+
var cleanCurrentModel = tools.removePrimarykeyandVirtual(currentModel, currentModel._entity);
|
|
145
|
+
// build columns equal to value string
|
|
146
|
+
var argu = this._SQLEngine._buildSQLEqualTo(cleanCurrentModel);
|
|
147
|
+
var primaryKey = tools.getPrimaryKeyObject(cleanCurrentModel.__entity);
|
|
148
|
+
var sqlUpdate = {tableName: cleanCurrentModel.__entity.__name, arg: argu, primaryKey : primaryKey, primaryKeyValue : cleanCurrentModel[primaryKey] };
|
|
149
|
+
this._SQLEngine.update(sqlUpdate);
|
|
150
|
+
}
|
|
151
|
+
else{
|
|
152
|
+
console.log("Tracked entity modified with no values being changed");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// code block
|
|
156
|
+
break;
|
|
157
|
+
case "delete":
|
|
158
|
+
var deleteObject = new deleteManager(this._SQLEngine, this.__entities);
|
|
159
|
+
deleteObject.init(currentModel);
|
|
160
|
+
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
146
163
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
console.log("error", error);
|
|
150
|
-
}
|
|
164
|
+
this.__clearErrorHandler();
|
|
165
|
+
this._SQLEngine.endTransaction();
|
|
151
166
|
}
|
|
152
|
-
|
|
167
|
+
|
|
168
|
+
catch(error){
|
|
169
|
+
this.__clearErrorHandler();
|
|
170
|
+
this._SQLEngine.errorTransaction();
|
|
171
|
+
console.log("error", error);
|
|
172
|
+
this.__clearTracked();
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
this.__clearTracked();
|
|
153
177
|
return true;
|
|
154
178
|
}
|
|
155
179
|
|
|
156
|
-
|
|
180
|
+
// TODO: WHY WE HAVE DOUBLE TRACKED OBJECTS - LOOP THROUGH ALL TRACKED OBJECTS
|
|
181
|
+
__track(model){
|
|
157
182
|
this.__trackedEntities.push(model);
|
|
158
183
|
return model;
|
|
159
184
|
}
|
|
160
185
|
|
|
161
|
-
|
|
186
|
+
__findTracked(id){
|
|
162
187
|
if(id){
|
|
163
188
|
for (var model in this.__trackedEntities) {
|
|
164
189
|
if(this.__trackedEntities[model].__ID === id){
|
|
@@ -168,7 +193,41 @@ class Context {
|
|
|
168
193
|
}
|
|
169
194
|
return null;
|
|
170
195
|
}
|
|
196
|
+
|
|
197
|
+
__clearTracked(){
|
|
198
|
+
this.__trackedEntities = [];
|
|
199
|
+
}
|
|
171
200
|
}
|
|
172
201
|
|
|
173
202
|
|
|
174
|
-
module.exports = Context;
|
|
203
|
+
module.exports = Context;
|
|
204
|
+
|
|
205
|
+
/*
|
|
206
|
+
|
|
207
|
+
//Create new standard
|
|
208
|
+
var standard = new Standard();
|
|
209
|
+
standard.StandardName = "Standard1";
|
|
210
|
+
|
|
211
|
+
//create three new teachers
|
|
212
|
+
var teacher1 = new Teacher();
|
|
213
|
+
teacher1.TeacherName = "New Teacher1";
|
|
214
|
+
|
|
215
|
+
var teacher2 = new Teacher();
|
|
216
|
+
teacher2.TeacherName = "New Teacher2";
|
|
217
|
+
|
|
218
|
+
var teacher3 = new Teacher();
|
|
219
|
+
teacher3.TeacherName = "New Teacher3";
|
|
220
|
+
|
|
221
|
+
//add teachers for new standard
|
|
222
|
+
standard.Teachers.Add(teacher1);
|
|
223
|
+
standard.Teachers.Add(teacher2);
|
|
224
|
+
standard.Teachers.Add(teacher3);
|
|
225
|
+
|
|
226
|
+
using (var dbCtx = new SchoolDBEntities())
|
|
227
|
+
{
|
|
228
|
+
//add standard entity into standards entitySet
|
|
229
|
+
dbCtx.Standards.Add(standard);
|
|
230
|
+
//Save whole entity graph to the database
|
|
231
|
+
dbCtx.SaveChanges();
|
|
232
|
+
}
|
|
233
|
+
*/
|
package/Migrations/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ program
|
|
|
12
12
|
.option('-v, --version', '0.0.1')
|
|
13
13
|
.description('A ORM framework that facilitates the creation and use of business objects whose data requires persistent storage to a database');
|
|
14
14
|
|
|
15
|
-
// Instructions : to run command you must go to folder where
|
|
15
|
+
// Instructions : to run command you must go to folder where context file is located and run command with context file name.
|
|
16
16
|
program
|
|
17
17
|
.command('enable-migrations <contextFileName>')
|
|
18
18
|
.alias('am')
|
|
@@ -41,6 +41,7 @@ program
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// Instructions : to run command you must go to folder where migration file is located.
|
|
44
45
|
program
|
|
45
46
|
.command('add-migration <name>')
|
|
46
47
|
.alias('am')
|
|
@@ -52,7 +53,7 @@ program
|
|
|
52
53
|
var migration = new Migration();
|
|
53
54
|
var context = require(contextSnapshot.contextLocation);
|
|
54
55
|
var newEntity = migration.EDMModelDiffer(contextSnapshot.schema, context);
|
|
55
|
-
if(newEntity
|
|
56
|
+
if(newEntity.length > 0){
|
|
56
57
|
var migrationDate = Date.now();
|
|
57
58
|
migration.migrationCodeGenerator(name, newEntity, migrationDate);
|
|
58
59
|
console.log(`migration ${name}_${migrationDate} created`);
|
package/Migrations/migrations.js
CHANGED
|
@@ -3,36 +3,55 @@ var fs = require('fs');
|
|
|
3
3
|
// https://blog.tekspace.io/code-first-multiple-db-context-migration/
|
|
4
4
|
|
|
5
5
|
// node masterrecord add-migration josh C:\Users\rbatista\Downloads\kollege\freshmen\app\models\context
|
|
6
|
+
class Migrations{
|
|
6
7
|
|
|
8
|
+
EDMModelDiffer(snapShots, tableList){
|
|
9
|
+
new schemaList = []
|
|
10
|
+
const tableKeyList = Object.keys(tableList);
|
|
11
|
+
// loop through tables
|
|
12
|
+
for (const tableKey of tableKeyList) {
|
|
13
|
+
// check if table has already been migrated
|
|
14
|
+
var tableSnapShot = snapShots[tableKey];
|
|
15
|
+
if(tableSnapShot){
|
|
16
|
+
// check if we have the column in the sceama
|
|
17
|
+
const columnKeyList = Object.keys(tableKey);
|
|
18
|
+
// loop through tables
|
|
19
|
+
for (const columnKey of columnKeyList) {
|
|
20
|
+
var newTable = {};
|
|
21
|
+
if(tableSnapShot[columnKey]){
|
|
7
22
|
|
|
23
|
+
/*
|
|
24
|
+
id : {
|
|
25
|
+
nullabale : true,
|
|
26
|
+
type : string
|
|
27
|
+
}
|
|
8
28
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
EDMModelDiffer(snapShot, contextModel){
|
|
29
|
+
id : {
|
|
30
|
+
nullabale : true,
|
|
31
|
+
type : int,
|
|
32
|
+
unique : true
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
*/
|
|
36
|
+
// if we then check if we have all the same types
|
|
37
|
+
// loop through schema list
|
|
38
|
+
// check if we have the same in the context
|
|
39
|
+
// if the same then check if if value is diffrent
|
|
40
|
+
// then delete from context
|
|
41
|
+
// after loop complete wahtever left in conext just push to object
|
|
42
|
+
}
|
|
43
|
+
else{
|
|
44
|
+
// if we dont have it then add it to the
|
|
45
|
+
newTable[columnKey] = tableKey[columnKey];
|
|
46
|
+
schemaList.push(newTable);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}else{
|
|
50
|
+
schemaList.push(contextKeys[key]);
|
|
51
|
+
}
|
|
33
52
|
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
|
|
54
|
+
}
|
|
36
55
|
}
|
|
37
56
|
|
|
38
57
|
migrationCodeGenerator(name, column, migrationDate){
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// ALL THIS SHOULD DO IS BUILD A SQL QUERY
|
|
2
|
+
// version 1.0.1
|
|
3
|
+
|
|
4
|
+
class queryManager{
|
|
5
|
+
constructor( query) {
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
queryObject
|
|
9
|
+
{
|
|
10
|
+
"where": where user.id = 1
|
|
11
|
+
"raw": "select * from tablename where user.id = 2" OR false,
|
|
12
|
+
"builder": builderObject,
|
|
13
|
+
"select" : "*",
|
|
14
|
+
"from" : from tablename
|
|
15
|
+
}
|
|
16
|
+
*/
|
|
17
|
+
this._query = query;
|
|
18
|
+
this._queryBuilder = query.builder;
|
|
19
|
+
this._context = query.builder.__context;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
single(){
|
|
23
|
+
var entityValue = this._context._SQLEngine.get(this._query.getScript());
|
|
24
|
+
var sing = this._queryBuilder.__execute(entityValue, this._queryBuilder);
|
|
25
|
+
return sing;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//
|
|
29
|
+
select(query){
|
|
30
|
+
// this will come after the where
|
|
31
|
+
this._query.select = "select " + query;
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
count(){
|
|
36
|
+
// trying to match string select and relace with select Count(*);
|
|
37
|
+
var res = this._query.select.replace("select *", "select Count(*)");
|
|
38
|
+
var entityValue = this._context._SQLEngine.get(res);
|
|
39
|
+
var val = entityValue[Object.keys(entityValue)[0]];
|
|
40
|
+
return val;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
toList(){
|
|
44
|
+
var entityValue = this._context._SQLEngine.all(this._query);
|
|
45
|
+
var toLi = this._queryBuilder.__executeList(entityValue, this._queryBuilder);
|
|
46
|
+
return toLi;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = queryManager;
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
|
|
56
|
+
LINQ Extension Methods
|
|
57
|
+
First()
|
|
58
|
+
FirstOrDefault()
|
|
59
|
+
SingleOrDefault()
|
|
60
|
+
Count()
|
|
61
|
+
Min()
|
|
62
|
+
Max()
|
|
63
|
+
Last()
|
|
64
|
+
LastOrDefault()
|
|
65
|
+
Average()
|
|
66
|
+
*/
|