foxhound 1.0.36 → 1.0.39

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.
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "optOut": false,
3
- "lastUpdateCheck": 1648063932373
3
+ "lastUpdateCheck": 1653489092676
4
4
  }
package/Dockerfile CHANGED
@@ -17,6 +17,20 @@ RUN echo "...mapping library specific volumes..."
17
17
  VOLUME /home/coder/foxhound
18
18
  # VOLUME /home/coder/foxhound/node_modules
19
19
 
20
+ RUN echo "...installing vscode extensions..."
21
+ RUN code-server --install-extension hbenl.vscode-mocha-test-adapter \
22
+ code-server --install-extension hbenl.vscode-test-explorer \
23
+ code-server --install-extension hbenl.test-adapter-converter \
24
+ code-server --install-extension cweijan.vscode-mysql-client2 \
25
+ code-server --install-extension daylerees.rainglow \
26
+ code-server --install-extension oderwat.indent-rainbow \
27
+ code-server --install-extension evan-buss.font-switcher \
28
+ code-server --install-extension vscode-icons-team.vscode-icons \
29
+ code-server --install-extension bengreenier.vscode-node-readme \
30
+ code-server --install-extension bierner.color-info \
31
+ code-server --install-extension dbaeumer.vscode-eslint \
32
+ code-server --install-extension PKief.material-icon-theme
33
+
20
34
  SHELL ["/bin/bash", "-c"]
21
35
  USER coder
22
36
 
package/debug/Harness.js CHANGED
@@ -24,8 +24,10 @@ var _AnimalSchemaWithoutDeleted = (
24
24
  { Column: "UpdatingIDUser", Type:"UpdateIDUser" }
25
25
  ]);
26
26
 
27
+ /*
27
28
  var tmpQuery = libFoxHound.new(libFable)
28
- .setDialect('MeadowEndpoints')
29
+ //.setDialect('MeadowEndpoints')
30
+ .setDialect('MySQL')
29
31
  .setScope('Animal')
30
32
  .setDataElements(['Name', 'Age', 'Cost'])
31
33
  .setCap(100)
@@ -39,7 +41,18 @@ var tmpQuery = libFoxHound.new(libFable)
39
41
  tmpQuery.setLogLevel(3).addSort('Age');
40
42
  // Build the query
41
43
  tmpQuery.buildReadQuery();
42
- // This is the query generated by the MeadowEndpoints dialect
44
+ // This is the query generated by the set dialect
43
45
  libFable.log.trace('Select Query', tmpQuery.query);
46
+ */
47
+ var tmpQuery = libFoxHound.new(libFable)
48
+ //.setDialect('MeadowEndpoints')
49
+ .setDialect('MySQL')
50
+ .setScope('Animal')
51
+ .addFilter('IDAnimal', 10);
52
+ tmpQuery.query.schema = _AnimalSchema;
53
+ // Build the query
54
+ tmpQuery.buildUndeleteQuery();
55
+ // This is the query generated by the set dialect
56
+ libFable.log.trace('Query: ', tmpQuery.query);
44
57
 
45
58
  console.log(tmpQuery.query.body);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foxhound",
3
- "version": "1.0.36",
3
+ "version": "1.0.39",
4
4
  "description": "A Database Query generation library.",
5
5
  "main": "source/FoxHound.js",
6
6
  "scripts": {
@@ -794,6 +794,13 @@ var FoxHound = function()
794
794
  return this;
795
795
  };
796
796
 
797
+ var buildUndeleteQuery = function()
798
+ {
799
+ checkDialect();
800
+ _Parameters.query.body = _Dialect.Undelete(_Parameters);
801
+ return this;
802
+ };
803
+
797
804
  var buildCountQuery = function()
798
805
  {
799
806
  checkDialect();
@@ -836,6 +843,7 @@ var FoxHound = function()
836
843
  buildReadQuery: buildReadQuery,
837
844
  buildUpdateQuery: buildUpdateQuery,
838
845
  buildDeleteQuery: buildDeleteQuery,
846
+ buildUndeleteQuery: buildUndeleteQuery,
839
847
  buildCountQuery: buildCountQuery,
840
848
 
841
849
  clone: clone,
@@ -20,24 +20,24 @@ var libUnderscore = require('underscore');
20
20
  var FoxHoundDialectALASQL = function()
21
21
  {
22
22
  /**
23
- * Generate a table name from the scope.
24
- *
25
- * Because ALASQL is all in-memory, and can be run in two modes (anonymous
26
- * working on arrays or table-based) we are going to make this a programmable
27
- * value. Then we can share the code across both providers.
28
- *
29
- * @method: generateTableName
30
- * @param: {Object} pParameters SQL Query Parameters
31
- * @return: {String} Returns the table name clause
32
- */
23
+ * Generate a table name from the scope.
24
+ *
25
+ * Because ALASQL is all in-memory, and can be run in two modes (anonymous
26
+ * working on arrays or table-based) we are going to make this a programmable
27
+ * value. Then we can share the code across both providers.
28
+ *
29
+ * @method: generateTableName
30
+ * @param: {Object} pParameters SQL Query Parameters
31
+ * @return: {String} Returns the table name clause
32
+ */
33
33
  var generateTableName = function(pParameters)
34
34
  {
35
35
  return ' '+pParameters.scope;
36
36
  };
37
37
 
38
38
  /**
39
- * Escape columns, because ALASQL has more reserved KWs than most SQL dialects
40
- */
39
+ * Escape columns, because ALASQL has more reserved KWs than most SQL dialects
40
+ */
41
41
  var escapeColumn = (pColumn, pParameters) =>
42
42
  {
43
43
  if (pColumn.indexOf('.') < 0)
@@ -61,16 +61,16 @@ var FoxHoundDialectALASQL = function()
61
61
  };
62
62
 
63
63
  /**
64
- * Generate a field list from the array of dataElements
65
- *
66
- * Each entry in the dataElements is a simple string
67
- *
68
- * @method: generateFieldList
69
- * @param: {Object} pParameters SQL Query Parameters
70
- * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
71
- * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
72
- * due to missing schema.
73
- */
64
+ * Generate a field list from the array of dataElements
65
+ *
66
+ * Each entry in the dataElements is a simple string
67
+ *
68
+ * @method: generateFieldList
69
+ * @param: {Object} pParameters SQL Query Parameters
70
+ * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
71
+ * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
72
+ * due to missing schema.
73
+ */
74
74
  var generateFieldList = function(pParameters, pIsForCountClause)
75
75
  {
76
76
  var tmpDataElements = pParameters.dataElements;
@@ -109,9 +109,9 @@ var FoxHoundDialectALASQL = function()
109
109
  };
110
110
 
111
111
  /**
112
- * Generate a query from the array of where clauses
113
- *
114
- * Each clause is an object like:
112
+ * Generate a query from the array of where clauses
113
+ *
114
+ * Each clause is an object like:
115
115
  {
116
116
  Column:'Name',
117
117
  Operator:'EQ',
@@ -119,11 +119,11 @@ var FoxHoundDialectALASQL = function()
119
119
  Connector:'And',
120
120
  Parameter:'Name'
121
121
  }
122
- *
123
- * @method: generateWhere
124
- * @param: {Object} pParameters SQL Query Parameters
125
- * @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
126
- */
122
+ *
123
+ * @method: generateWhere
124
+ * @param: {Object} pParameters SQL Query Parameters
125
+ * @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
126
+ */
127
127
  var generateWhere = function(pParameters)
128
128
  {
129
129
  var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
@@ -229,15 +229,15 @@ var FoxHoundDialectALASQL = function()
229
229
  };
230
230
 
231
231
  /**
232
- * Generate an ORDER BY clause from the sort array
233
- *
234
- * Each entry in the sort is an object like:
235
- * {Column:'Color',Direction:'Descending'}
236
- *
237
- * @method: generateOrderBy
238
- * @param: {Object} pParameters SQL Query Parameters
239
- * @return: {String} Returns the field list clause
240
- */
232
+ * Generate an ORDER BY clause from the sort array
233
+ *
234
+ * Each entry in the sort is an object like:
235
+ * {Column:'Color',Direction:'Descending'}
236
+ *
237
+ * @method: generateOrderBy
238
+ * @param: {Object} pParameters SQL Query Parameters
239
+ * @return: {String} Returns the field list clause
240
+ */
241
241
  var generateOrderBy = function(pParameters)
242
242
  {
243
243
  var tmpOrderBy = pParameters.sort;
@@ -264,12 +264,12 @@ var FoxHoundDialectALASQL = function()
264
264
  };
265
265
 
266
266
  /**
267
- * Generate the limit clause
268
- *
269
- * @method: generateLimit
270
- * @param: {Object} pParameters SQL Query Parameters
271
- * @return: {String} Returns the table name clause
272
- */
267
+ * Generate the limit clause
268
+ *
269
+ * @method: generateLimit
270
+ * @param: {Object} pParameters SQL Query Parameters
271
+ * @return: {String} Returns the table name clause
272
+ */
273
273
  var generateLimit = function(pParameters)
274
274
  {
275
275
  if (!pParameters.cap)
@@ -291,12 +291,12 @@ var FoxHoundDialectALASQL = function()
291
291
  };
292
292
 
293
293
  /**
294
- * Generate the update SET clause
295
- *
296
- * @method: generateUpdateSetters
297
- * @param: {Object} pParameters SQL Query Parameters
298
- * @return: {String} Returns the table name clause
299
- */
294
+ * Generate the update SET clause
295
+ *
296
+ * @method: generateUpdateSetters
297
+ * @param: {Object} pParameters SQL Query Parameters
298
+ * @return: {String} Returns the table name clause
299
+ */
300
300
  var generateUpdateSetters = function(pParameters)
301
301
  {
302
302
  var tmpRecords = pParameters.query.records;
@@ -391,12 +391,12 @@ var FoxHoundDialectALASQL = function()
391
391
  };
392
392
 
393
393
  /**
394
- * Generate the update-delete SET clause
395
- *
396
- * @method: generateUpdateDeleteSetters
397
- * @param: {Object} pParameters SQL Query Parameters
398
- * @return: {String} Returns the table name clause
399
- */
394
+ * Generate the update-delete SET clause
395
+ *
396
+ * @method: generateUpdateDeleteSetters
397
+ * @param: {Object} pParameters SQL Query Parameters
398
+ * @return: {String} Returns the table name clause
399
+ */
400
400
  var generateUpdateDeleteSetters = function(pParameters)
401
401
  {
402
402
  if (pParameters.query.disableDeleteTracking)
@@ -468,12 +468,81 @@ var FoxHoundDialectALASQL = function()
468
468
  };
469
469
 
470
470
  /**
471
- * Generate the create SET clause
472
- *
473
- * @method: generateCreateSetList
474
- * @param: {Object} pParameters SQL Query Parameters
475
- * @return: {String} Returns the table name clause
476
- */
471
+ * Generate the update-delete SET clause
472
+ *
473
+ * @method: generateUpdateDeleteSetters
474
+ * @param: {Object} pParameters SQL Query Parameters
475
+ * @return: {String} Returns the table name clause
476
+ */
477
+ var generateUpdateUndeleteSetters = function(pParameters)
478
+ {
479
+ // Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
480
+ var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
481
+
482
+ var tmpCurrentColumn = 0;
483
+ var tmpHasDeletedField = false;
484
+ var tmpUpdate = '';
485
+ // No hash table yet, so, we will just linear search it for now.
486
+ // This uses the schema to decide if we want to treat a column differently on insert
487
+ var tmpSchemaEntry = {Type:'Default'};
488
+ for (var i = 0; i < tmpSchema.length; i++)
489
+ {
490
+ // There is a schema entry for it. Process it accordingly.
491
+ tmpSchemaEntry = tmpSchema[i];
492
+
493
+ var tmpUpdateSql = null;
494
+
495
+ switch (tmpSchemaEntry.Type)
496
+ {
497
+ case 'Deleted':
498
+ tmpUpdateSql = ' '+escapeColumn(tmpSchemaEntry.Column, pParameters)+' = 0';
499
+ tmpHasDeletedField = true; //this field is required in order for query to be built
500
+ break;
501
+ case 'UpdateDate':
502
+ // Delete operation is an Update, so we should stamp the update time
503
+ tmpUpdateSql = ' '+escapeColumn(tmpSchemaEntry.Column, pParameters)+' = NOW()';
504
+ break;
505
+ case 'UpdateIDUser':
506
+ // This is the user ID, which we hope is in the query.
507
+ // This is how to deal with a normal column
508
+ var tmpColumnParameter = tmpSchemaEntry.Column+'_'+tmpCurrentColumn;
509
+ tmpUpdateSql = ' '+escapeColumn(tmpSchemaEntry.Column, pParameters)+' = :'+tmpColumnParameter;
510
+ // Set the query parameter
511
+ pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
512
+ break;
513
+ default:
514
+ //DON'T allow update of other fields in this query
515
+ continue;
516
+ }
517
+
518
+ if (tmpCurrentColumn > 0)
519
+ {
520
+ tmpUpdate += ',';
521
+ }
522
+
523
+ tmpUpdate += tmpUpdateSql;
524
+
525
+ // We use a number to make sure parameters are unique.
526
+ tmpCurrentColumn++;
527
+ }
528
+
529
+ // We need to tell the query not to generate improperly if there are no values set.
530
+ if (!tmpHasDeletedField ||
531
+ tmpUpdate === '')
532
+ {
533
+ return false;
534
+ }
535
+
536
+ return tmpUpdate;
537
+ };
538
+
539
+ /**
540
+ * Generate the create SET clause
541
+ *
542
+ * @method: generateCreateSetList
543
+ * @param: {Object} pParameters SQL Query Parameters
544
+ * @return: {String} Returns the table name clause
545
+ */
477
546
  var generateCreateSetValues = function(pParameters)
478
547
  {
479
548
  var tmpRecords = pParameters.query.records;
@@ -613,12 +682,12 @@ var FoxHoundDialectALASQL = function()
613
682
  };
614
683
 
615
684
  /**
616
- * Generate the create SET clause
617
- *
618
- * @method: generateCreateSetList
619
- * @param: {Object} pParameters SQL Query Parameters
620
- * @return: {String} Returns the table name clause
621
- */
685
+ * Generate the create SET clause
686
+ *
687
+ * @method: generateCreateSetList
688
+ * @param: {Object} pParameters SQL Query Parameters
689
+ * @return: {String} Returns the table name clause
690
+ */
622
691
  var generateCreateSetList = function(pParameters)
623
692
  {
624
693
  // The records were already validated by generateCreateSetValues
@@ -755,6 +824,26 @@ var FoxHoundDialectALASQL = function()
755
824
  }
756
825
  };
757
826
 
827
+ var Undelete = function(pParameters)
828
+ {
829
+ var tmpTableName = generateTableName(pParameters);
830
+ let tmpDeleteTrackingState = pParameters.query.disableDeleteTracking;
831
+ pParameters.query.disableDeleteTracking = false;
832
+ var tmpWhere = generateWhere(pParameters);
833
+ var tmpUpdateUndeleteSetters = generateUpdateUndeleteSetters(pParameters);
834
+ pParameters.query.disableDeleteTracking = tmpDeleteTrackingState;
835
+
836
+ if (tmpUpdateUndeleteSetters)
837
+ {
838
+ //If it has a deleted bit, update it instead of actually deleting the record
839
+ return 'UPDATE'+tmpTableName+' SET'+tmpUpdateUndeleteSetters+tmpWhere+';';
840
+ }
841
+ else
842
+ {
843
+ return 'SELECT NULL;';
844
+ }
845
+ };
846
+
758
847
  var Count = function(pParameters)
759
848
  {
760
849
  var tmpTableName = generateTableName(pParameters);
@@ -790,15 +879,16 @@ var FoxHoundDialectALASQL = function()
790
879
  Read: Read,
791
880
  Update: Update,
792
881
  Delete: Delete,
882
+ Undelete: Undelete,
793
883
  Count: Count
794
884
  });
795
885
 
796
886
  /**
797
- * Dialect Name
798
- *
799
- * @property name
800
- * @type string
801
- */
887
+ * Dialect Name
888
+ *
889
+ * @property name
890
+ * @type string
891
+ */
802
892
  Object.defineProperty(tmpDialect, 'name',
803
893
  {
804
894
  get: function() { return 'ALASQL'; },
@@ -54,6 +54,13 @@ var FoxHoundDialectEnglish = function()
54
54
  return 'I am deleting your '+tmpScope+'.';
55
55
  };
56
56
 
57
+ var Undelete = function(pParameters)
58
+ {
59
+ var tmpScope = pParameters.scope;
60
+
61
+ return 'I am undeleting your '+tmpScope+'.';
62
+ };
63
+
57
64
  var Count = function(pParameters)
58
65
  {
59
66
  var tmpScope = pParameters.scope;
@@ -67,6 +74,7 @@ var FoxHoundDialectEnglish = function()
67
74
  Read: Read,
68
75
  Update: Update,
69
76
  Delete: Delete,
77
+ Undelete: Undelete,
70
78
  Count: Count
71
79
  });
72
80
 
@@ -404,7 +404,6 @@ var FoxHoundDialectMeadowEndpoints = function()
404
404
  }
405
405
 
406
406
  return tmpURL;
407
- ///'SELECT'+tmpFieldList+' FROM'+tmpTableName+tmpJoin+tmpWhere+tmpOrderBy+tmpLimit+';';
408
407
  };
409
408
 
410
409
  var Update = function(pParameters)
@@ -449,7 +448,7 @@ var FoxHoundDialectMeadowEndpoints = function()
449
448
 
450
449
  if (tmpWhere)
451
450
  {
452
- return `${tmpCountQuery}s/Count/FilteredTo/${tmpWhere}`;
451
+ return `${tmpTableName}s/Count/FilteredTo/${tmpWhere}`;
453
452
  }
454
453
 
455
454
  return tmpCountQuery;
@@ -23,12 +23,12 @@ var FoxHoundDialectMySQL = function()
23
23
  const SQL_NOW = "NOW(3)";
24
24
 
25
25
  /**
26
- * Generate a table name from the scope
27
- *
28
- * @method: generateTableName
29
- * @param: {Object} pParameters SQL Query Parameters
30
- * @return: {String} Returns the table name clause
31
- */
26
+ * Generate a table name from the scope
27
+ *
28
+ * @method: generateTableName
29
+ * @param: {Object} pParameters SQL Query Parameters
30
+ * @return: {String} Returns the table name clause
31
+ */
32
32
  var generateTableName = function(pParameters)
33
33
  {
34
34
  if (pParameters.scope && pParameters.scope.indexOf('`') >= 0)
@@ -38,16 +38,16 @@ var FoxHoundDialectMySQL = function()
38
38
  };
39
39
 
40
40
  /**
41
- * Generate a field list from the array of dataElements
42
- *
43
- * Each entry in the dataElements is a simple string
44
- *
45
- * @method: generateFieldList
46
- * @param: {Object} pParameters SQL Query Parameters
47
- * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
48
- * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
49
- * due to missing schema.
50
- */
41
+ * Generate a field list from the array of dataElements
42
+ *
43
+ * Each entry in the dataElements is a simple string
44
+ *
45
+ * @method: generateFieldList
46
+ * @param: {Object} pParameters SQL Query Parameters
47
+ * @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
48
+ * @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
49
+ * due to missing schema.
50
+ */
51
51
  var generateFieldList = function(pParameters, pIsForCountClause)
52
52
  {
53
53
  var tmpDataElements = pParameters.dataElements;
@@ -106,8 +106,8 @@ var FoxHoundDialectMySQL = function()
106
106
  };
107
107
 
108
108
  /**
109
- * Ensure a field name is properly escaped.
110
- */
109
+ * Ensure a field name is properly escaped.
110
+ */
111
111
  var generateSafeFieldName = function(pFieldName)
112
112
  {
113
113
  let pFieldNames = pFieldName.split('.');
@@ -122,9 +122,9 @@ var FoxHoundDialectMySQL = function()
122
122
  }
123
123
 
124
124
  /**
125
- * Generate a query from the array of where clauses
126
- *
127
- * Each clause is an object like:
125
+ * Generate a query from the array of where clauses
126
+ *
127
+ * Each clause is an object like:
128
128
  {
129
129
  Column:'Name',
130
130
  Operator:'EQ',
@@ -132,11 +132,11 @@ var FoxHoundDialectMySQL = function()
132
132
  Connector:'And',
133
133
  Parameter:'Name'
134
134
  }
135
- *
136
- * @method: generateWhere
137
- * @param: {Object} pParameters SQL Query Parameters
138
- * @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
139
- */
135
+ *
136
+ * @method: generateWhere
137
+ * @param: {Object} pParameters SQL Query Parameters
138
+ * @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
139
+ */
140
140
  var generateWhere = function(pParameters)
141
141
  {
142
142
  var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
@@ -247,15 +247,15 @@ var FoxHoundDialectMySQL = function()
247
247
  };
248
248
 
249
249
  /**
250
- * Generate an ORDER BY clause from the sort array
251
- *
252
- * Each entry in the sort is an object like:
253
- * {Column:'Color',Direction:'Descending'}
254
- *
255
- * @method: generateOrderBy
256
- * @param: {Object} pParameters SQL Query Parameters
257
- * @return: {String} Returns the field list clause
258
- */
250
+ * Generate an ORDER BY clause from the sort array
251
+ *
252
+ * Each entry in the sort is an object like:
253
+ * {Column:'Color',Direction:'Descending'}
254
+ *
255
+ * @method: generateOrderBy
256
+ * @param: {Object} pParameters SQL Query Parameters
257
+ * @return: {String} Returns the field list clause
258
+ */
259
259
  var generateOrderBy = function(pParameters)
260
260
  {
261
261
  var tmpOrderBy = pParameters.sort;
@@ -282,12 +282,12 @@ var FoxHoundDialectMySQL = function()
282
282
  };
283
283
 
284
284
  /**
285
- * Generate the limit clause
286
- *
287
- * @method: generateLimit
288
- * @param: {Object} pParameters SQL Query Parameters
289
- * @return: {String} Returns the table name clause
290
- */
285
+ * Generate the limit clause
286
+ *
287
+ * @method: generateLimit
288
+ * @param: {Object} pParameters SQL Query Parameters
289
+ * @return: {String} Returns the table name clause
290
+ */
291
291
  var generateLimit = function(pParameters)
292
292
  {
293
293
  if (!pParameters.cap)
@@ -308,12 +308,12 @@ var FoxHoundDialectMySQL = function()
308
308
  };
309
309
 
310
310
  /**
311
- * Generate the join clause
312
- *
313
- * @method: generateJoins
314
- * @param: {Object} pParameters SQL Query Parameters
315
- * @return: {String} Returns the join clause
316
- */
311
+ * Generate the join clause
312
+ *
313
+ * @method: generateJoins
314
+ * @param: {Object} pParameters SQL Query Parameters
315
+ * @return: {String} Returns the join clause
316
+ */
317
317
  var generateJoins = function(pParameters)
318
318
  {
319
319
  var tmpJoins = pParameters.join;
@@ -337,12 +337,12 @@ var FoxHoundDialectMySQL = function()
337
337
  }
338
338
 
339
339
  /**
340
- * Generate the update SET clause
341
- *
342
- * @method: generateUpdateSetters
343
- * @param: {Object} pParameters SQL Query Parameters
344
- * @return: {String} Returns the table name clause
345
- */
340
+ * Generate the update SET clause
341
+ *
342
+ * @method: generateUpdateSetters
343
+ * @param: {Object} pParameters SQL Query Parameters
344
+ * @return: {String} Returns the table name clause
345
+ */
346
346
  var generateUpdateSetters = function(pParameters)
347
347
  {
348
348
  var tmpRecords = pParameters.query.records;
@@ -437,12 +437,12 @@ var FoxHoundDialectMySQL = function()
437
437
  };
438
438
 
439
439
  /**
440
- * Generate the update-delete SET clause
441
- *
442
- * @method: generateUpdateDeleteSetters
443
- * @param: {Object} pParameters SQL Query Parameters
444
- * @return: {String} Returns the table name clause
445
- */
440
+ * Generate the update-delete SET clause
441
+ *
442
+ * @method: generateUpdateDeleteSetters
443
+ * @param: {Object} pParameters SQL Query Parameters
444
+ * @return: {String} Returns the table name clause
445
+ */
446
446
  var generateUpdateDeleteSetters = function(pParameters)
447
447
  {
448
448
  if (pParameters.query.disableDeleteTracking)
@@ -452,7 +452,7 @@ var FoxHoundDialectMySQL = function()
452
452
  }
453
453
  // Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
454
454
  var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
455
-
455
+
456
456
  var tmpCurrentColumn = 0;
457
457
  var tmpHasDeletedField = false;
458
458
  var tmpUpdate = '';
@@ -463,9 +463,9 @@ var FoxHoundDialectMySQL = function()
463
463
  {
464
464
  // There is a schema entry for it. Process it accordingly.
465
465
  tmpSchemaEntry = tmpSchema[i];
466
-
466
+
467
467
  var tmpUpdateSql = null;
468
-
468
+
469
469
  switch (tmpSchemaEntry.Type)
470
470
  {
471
471
  case 'Deleted':
@@ -491,6 +491,72 @@ var FoxHoundDialectMySQL = function()
491
491
  //DON'T allow update of other fields in this query
492
492
  continue;
493
493
  }
494
+
495
+ if (tmpCurrentColumn > 0)
496
+ {
497
+ tmpUpdate += ',';
498
+ }
499
+
500
+ tmpUpdate += tmpUpdateSql;
501
+
502
+ // We use a number to make sure parameters are unique.
503
+ tmpCurrentColumn++;
504
+ }
505
+
506
+ // We need to tell the query not to generate improperly if there are no values set.
507
+ if (!tmpHasDeletedField ||
508
+ tmpUpdate === '')
509
+ {
510
+ return false;
511
+ }
512
+
513
+ return tmpUpdate;
514
+ };
515
+
516
+ /**
517
+ * Generate the update-undelete SET clause
518
+ *
519
+ * @method: generateUpdateUndeleteSetters
520
+ * @param: {Object} pParameters SQL Query Parameters
521
+ * @return: {String} Returns the table name clause
522
+ */
523
+ var generateUpdateUndeleteSetters = function(pParameters)
524
+ {
525
+ // Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
526
+ var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
527
+
528
+ var tmpCurrentColumn = 0;
529
+ var tmpHasDeletedField = false;
530
+ var tmpUpdate = '';
531
+ // No hash table yet, so, we will just linear search it for now.
532
+ // This uses the schema to decide if we want to treat a column differently on insert
533
+ var tmpSchemaEntry = {Type:'Default'};
534
+ for (var i = 0; i < tmpSchema.length; i++)
535
+ {
536
+ // There is a schema entry for it. Process it accordingly.
537
+ tmpSchemaEntry = tmpSchema[i];
538
+
539
+ var tmpUpdateSql = null;
540
+
541
+ switch (tmpSchemaEntry.Type)
542
+ {
543
+ case 'Deleted':
544
+ tmpUpdateSql = ' '+tmpSchemaEntry.Column+' = 0';
545
+ tmpHasDeletedField = true; //this field is required in order for query to be built
546
+ break;
547
+ case 'UpdateDate':
548
+ // The undelete operation is an Update, so we should stamp the update time
549
+ tmpUpdateSql = ' '+tmpSchemaEntry.Column+' = ' + SQL_NOW;
550
+ break;
551
+ case 'UpdateIDUser':
552
+ var tmpColumnParameter = tmpSchemaEntry.Column+'_'+tmpCurrentColumn;
553
+ tmpUpdateSql = ' '+tmpSchemaEntry.Column+' = :'+tmpColumnParameter;
554
+ pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
555
+ break;
556
+ default:
557
+ //DON'T allow update of other fields in this query
558
+ continue;
559
+ }
494
560
 
495
561
  if (tmpCurrentColumn > 0)
496
562
  {
@@ -514,12 +580,12 @@ var FoxHoundDialectMySQL = function()
514
580
  };
515
581
 
516
582
  /**
517
- * Generate the create SET clause
518
- *
519
- * @method: generateCreateSetList
520
- * @param: {Object} pParameters SQL Query Parameters
521
- * @return: {String} Returns the table name clause
522
- */
583
+ * Generate the create SET clause
584
+ *
585
+ * @method: generateCreateSetList
586
+ * @param: {Object} pParameters SQL Query Parameters
587
+ * @return: {String} Returns the table name clause
588
+ */
523
589
  var generateCreateSetValues = function(pParameters)
524
590
  {
525
591
  var tmpRecords = pParameters.query.records;
@@ -659,12 +725,12 @@ var FoxHoundDialectMySQL = function()
659
725
  };
660
726
 
661
727
  /**
662
- * Generate the create SET clause
663
- *
664
- * @method: generateCreateSetList
665
- * @param: {Object} pParameters SQL Query Parameters
666
- * @return: {String} Returns the table name clause
667
- */
728
+ * Generate the create SET clause
729
+ *
730
+ * @method: generateCreateSetList
731
+ * @param: {Object} pParameters SQL Query Parameters
732
+ * @return: {String} Returns the table name clause
733
+ */
668
734
  var generateCreateSetList = function(pParameters)
669
735
  {
670
736
  // The records were already validated by generateCreateSetValues
@@ -802,6 +868,29 @@ var FoxHoundDialectMySQL = function()
802
868
  }
803
869
  };
804
870
 
871
+ var Undelete = function(pParameters)
872
+ {
873
+ var tmpTableName = generateTableName(pParameters);
874
+ // TODO: Fix these
875
+ let tmpDeleteTrackingState = pParameters.query.disableDeleteTracking;
876
+ pParameters.query.disableDeleteTracking = false;
877
+ var tmpWhere = generateWhere(pParameters);
878
+ var tmpUpdateUndeleteSetters = generateUpdateUndeleteSetters(pParameters);
879
+ pParameters.query.disableDeleteTracking = tmpDeleteTrackingState;
880
+
881
+ if (tmpUpdateUndeleteSetters)
882
+ {
883
+ //If the table has a deleted bit, go forward with the update to change things.
884
+ return 'UPDATE'+tmpTableName+' SET'+tmpUpdateUndeleteSetters+tmpWhere+';';
885
+ }
886
+ else
887
+ {
888
+ // This is a no-op because the record can't be undeleted.
889
+ // TODO: Should it throw instead?
890
+ return 'SELECT NULL;';
891
+ }
892
+ };
893
+
805
894
  var Count = function(pParameters)
806
895
  {
807
896
  var tmpFieldList = pParameters.distinct ? generateFieldList(pParameters, true) : '*';
@@ -838,15 +927,16 @@ var FoxHoundDialectMySQL = function()
838
927
  Read: Read,
839
928
  Update: Update,
840
929
  Delete: Delete,
930
+ Undelete: Undelete,
841
931
  Count: Count
842
932
  });
843
933
 
844
934
  /**
845
- * Dialect Name
846
- *
847
- * @property name
848
- * @type string
849
- */
935
+ * Dialect Name
936
+ *
937
+ * @property name
938
+ * @type string
939
+ */
850
940
  Object.defineProperty(tmpDialect, 'name',
851
941
  {
852
942
  get: function() { return 'MySQL'; },
@@ -659,6 +659,43 @@ suite
659
659
  }
660
660
  );
661
661
  test
662
+ (
663
+ 'Undelete Query with Deleted Bit',
664
+ function()
665
+ {
666
+ var tmpQuery = libFoxHound.new(libFable).setDialect('ALASQL')
667
+ .setScope('Animal')
668
+ .addFilter('IDAnimal', 10);
669
+
670
+ //Use a schema that already defines a deleted bit
671
+ tmpQuery.query.schema = _AnimalSchema;
672
+
673
+ // Build the query
674
+ tmpQuery.buildUndeleteQuery();
675
+ // This is the query generated by the ALASQL dialect
676
+ libFable.log.trace('Undelete Query', tmpQuery.query);
677
+ Expect(tmpQuery.query.body)
678
+ .to.equal('UPDATE Animal SET `UpdateDate` = NOW(), `UpdatingIDUser` = :UpdatingIDUser_1, `Deleted` = 0 WHERE `IDAnimal` = :IDAnimal_w0 AND `Deleted` = :Deleted_w1;');
679
+ }
680
+ );
681
+ test
682
+ (
683
+ 'Undelete Query without Deleted Bit',
684
+ function()
685
+ {
686
+ var tmpQuery = libFoxHound.new(libFable).setDialect('ALASQL')
687
+ .setScope('Animal')
688
+ .addFilter('IDAnimal', 10);
689
+
690
+ // Build the query
691
+ tmpQuery.buildUndeleteQuery();
692
+ // This is the query generated by the ALASQL dialect
693
+ libFable.log.trace('Undelete Query', tmpQuery.query);
694
+ Expect(tmpQuery.query.body)
695
+ .to.equal('SELECT NULL;');
696
+ }
697
+ );
698
+ test
662
699
  (
663
700
  'Update Query -- without Deleted',
664
701
  function()
@@ -205,6 +205,20 @@ suite
205
205
  }
206
206
  );
207
207
  test
208
+ (
209
+ 'Undelete Query',
210
+ function()
211
+ {
212
+ var tmpQuery = libFoxHound.new(libFable).setDialect('English').setScope('Animal');
213
+
214
+ // Build the query
215
+ tmpQuery.buildUndeleteQuery();
216
+ // This is the query generated by the English dialect
217
+ Expect(tmpQuery.query.body)
218
+ .to.equal('I am undeleting your Animal.');
219
+ }
220
+ );
221
+ test
208
222
  (
209
223
  'Count Query',
210
224
  function()
@@ -772,6 +772,43 @@ suite
772
772
  .to.equal('DELETE FROM `Animal` WHERE IDAnimal = :IDAnimal_w0;');
773
773
  }
774
774
  );
775
+ test
776
+ (
777
+ 'Undelete Query with Deleted Bit',
778
+ function()
779
+ {
780
+ var tmpQuery = libFoxHound.new(libFable).setDialect('MySQL')
781
+ .setScope('Animal')
782
+ .addFilter('IDAnimal', 10);
783
+
784
+ //Use a schema that already defines a deleted bit
785
+ tmpQuery.query.schema = _AnimalSchema;
786
+
787
+ // Build the query
788
+ tmpQuery.buildUndeleteQuery();
789
+ // This is the query generated by the MySQL dialect
790
+ libFable.log.trace('Undelete Query', tmpQuery.query);
791
+ Expect(tmpQuery.query.body)
792
+ .to.equal('UPDATE `Animal` SET UpdateDate = NOW(3), UpdatingIDUser = :UpdatingIDUser_1, Deleted = 0 WHERE IDAnimal = :IDAnimal_w0 AND `Animal`.Deleted = :Deleted_w1;');
793
+ }
794
+ );
795
+ test
796
+ (
797
+ 'Undelete Query without Deleted Bit',
798
+ function()
799
+ {
800
+ var tmpQuery = libFoxHound.new(libFable).setDialect('MySQL')
801
+ .setScope('Animal')
802
+ .addFilter('IDAnimal', 10);
803
+
804
+ // Build the query
805
+ tmpQuery.buildUndeleteQuery();
806
+ // This is the query generated by the MySQL dialect
807
+ libFable.log.trace('Undelete Query', tmpQuery.query);
808
+ Expect(tmpQuery.query.body)
809
+ .to.equal('SELECT NULL;');
810
+ }
811
+ );
775
812
  }
776
813
  );
777
814