masterrecord 0.0.45 → 0.0.46

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/context.js CHANGED
@@ -4,7 +4,7 @@ var modelBuilder = require('./Entity/entityModelBuilder');
4
4
  var query = require('masterrecord/QueryLanguage/queryMethods');
5
5
  var tools = require('./Tools');
6
6
  var SQLLiteEngine = require('masterrecord/SQLLiteEngine');
7
- var MYSQLEngine = require('masterrecord/MYSQLEngine');
7
+ var MYSQLEngine = require('masterrecord/mySQLEngine');
8
8
  var insertManager = require('./insertManager');
9
9
  var deleteManager = require('./deleteManager');
10
10
  var globSearch = require("glob");
@@ -23,6 +23,7 @@ class context {
23
23
  __name = "";
24
24
  isSQLite = false;
25
25
  isMySQL = false;
26
+ isPostgres = false;
26
27
 
27
28
  constructor(){
28
29
  this. __enviornment = process.env.master;
@@ -128,16 +129,20 @@ class context {
128
129
  var file = this.__findSettings(root, rootFolderLocation, envType);
129
130
  var settings = require(file.file);
130
131
  var options = settings[contextName];
132
+
131
133
  if(options === undefined){
132
134
  console.log("settings missing context name settings");
133
135
  throw error("settings missing context name settings");
134
136
  }
137
+
135
138
  this.validateSQLiteOptions(options);
136
139
  options.completeConnection = `${file.rootFolder}${options.connection}`;
137
140
  var dbDirectory = options.completeConnection.substr(0, options.completeConnection.lastIndexOf("\/"));
141
+
138
142
  if (!fs.existsSync(dbDirectory)){
139
143
  fs.mkdirSync(dbDirectory);
140
144
  }
145
+
141
146
  this.db = this.__SQLiteInit(options, "better-sqlite3");
142
147
  this._SQLEngine.setDB(this.db, "better-sqlite3");
143
148
  return this;
@@ -151,8 +156,9 @@ class context {
151
156
 
152
157
  }
153
158
 
154
- useMySql(options, rootFolderLocation){
159
+ useMySql(options){
155
160
  if(options !== undefined){
161
+ this.isMySQL = true;
156
162
  this.db = this.__mysqlInit(options, "mysql");
157
163
  this._MYSQLEngine.setDB(this.db, "mysql");
158
164
  return this;
@@ -217,6 +223,41 @@ class context {
217
223
  this.__clearErrorHandler();
218
224
  this._SQLEngine.endTransaction();
219
225
  }
226
+ if(this.isMySQL){
227
+ this._SQLEngine.startTransaction();
228
+ for (var model in tracked) {
229
+ var currentModel = tracked[model];
230
+ switch(currentModel.__state) {
231
+ case "insert":
232
+ var insert = new insertManager(this._SQLEngine, this._isModelValid, this.__entities);
233
+ insert.init(currentModel);
234
+
235
+ break;
236
+ case "modified":
237
+ if(currentModel.__dirtyFields.length > 0){
238
+ var cleanCurrentModel = tools.removePrimarykeyandVirtual(currentModel, currentModel._entity);
239
+ // build columns equal to value string
240
+ var argu = this._SQLEngine._buildSQLEqualTo(cleanCurrentModel);
241
+ var primaryKey = tools.getPrimaryKeyObject(cleanCurrentModel.__entity);
242
+ var sqlUpdate = {tableName: cleanCurrentModel.__entity.__name, arg: argu, primaryKey : primaryKey, primaryKeyValue : cleanCurrentModel[primaryKey] };
243
+ this._SQLEngine.update(sqlUpdate);
244
+ }
245
+ else{
246
+ console.log("Tracked entity modified with no values being changed");
247
+ }
248
+
249
+ // code block
250
+ break;
251
+ case "delete":
252
+ var deleteObject = new deleteManager(this._SQLEngine, this.__entities);
253
+ deleteObject.init(currentModel);
254
+
255
+ break;
256
+ }
257
+ }
258
+ this.__clearErrorHandler();
259
+ this._SQLEngine.endTransaction();
260
+ }
220
261
  }
221
262
  else{
222
263
  console.log("save changes has no tracked entities");
package/mySQLEngine.js ADDED
@@ -0,0 +1,409 @@
1
+ var tools = require('masterrecord/Tools');
2
+
3
+ class SQLLiteEngine {
4
+
5
+ unsupportedWords = ["order"]
6
+
7
+ update(query){
8
+ var sqlQuery = ` UPDATE [${query.tableName}]
9
+ SET ${query.arg}
10
+ WHERE [${query.tableName}].[${query.primaryKey}] = ${query.primaryKeyValue}` // primary key for that table =
11
+ return this._run(sqlQuery);
12
+ }
13
+
14
+ delete(queryObject){
15
+ var sqlObject = this._buildDeleteObject(queryObject);
16
+ var sqlQuery = `DELETE FROM [${sqlObject.tableName}] WHERE [${sqlObject.tableName}].[${sqlObject.primaryKey}] = ${sqlObject.value}`;
17
+ return this._execute(sqlQuery);
18
+ }
19
+
20
+ insert(queryObject){
21
+ var sqlObject = this._buildSQLInsertObject(queryObject, queryObject.__entity);
22
+ var query = `INSERT INTO [${sqlObject.tableName}] (${sqlObject.columns})
23
+ VALUES (${sqlObject.values})`;
24
+ var queryObj = this._run(query);
25
+ var open = {
26
+ "id": queryObj.lastInsertRowid
27
+ };
28
+ return open;
29
+ }
30
+
31
+ get(query, entity, context){
32
+ var queryString = {};
33
+ try {
34
+ if(query.raw){
35
+ queryString.query = query.raw;
36
+ }
37
+ else{
38
+ queryString = this.buildQuery(query, entity, context);
39
+ }
40
+ if(queryString.query){
41
+ console.log("SQL:", queryString.query);
42
+ var queryReturn = this.db.prepare(queryString.query).get();
43
+ return queryReturn;
44
+ }
45
+ return null;
46
+ } catch (err) {
47
+ console.error(err);
48
+ return null;
49
+ }
50
+ }
51
+
52
+ getCount(queryObject, entity, context){
53
+ var query = queryObject.script;
54
+ var queryString = {};
55
+ try {
56
+ if(query.raw){
57
+ queryString.query = query.raw;
58
+ }
59
+ else{
60
+ queryString = this.buildQuery(query, entity, context);
61
+ }
62
+ if(queryString.query){
63
+ var queryCount = queryObject.count(queryString.query)
64
+ console.log("SQL:", queryCount );
65
+ var queryReturn = this.db.prepare(queryCount ).get();
66
+ return queryReturn;
67
+ }
68
+ return null;
69
+ } catch (err) {
70
+ console.error(err);
71
+ return null;
72
+ }
73
+ }
74
+
75
+ all(query, entity, context){
76
+ var selectQuery = {};
77
+ try {
78
+ if(query.raw){
79
+ selectQuery.query = query.raw;
80
+ }
81
+ else{
82
+ selectQuery = this.buildQuery(query, entity, context);
83
+ }
84
+ if(selectQuery.query){
85
+ console.log("SQL:", selectQuery.query);
86
+ var queryReturn = this.db.prepare(selectQuery.query).all();
87
+ return queryReturn;
88
+ }
89
+ return null;
90
+ } catch (err) {
91
+ console.error(err);
92
+ return null;
93
+ }
94
+ }
95
+
96
+
97
+ buildQuery(query, entity, context){
98
+
99
+ var queryObject = {};
100
+ queryObject.entity = this.getEntity(entity.__name, query.entityMap);
101
+ queryObject.select = this.buildSelect(query, entity);
102
+ queryObject.from = this.buildFrom(query, entity);
103
+ queryObject.include = this.buildInclude(query, entity, context, queryObject);
104
+ queryObject.where = this.buildWhere(query, entity);
105
+
106
+ var queryString = `${queryObject.select} ${queryObject.from} ${queryObject.include} ${queryObject.where}`;
107
+ return {
108
+ query : queryString,
109
+ entity : this.getEntity(entity.__name, query.entityMap)
110
+ }
111
+
112
+ }
113
+
114
+ buildWhere(query, mainQuery){
115
+ var whereEntity = query.where;
116
+ var strQuery = "";
117
+ var $that = this;
118
+ if(whereEntity){
119
+ var entity = this.getEntity(query.parentName, query.entityMap);
120
+ for (let part in whereEntity[query.parentName]) {
121
+ var item = whereEntity[query.parentName][part];
122
+ for (let exp in item.expressions) {
123
+ var field = tools.capitalizeFirstLetter(item.expressions[exp].field);
124
+ if(mainQuery[field]){
125
+ if(mainQuery[field].isNavigational){
126
+ entity = $that.getEntity(field, query.entityMap);
127
+ field = item.fields[1];
128
+ }
129
+ }
130
+ if(strQuery === ""){
131
+ strQuery = `WHERE ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
132
+ }
133
+ else{
134
+ strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
135
+ }
136
+ }
137
+ }
138
+ }
139
+ return strQuery;
140
+ }
141
+
142
+ buildInclude( query, entity, context){
143
+ var includeQuery = "";
144
+ for (let part in query.include) {
145
+ var includeEntity = query.include[part];
146
+ var $that = this;
147
+ if(includeEntity){
148
+ var parentObj = includeEntity[query.parentName];
149
+ var currentContext = "";
150
+ if(includeEntity.selectFields){
151
+ currentContext = context[tools.capitalizeFirstLetter(includeEntity.selectFields[0])];
152
+ }
153
+
154
+ if(parentObj){
155
+ parentObj.entityMap = query.entityMap;
156
+ var foreignKey = $that.getForeignKey(entity.__name, currentContext.__entity);
157
+ var mainPrimaryKey = $that.getPrimarykey(entity);
158
+ var mainEntity = $that.getEntity(entity.__name, query.entityMap);
159
+ if(currentContext.__entity[entity.__name].type === "hasManyThrough"){
160
+ var foreignTable = tools.capitalizeFirstLetter(currentContext.__entity[entity.__name].foreignTable); //to uppercase letter
161
+ foreignKey = $that.getPrimarykey(currentContext.__entity);
162
+ mainPrimaryKey = context[foreignTable].__entity[currentContext.__entity.__name].foreignKey;
163
+ var mainEntity = $that.getEntity(foreignTable,query.entityMap);
164
+ }
165
+ // add foreign key to select so that it picks it up
166
+ if(parentObj.select){
167
+ parentObj.select.selectFields.push(foreignKey);
168
+ }else{
169
+ parentObj.select = {};
170
+ parentObj.select.selectFields = [];
171
+ parentObj.select.selectFields.push(foreignKey);
172
+ }
173
+
174
+ var innerQuery = $that.buildQuery(parentObj, currentContext.__entity, context);
175
+
176
+ includeQuery += `LEFT JOIN (${innerQuery.query}) AS ${innerQuery.entity} ON ${ mainEntity}.${mainPrimaryKey} = ${innerQuery.entity}.${foreignKey} `;
177
+
178
+ }
179
+ }
180
+ }
181
+ return includeQuery;
182
+ }
183
+
184
+ buildFrom(query, entity){
185
+ var entityName = this.getEntity(entity.__name, query.entityMap);
186
+ if(entityName ){
187
+ return `FROM ${entity.__name } AS ${entityName}`;
188
+ }
189
+ else{ return "" }
190
+ }
191
+
192
+ buildSelect(query, entity){
193
+ // this means that there is a select statement
194
+ var select = "SELECT";
195
+ var arr = "";
196
+ var $that = this;
197
+ if(query.select){
198
+ for (const item in query.select.selectFields) {
199
+ arr += `${$that.getEntity(entity.__name, query.entityMap)}.${query.select.selectFields[item]}, `;
200
+ };
201
+
202
+ }
203
+ else{
204
+ var entityList = this.getEntityList(entity);
205
+ for (const item in entityList) {
206
+ arr += `${$that.getEntity(entity.__name, query.entityMap)}.${entityList[item]}, `;
207
+ };
208
+ }
209
+ arr = arr.replace(/,\s*$/, "");
210
+ return `${select} ${arr} `;
211
+ }
212
+
213
+ getForeignKey(name, entity){
214
+ if(entity && name){
215
+ return entity[name].foreignKey;
216
+ }
217
+ }
218
+
219
+ getPrimarykey(entity){
220
+ for (const item in entity) {
221
+ if(entity[item].primary){
222
+ if(entity[item].primary === true){
223
+ return entity[item].name;
224
+ }
225
+ }
226
+ };
227
+ }
228
+
229
+ getForeignTable(name, entity){
230
+ if(entity && name){
231
+ return entity[name].foreignTable;
232
+ }
233
+ }
234
+
235
+ getInclude(name, query){
236
+ var include = query.include;
237
+ if(include){
238
+ for (let part in include) {
239
+ if(tools.capitalizeFirstLetter(include[part].selectFields[0]) === name){
240
+ return include[part];
241
+ }
242
+ }
243
+ }
244
+ else{
245
+ return "";
246
+ }
247
+ }
248
+
249
+ getEntity(name, maps){
250
+ for (let item in maps) {
251
+ var map = maps[item];
252
+ if(tools.capitalizeFirstLetter(name) === map.name){
253
+ return map.entity
254
+ }
255
+ }
256
+ return "";
257
+ }
258
+
259
+ // return a list of entity names and skip foreign keys and underscore.
260
+ getEntityList(entity){
261
+ var entitiesList = [];
262
+ var $that = this;
263
+ for (var ent in entity) {
264
+ if(!ent.startsWith("_")){
265
+ if(!entity[ent].foreignKey){
266
+ if(entity[ent].relationshipTable){
267
+ if($that.chechUnsupportedWords(entity[ent].relationshipTable)){
268
+ entitiesList.push(`'${entity[ent].relationshipTable}'`);
269
+ }
270
+ else{
271
+ entitiesList.push(entity[ent].relationshipTable);
272
+ }
273
+ }
274
+ else{
275
+ if($that.chechUnsupportedWords(ent)){
276
+ entitiesList.push(`'${ent}'`);
277
+ }
278
+ else{
279
+ entitiesList.push(ent);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ }
285
+ return entitiesList
286
+ }
287
+
288
+ chechUnsupportedWords(word){
289
+ for (var item in this.unsupportedWords) {
290
+ var text = this.unsupportedWords[item];
291
+ if(text === word){
292
+ return true
293
+ }
294
+ }
295
+ return false;
296
+ }
297
+
298
+ startTransaction(){
299
+ this.db.prepare('BEGIN').run();
300
+ }
301
+
302
+ endTransaction(){
303
+ this.db.prepare('COMMIT').run();
304
+ }
305
+
306
+ errorTransaction(){
307
+ this.db.prepare('ROLLBACK').run();
308
+ }
309
+
310
+ _buildSQLEqualTo(model){
311
+ var $that = this;
312
+ var argument = null;
313
+ var dirtyFields = model.__dirtyFields;
314
+
315
+ for (var column in dirtyFields) {
316
+ // TODO Boolean value is a string with a letter
317
+ switch(model.__entity[dirtyFields[column]].type){
318
+ case "integer" :
319
+ argument = argument === null ? `[${dirtyFields[column]}] = ${model[dirtyFields[column]]},` : `${argument} [${dirtyFields[column]}] = ${model[dirtyFields[column]]},`;
320
+ break;
321
+ case "string" :
322
+ argument = argument === null ? `[${dirtyFields[column]}] = '${$that._santizeSingleQuotes(model[dirtyFields[column]])}',` : `${argument} [${dirtyFields[column]}] = '${$that._santizeSingleQuotes(model[dirtyFields[column]])}',`;
323
+ break;
324
+ default:
325
+ argument = argument === null ? `[${dirtyFields[column]}] = '${model[dirtyFields[column]]}',` : `${argument} [${dirtyFields[column]}] = '${model[dirtyFields[column]]}',`;
326
+ }
327
+ }
328
+ return argument.replace(/,\s*$/, "");
329
+ }
330
+
331
+
332
+ _buildDeleteObject(currentModel){
333
+ var primaryKey = currentModel.__Key === undefined ? tools.getPrimaryKeyObject(currentModel.__entity) : currentModel.__Key;
334
+ var value = currentModel.__value === undefined ? currentModel[primaryKey] : currentModel.__value;
335
+ var tableName = currentModel.__tableName === undefined ? currentModel.__entity.__name : currentModel.__tableName;
336
+ return {tableName: tableName, primaryKey : primaryKey, value : value};
337
+ }
338
+
339
+
340
+ // return columns and value strings
341
+ _buildSQLInsertObject(fields, modelEntity){
342
+ var $that = this;
343
+ var columns = null;
344
+ var values = null;
345
+ for (var column in modelEntity) {
346
+ // column1 = value1, column2 = value2, ...
347
+ if(column.indexOf("__") === -1 ){
348
+ // call the get method if avlable
349
+ var fieldColumn = "";
350
+ // check if get function is avaliable if so use that
351
+ fieldColumn = fields[column];
352
+
353
+ if((fieldColumn !== undefined && fieldColumn !== null && fieldColumn !== "" ) && typeof(fieldColumn) !== "object"){
354
+ switch(modelEntity[column].type){
355
+ case "belongsTo" :
356
+ column = modelEntity[column].relationshipTable === undefined ? column : modelEntity[column].relationshipTable;
357
+ break;
358
+ case "string" :
359
+ fieldColumn = `'${$that._santizeSingleQuotes(fields[column])}'`;
360
+ break;
361
+ case "time" :
362
+ fieldColumn = fields[column];
363
+ break;
364
+ }
365
+
366
+ columns = columns === null ? `'${column}',` : `${columns} '${column}',`;
367
+ values = values === null ? `${fieldColumn},` : `${values} ${fieldColumn},`;
368
+
369
+ }
370
+ }
371
+ }
372
+ return {tableName: modelEntity.__name, columns: columns.replace(/,\s*$/, ""), values: values.replace(/,\s*$/, "")};
373
+
374
+ }
375
+
376
+ // will add double single quotes to allow sting to be saved.
377
+ _santizeSingleQuotes(string){
378
+ return string.replace(/'/g, "''");
379
+ }
380
+
381
+ // converts any object into SQL parameter select string
382
+ _convertEntityToSelectParameterString(obj, entityName){
383
+ // todo: loop throgh object and append string with comma to
384
+ var mainString = "";
385
+ const entries = Object.keys(obj);
386
+
387
+ for (const [name] of entries) {
388
+ mainString += `${mainString}, ${entityName}.${name}`;
389
+ }
390
+ return mainString;;
391
+ }
392
+
393
+ _execute(query){
394
+ console.log("SQL:", query);
395
+ return this.db.exec(query);
396
+ }
397
+
398
+ _run(query){
399
+ console.log("SQL:", query);
400
+ return this.db.prepare(query).run();
401
+ }
402
+
403
+ setDB(db, type){
404
+ this.db = db;
405
+ this.dbType = type; // this will let us know which type of sqlengine to use.
406
+ }
407
+ }
408
+
409
+ module.exports = SQLLiteEngine;
package/package.json CHANGED
@@ -5,9 +5,10 @@
5
5
  "commander": "^11.1.0",
6
6
  "glob" : "^10.3.10",
7
7
  "deep-object-diff" : "^1.1.9",
8
- "pg" : "^8.13.3"
8
+ "pg" : "^8.13.3",
9
+ "mysql" : "^2.18.1"
9
10
  },
10
- "version": "0.0.45",
11
+ "version": "0.0.46",
11
12
  "description": "An Object-relational mapping for the Master framework. Master Record connects classes to relational database tables to establish a database with almost zero-configuration ",
12
13
  "homepage": "https://github.com/Tailor/MasterRecord#readme",
13
14
  "repository": {
package/postgresEngine.js CHANGED
@@ -1,6 +1,7 @@
1
+ // Version 0.0.12
1
2
  var tools = require('masterrecord/Tools');
2
3
 
3
- class SQLLiteEngine {
4
+ class postgresEngine {
4
5
 
5
6
  unsupportedWords = ["order"]
6
7
 
@@ -35,7 +36,12 @@ class SQLLiteEngine {
35
36
  queryString.query = query.raw;
36
37
  }
37
38
  else{
38
- queryString = this.buildQuery(query, entity, context);
39
+ if(typeof query === 'string'){
40
+ queryString.query = query;
41
+ }
42
+ else{
43
+ queryString = this.buildQuery(query, entity, context);
44
+ }
39
45
  }
40
46
  if(queryString.query){
41
47
  console.log("SQL:", queryString.query);
@@ -57,10 +63,14 @@ class SQLLiteEngine {
57
63
  queryString.query = query.raw;
58
64
  }
59
65
  else{
60
- queryString = this.buildQuery(query, entity, context);
66
+ if(query.count === undefined){
67
+ query.count = "none";
68
+ }
69
+ queryString.entity = this.getEntity(entity.__name, query.entityMap);
70
+ queryString.query = `SELECT ${this.buildCount(query, entity)} ${this.buildFrom(query, entity)} ${this.buildWhere(query, entity)}`
61
71
  }
62
72
  if(queryString.query){
63
- var queryCount = queryObject.count(queryString.query)
73
+ var queryCount = queryString.query
64
74
  console.log("SQL:", queryCount );
65
75
  var queryReturn = this.db.prepare(queryCount ).get();
66
76
  return queryReturn;
@@ -79,6 +89,7 @@ class SQLLiteEngine {
79
89
  selectQuery.query = query.raw;
80
90
  }
81
91
  else{
92
+
82
93
  selectQuery = this.buildQuery(query, entity, context);
83
94
  }
84
95
  if(selectQuery.query){
@@ -93,17 +104,49 @@ class SQLLiteEngine {
93
104
  }
94
105
  }
95
106
 
107
+ changeNullQuery(query){
108
+ if(query.where){
109
+ var whereClaus;
110
+ whereClaus = query.where.expr.replace("=== null", "is null");
111
+ if(whereClaus === query.where.expr){
112
+ whereClaus = query.where.expr.replace("!= null", "is not null");
113
+ }
114
+ query.where.expr = whereClaus;
115
+ }
116
+
117
+ }
118
+
119
+ buildCount(query, mainQuery){
120
+ var entity = this.getEntity(query.parentName, query.entityMap);
121
+ if(query.count){
122
+ if(query.count !== "none"){
123
+ return `COUNT(${entity}.${query.count.selectFields[0]})`
124
+ }
125
+ else{
126
+ return `COUNT(*)`
127
+ }
128
+ }
129
+ else{
130
+ return ""
131
+ }
132
+ }
96
133
 
97
- buildQuery(query, entity, context){
134
+ buildQuery(query, entity, context, limit){
98
135
 
99
136
  var queryObject = {};
100
137
  queryObject.entity = this.getEntity(entity.__name, query.entityMap);
101
138
  queryObject.select = this.buildSelect(query, entity);
139
+ queryObject.count = this.buildCount(query, entity);
102
140
  queryObject.from = this.buildFrom(query, entity);
103
141
  queryObject.include = this.buildInclude(query, entity, context, queryObject);
104
142
  queryObject.where = this.buildWhere(query, entity);
143
+ queryObject.and = this.buildAnd(query, entity);
144
+ queryObject.take = this.buildTake(query);
145
+ queryObject.skip = this.buildSkip(query);
146
+ queryObject.orderBy = this.buildOrderBy(query);
147
+
105
148
 
106
- var queryString = `${queryObject.select} ${queryObject.from} ${queryObject.include} ${queryObject.where}`;
149
+ var queryString = `${queryObject.select} ${queryObject.count} ${queryObject.from} ${queryObject.include} ${queryObject.where} ${queryObject.and} ${queryObject.orderBy} ${queryObject.take} ${queryObject.skip}`;
107
150
  return {
108
151
  query : queryString,
109
152
  entity : this.getEntity(entity.__name, query.entityMap)
@@ -111,14 +154,62 @@ class SQLLiteEngine {
111
154
 
112
155
  }
113
156
 
114
- buildWhere(query, mainQuery){
115
- var whereEntity = query.where;
157
+ buildOrderBy(query){
158
+ // ORDER BY column1, column2, ... ASC|DESC;
159
+ var $that = this;
160
+ var orderByType = "ASC";
161
+ var orderByEntity = query.orderBy;
162
+ var strQuery = "";
163
+ if(orderByEntity === false){
164
+ orderByType = "DESC";
165
+ orderByEntity = query.orderByDesc;
166
+ }
167
+ if(orderByEntity){
168
+ var entity = this.getEntity(query.parentName, query.entityMap);
169
+ var fieldList = "";
170
+ for (const item in orderByEntity.selectFields) {
171
+ fieldList += `${entity}.${orderByEntity.selectFields[item]}, `;
172
+ };
173
+ fieldList = fieldList.replace(/,\s*$/, "");
174
+ strQuery = "ORDER BY";
175
+ strQuery += ` ${fieldList} ${orderByType}`;
176
+ }
177
+ return strQuery;
178
+ }
179
+
180
+ buildTake(query){
181
+ if(query.take){
182
+ return `LIMIT ${query.take}`
183
+ }
184
+ else{
185
+ return "";
186
+ }
187
+ }
188
+
189
+ buildSkip(query){
190
+ if(query.skip){
191
+ return `OFFSET ${query.skip}`
192
+ }
193
+ else{
194
+ return "";
195
+ }
196
+ }
197
+
198
+ buildAnd(query, mainQuery){
199
+ // loop through the AND
200
+ // loop update ther where .expr
201
+ var andEntity = query.and;
116
202
  var strQuery = "";
117
203
  var $that = this;
118
- if(whereEntity){
204
+ var str = "";
205
+
206
+ if(andEntity){
119
207
  var entity = this.getEntity(query.parentName, query.entityMap);
120
- for (let part in whereEntity[query.parentName]) {
121
- var item = whereEntity[query.parentName][part];
208
+ var andList = [];
209
+ for (let entityPart in andEntity) { // loop through list of and's
210
+ var itemEntity = andEntity[entityPart]; // get the entityANd
211
+ for (let table in itemEntity[query.parentName]) { // find the main table
212
+ var item = itemEntity[query.parentName][table];
122
213
  for (let exp in item.expressions) {
123
214
  var field = tools.capitalizeFirstLetter(item.expressions[exp].field);
124
215
  if(mainQuery[field]){
@@ -127,14 +218,90 @@ class SQLLiteEngine {
127
218
  field = item.fields[1];
128
219
  }
129
220
  }
221
+ if(item.expressions[exp].arg === "null"){
222
+ if(item.expressions[exp].func === "="){
223
+ item.expressions[exp].func = "is"
224
+ }
225
+ if(item.expressions[exp].func === "!="){
226
+ item.expressions[exp].func = "is not"
227
+ }
228
+ }
130
229
  if(strQuery === ""){
131
- strQuery = `WHERE ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
230
+ if(item.expressions[exp].arg === "null"){
231
+ strQuery = `${entity}.${field} ${item.expressions[exp].func} ${item.expressions[exp].arg}`;
232
+ }else{
233
+ strQuery = `${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
234
+ }
235
+ }
236
+ else{
237
+ if(item.expressions[exp].arg === "null"){
238
+ strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} ${item.expressions[exp].arg}`;
239
+ }else{
240
+ strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
241
+ }
242
+
243
+ }
244
+ }
245
+ andList.push(strQuery);
246
+ }
247
+ }
248
+ }
249
+
250
+ if(andList.length > 0){
251
+ str = `and ${andList.join(" and ")}`;
252
+ }
253
+ return str
254
+ }
255
+
256
+ buildWhere(query, mainQuery){
257
+ var whereEntity = query.where;
258
+
259
+ var strQuery = "";
260
+ var $that = this;
261
+ if(whereEntity){
262
+ var entity = this.getEntity(query.parentName, query.entityMap);
263
+
264
+ var item = whereEntity[query.parentName].query;
265
+ for (let exp in item.expressions) {
266
+ var field = tools.capitalizeFirstLetter(item.expressions[exp].field);
267
+ if(mainQuery[field]){
268
+ if(mainQuery[field].isNavigational){
269
+ entity = $that.getEntity(field, query.entityMap);
270
+ field = item.fields[1];
271
+ }
272
+ }
273
+ if(item.expressions[exp].arg === "null"){
274
+ if(item.expressions[exp].func === "="){
275
+ item.expressions[exp].func = "is"
276
+ }
277
+ if(item.expressions[exp].func === "!="){
278
+ item.expressions[exp].func = "is not"
279
+ }
280
+ }
281
+ if(strQuery === ""){
282
+ if(item.expressions[exp].arg === "null"){
283
+ strQuery = `WHERE ${entity}.${field} ${item.expressions[exp].func} ${item.expressions[exp].arg}`;
284
+ }else{
285
+ if(item.expressions[exp].func === "IN"){
286
+ strQuery = `WHERE ${entity}.${field} ${item.expressions[exp].func} ${item.expressions[exp].arg}`;
132
287
  }
133
288
  else{
134
- strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
289
+ strQuery = `WHERE ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
135
290
  }
136
291
  }
137
292
  }
293
+ else{
294
+ if(item.expressions[exp].arg === "null"){
295
+ strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} ${item.expressions[exp].arg}`;
296
+ }else{
297
+ strQuery = `${strQuery} and ${entity}.${field} ${item.expressions[exp].func} '${item.expressions[exp].arg}'`;
298
+ }
299
+
300
+ }
301
+ }
302
+
303
+
304
+
138
305
  }
139
306
  return strQuery;
140
307
  }
@@ -249,7 +416,7 @@ class SQLLiteEngine {
249
416
  getEntity(name, maps){
250
417
  for (let item in maps) {
251
418
  var map = maps[item];
252
- if(tools.capitalizeFirstLetter(name) === map.name){
419
+ if(tools.capitalizeFirstLetter(name) === tools.capitalizeFirstLetter(map.name)){
253
420
  return map.entity
254
421
  }
255
422
  }
@@ -263,21 +430,16 @@ class SQLLiteEngine {
263
430
  for (var ent in entity) {
264
431
  if(!ent.startsWith("_")){
265
432
  if(!entity[ent].foreignKey){
266
- if(entity[ent].relationshipTable){
267
- if($that.chechUnsupportedWords(entity[ent].relationshipTable)){
268
- entitiesList.push(`'${entity[ent].relationshipTable}'`);
269
- }
270
- else{
271
- entitiesList.push(entity[ent].relationshipTable);
272
- }
433
+ if($that.chechUnsupportedWords(ent)){
434
+ entitiesList.push(`'${ent}'`);
273
435
  }
274
436
  else{
275
- if($that.chechUnsupportedWords(ent)){
276
- entitiesList.push(`'${ent}'`);
277
- }
278
- else{
279
- entitiesList.push(ent);
280
- }
437
+ entitiesList.push(ent);
438
+ }
439
+ }
440
+ else{
441
+ if(entity[ent].type === 'belongsTo'){
442
+ entitiesList.push(`${entity[ent].foreignKey}`);
281
443
  }
282
444
  }
283
445
  }
@@ -311,16 +473,39 @@ class SQLLiteEngine {
311
473
  var $that = this;
312
474
  var argument = null;
313
475
  var dirtyFields = model.__dirtyFields;
314
-
476
+
315
477
  for (var column in dirtyFields) {
478
+
316
479
  // TODO Boolean value is a string with a letter
317
480
  switch(model.__entity[dirtyFields[column]].type){
318
- case "integer" :
481
+ case "integer" :
482
+ //model.__entity[dirtyFields[column]].skipGetFunction = true;
319
483
  argument = argument === null ? `[${dirtyFields[column]}] = ${model[dirtyFields[column]]},` : `${argument} [${dirtyFields[column]}] = ${model[dirtyFields[column]]},`;
484
+ //model.__entity[dirtyFields[column]].skipGetFunction = false;
320
485
  break;
321
486
  case "string" :
322
487
  argument = argument === null ? `[${dirtyFields[column]}] = '${$that._santizeSingleQuotes(model[dirtyFields[column]])}',` : `${argument} [${dirtyFields[column]}] = '${$that._santizeSingleQuotes(model[dirtyFields[column]])}',`;
323
488
  break;
489
+ case "boolean" :
490
+ var bool = "";
491
+ if(model.__entity[dirtyFields[column]].valueConversion){
492
+ bool = tools.convertBooleanToNumber(model[dirtyFields[column]]);
493
+ }
494
+ else{
495
+ bool = model[dirtyFields[column]];
496
+ }
497
+ argument = argument === null ? `[${dirtyFields[column]}] = '${bool}',` : `${argument} [${dirtyFields[column]}] = ${bool},`;
498
+ break;
499
+ case "time" :
500
+ argument = argument === null ? `[${dirtyFields[column]}] = '${model[dirtyFields[column]]}',` : `${argument} [${dirtyFields[column]}] = ${model[dirtyFields[column]]},`;
501
+ break;
502
+ case "belongsTo" :
503
+ var fore = `_${dirtyFields[column]}`;
504
+ argument = argument === null ? `[${model.__entity[dirtyFields[column]].foreignKey}] = '${model[fore]}',` : `${argument} [${model.__entity[dirtyFields[column]].foreignKey}] = '${model[fore]}',`;
505
+ break;
506
+ case "hasMany" :
507
+ argument = argument === null ? `[${dirtyFields[column]}] = '${model[dirtyFields[column]]}',` : `${argument} [${dirtyFields[column]}] = '${model[dirtyFields[column]]}',`;
508
+ break;
324
509
  default:
325
510
  argument = argument === null ? `[${dirtyFields[column]}] = '${model[dirtyFields[column]]}',` : `${argument} [${dirtyFields[column]}] = '${model[dirtyFields[column]]}',`;
326
511
  }
@@ -353,7 +538,7 @@ class SQLLiteEngine {
353
538
  if((fieldColumn !== undefined && fieldColumn !== null && fieldColumn !== "" ) && typeof(fieldColumn) !== "object"){
354
539
  switch(modelEntity[column].type){
355
540
  case "belongsTo" :
356
- column = modelEntity[column].relationshipTable === undefined ? column : modelEntity[column].relationshipTable;
541
+ column = modelEntity[column].foreignKey === undefined ? column : modelEntity[column].foreignKey;
357
542
  break;
358
543
  case "string" :
359
544
  fieldColumn = `'${$that._santizeSingleQuotes(fields[column])}'`;
@@ -367,6 +552,24 @@ class SQLLiteEngine {
367
552
  values = values === null ? `${fieldColumn},` : `${values} ${fieldColumn},`;
368
553
 
369
554
  }
555
+ else{
556
+ switch(modelEntity[column].type){
557
+ case "belongsTo" :
558
+ var fieldObject = tools.findTrackedObject(fields.__context.__trackedEntities, column );
559
+ if( Object.keys(fieldObject).length > 0){
560
+ var primaryKey = tools.getPrimaryKeyObject(fieldObject.__entity);
561
+ fieldColumn = fieldObject[primaryKey];
562
+ column = modelEntity[column].foreignKey;
563
+ columns = columns === null ? `'${column}',` : `${columns} '${column}',`;
564
+ values = values === null ? `${fieldColumn},` : `${values} ${fieldColumn},`;
565
+ }else{
566
+ console.log("Cannot find belings to relationship")
567
+ }
568
+
569
+ break;
570
+ }
571
+
572
+ }
370
573
  }
371
574
  }
372
575
  return {tableName: modelEntity.__name, columns: columns.replace(/,\s*$/, ""), values: values.replace(/,\s*$/, "")};
@@ -375,7 +578,13 @@ class SQLLiteEngine {
375
578
 
376
579
  // will add double single quotes to allow sting to be saved.
377
580
  _santizeSingleQuotes(string){
378
- return string.replace(/'/g, "''");
581
+ if (typeof string === 'string' || string instanceof String){
582
+ return string.replace(/'/g, "''");
583
+ }
584
+ else{
585
+ console.log("warning - Field being passed is not a string");
586
+ throw "warning - Field being passed is not a string";
587
+ }
379
588
  }
380
589
 
381
590
  // converts any object into SQL parameter select string
@@ -406,4 +615,4 @@ class SQLLiteEngine {
406
615
  }
407
616
  }
408
617
 
409
- module.exports = SQLLiteEngine;
618
+ module.exports = postgresEngine;