foxhound 2.0.8 → 2.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foxhound",
3
- "version": "2.0.8",
3
+ "version": "2.0.9",
4
4
  "description": "A Database Query generation library.",
5
5
  "main": "source/FoxHound.js",
6
6
  "scripts": {
@@ -852,6 +852,19 @@ var FoxHound = function()
852
852
  enumerable: true
853
853
  });
854
854
 
855
+ /**
856
+ * Query
857
+ *
858
+ * @property query
859
+ * @type Object
860
+ */
861
+ Object.defineProperty(tmpNewFoxHoundObject, 'indexHints',
862
+ {
863
+ get: function() { return _Parameters.indexHints; },
864
+ set: function(pHints) { _Parameters.indexHints = pHints; },
865
+ enumerable: true,
866
+ });
867
+
855
868
  /**
856
869
  * Result
857
870
  *
@@ -78,7 +78,12 @@ var FoxHoundQueryParameters = (
78
78
  parameters: {}
79
79
  }
80
80
  */
81
-
81
+
82
+ indexHints: false,
83
+ /*
84
+ ['IndexName1', 'IndexName2'] // A list of index names to hint to the underlying provider, if supported
85
+ */
86
+
82
87
  // Who is making the query
83
88
  userID: 0,
84
89
 
@@ -93,4 +98,4 @@ var FoxHoundQueryParameters = (
93
98
  */
94
99
  });
95
100
 
96
- module.exports = FoxHoundQueryParameters;
101
+ module.exports = FoxHoundQueryParameters;
@@ -355,7 +355,7 @@ var FoxHoundDialectMSSQL = function(pFable)
355
355
  *
356
356
  * @method: generateLimit
357
357
  * @param: {Object} pParameters SQL Query Parameters
358
- * @return: {String} Returns the table name clause
358
+ * @return: {String} Returns the table limit clause
359
359
  */
360
360
  var generateLimit = function(pParameters)
361
361
  {
@@ -380,6 +380,23 @@ var FoxHoundDialectMSSQL = function(pFable)
380
380
  return tmpLimit;
381
381
  };
382
382
 
383
+ /**
384
+ * Generate the an index hinting clause
385
+ *
386
+ * @method: generateIndexHints
387
+ * @param: {Object} pParameters SQL Query Parameters
388
+ * @return: {String} Returns the table index hint clause
389
+ */
390
+ var generateIndexHints = function(pParameters)
391
+ {
392
+ if (!Array.isArray(pParameters.indexHints) || pParameters.indexHints.length < 1)
393
+ {
394
+ return '';
395
+ }
396
+
397
+ return ` WITH(INDEX(${pParameters.indexHints.join(',')}))`
398
+ };
399
+
383
400
  /**
384
401
  * Generate the join clause
385
402
  *
@@ -909,6 +926,7 @@ var FoxHoundDialectMSSQL = function(pFable)
909
926
  var tmpJoin = generateJoins(pParameters);
910
927
  var tmpOrderBy = generateOrderBy(pParameters);
911
928
  var tmpLimit = generateLimit(pParameters);
929
+ var tmpIndexHints = generateIndexHints(pParameters);
912
930
  const tmpOptDistinct = pParameters.distinct ? ' DISTINCT' : '';
913
931
 
914
932
  if (pParameters.queryOverride)
@@ -916,7 +934,7 @@ var FoxHoundDialectMSSQL = function(pFable)
916
934
  try
917
935
  {
918
936
  var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
919
- return tmpQueryTemplate({FieldList:tmpFieldList, TableName:tmpTableName, Where:tmpWhere, Join:tmpJoin, OrderBy:tmpOrderBy, Limit:tmpLimit, Distinct: tmpOptDistinct, _Params: pParameters});
937
+ return tmpQueryTemplate({FieldList:tmpFieldList, TableName:tmpTableName, Where:tmpWhere, Join:tmpJoin, OrderBy:tmpOrderBy, Limit:tmpLimit, IndexHints: tmpIndexHints, Distinct: tmpOptDistinct, _Params: pParameters});
920
938
  }
921
939
  catch (pError)
922
940
  {
@@ -926,7 +944,7 @@ var FoxHoundDialectMSSQL = function(pFable)
926
944
  }
927
945
  }
928
946
 
929
- return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpJoin}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
947
+ return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpIndexHints}${tmpJoin}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
930
948
  };
931
949
 
932
950
  var Update = function(pParameters)
@@ -989,6 +1007,7 @@ var FoxHoundDialectMSSQL = function(pFable)
989
1007
  var tmpTableName = generateTableName(pParameters);
990
1008
  var tmpJoin = generateJoins(pParameters);
991
1009
  var tmpWhere = generateWhere(pParameters);
1010
+ var tmpIndexHints = generateIndexHints(pParameters);
992
1011
  // here, we ignore the distinct keyword if no fields have been specified and
993
1012
  if (pParameters.distinct && tmpFieldList.length < 1)
994
1013
  {
@@ -1001,7 +1020,7 @@ var FoxHoundDialectMSSQL = function(pFable)
1001
1020
  try
1002
1021
  {
1003
1022
  var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
1004
- return tmpQueryTemplate({FieldList:[], TableName:tmpTableName, Where:tmpWhere, OrderBy:'', Limit:'', Distinct: tmpOptDistinct, _Params: pParameters});
1023
+ return tmpQueryTemplate({FieldList:[], TableName:tmpTableName, Where:tmpWhere, OrderBy:'', IndexHints: tmpIndexHints, Limit:'', Distinct: tmpOptDistinct, _Params: pParameters});
1005
1024
  }
1006
1025
  catch (pError)
1007
1026
  {
@@ -1011,7 +1030,7 @@ var FoxHoundDialectMSSQL = function(pFable)
1011
1030
  }
1012
1031
  }
1013
1032
 
1014
- return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS Row_Count FROM${tmpTableName}${tmpJoin}${tmpWhere};`;
1033
+ return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS Row_Count FROM${tmpTableName}${tmpIndexHints}${tmpJoin}${tmpWhere};`;
1015
1034
  };
1016
1035
 
1017
1036
  var tmpDialect = ({
@@ -296,7 +296,7 @@ var FoxHoundDialectMySQL = function(pFable)
296
296
  *
297
297
  * @method: generateLimit
298
298
  * @param: {Object} pParameters SQL Query Parameters
299
- * @return: {String} Returns the table name clause
299
+ * @return: {String} Returns the table limit clause
300
300
  */
301
301
  var generateLimit = function(pParameters)
302
302
  {
@@ -317,6 +317,23 @@ var FoxHoundDialectMySQL = function(pFable)
317
317
  return tmpLimit;
318
318
  };
319
319
 
320
+ /**
321
+ * Generate the use index clause
322
+ *
323
+ * @method: generateIndexHints
324
+ * @param: {Object} pParameters SQL Query Parameters
325
+ * @return: {String} Returns the table limit clause
326
+ */
327
+ var generateIndexHints = function(pParameters)
328
+ {
329
+ if (!Array.isArray(pParameters.indexHints) || pParameters.indexHints.length < 1)
330
+ {
331
+ return '';
332
+ }
333
+
334
+ return ` USE INDEX (${pParameters.indexHints.join(',')})`;
335
+ };
336
+
320
337
  /**
321
338
  * Generate the join clause
322
339
  *
@@ -827,6 +844,7 @@ var FoxHoundDialectMySQL = function(pFable)
827
844
  var tmpJoin = generateJoins(pParameters);
828
845
  var tmpOrderBy = generateOrderBy(pParameters);
829
846
  var tmpLimit = generateLimit(pParameters);
847
+ var tmpIndexHints = generateIndexHints(pParameters);
830
848
  const tmpOptDistinct = pParameters.distinct ? ' DISTINCT' : '';
831
849
 
832
850
  if (pParameters.queryOverride)
@@ -834,7 +852,7 @@ var FoxHoundDialectMySQL = function(pFable)
834
852
  try
835
853
  {
836
854
  var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
837
- return tmpQueryTemplate({FieldList:tmpFieldList, TableName:tmpTableName, Where:tmpWhere, Join:tmpJoin, OrderBy:tmpOrderBy, Limit:tmpLimit, Distinct: tmpOptDistinct, _Params: pParameters});
855
+ return tmpQueryTemplate({FieldList:tmpFieldList, TableName:tmpTableName, Where:tmpWhere, Join:tmpJoin, OrderBy:tmpOrderBy, Limit:tmpLimit, IndexHints: tmpIndexHints, Distinct: tmpOptDistinct, _Params: pParameters});
838
856
  }
839
857
  catch (pError)
840
858
  {
@@ -844,7 +862,7 @@ var FoxHoundDialectMySQL = function(pFable)
844
862
  }
845
863
  }
846
864
 
847
- return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpJoin}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
865
+ return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpIndexHints}${tmpJoin}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
848
866
  };
849
867
 
850
868
  var Update = function(pParameters)
@@ -907,6 +925,7 @@ var FoxHoundDialectMySQL = function(pFable)
907
925
  var tmpTableName = generateTableName(pParameters);
908
926
  var tmpJoin = generateJoins(pParameters);
909
927
  var tmpWhere = generateWhere(pParameters);
928
+ var tmpIndexHints = generateIndexHints(pParameters);
910
929
  // here, we ignore the distinct keyword if no fields have been specified and
911
930
  if (pParameters.distinct && tmpFieldList.length < 1)
912
931
  {
@@ -919,7 +938,7 @@ var FoxHoundDialectMySQL = function(pFable)
919
938
  try
920
939
  {
921
940
  var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
922
- return tmpQueryTemplate({FieldList:[], TableName:tmpTableName, Where:tmpWhere, OrderBy:'', Limit:'', Distinct: tmpOptDistinct, _Params: pParameters});
941
+ return tmpQueryTemplate({FieldList:[], TableName:tmpTableName, Where:tmpWhere, OrderBy:'', Limit:'', IndexHints: tmpIndexHints, Distinct: tmpOptDistinct, _Params: pParameters});
923
942
  }
924
943
  catch (pError)
925
944
  {
@@ -929,7 +948,7 @@ var FoxHoundDialectMySQL = function(pFable)
929
948
  }
930
949
  }
931
950
 
932
- return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS RowCount FROM${tmpTableName}${tmpJoin}${tmpWhere};`;
951
+ return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS RowCount FROM${tmpTableName}${tmpIndexHints}${tmpJoin}${tmpWhere};`;
933
952
  };
934
953
 
935
954
  var tmpDialect = ({
@@ -124,6 +124,22 @@ suite
124
124
  }
125
125
  );
126
126
  test
127
+ (
128
+ 'Read Query with Index Hints',
129
+ function()
130
+ {
131
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MySQL').setScope('Animal');
132
+ tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
133
+ tmpQuery.indexHints = ['AnimalIndex_1', 'AnimalIndex_2'];
134
+ // Build the query
135
+ tmpQuery.buildReadQuery();
136
+ // This is the query generated by the MySQL dialect
137
+ _Fable.log.trace('Simple Select Query', tmpQuery.query);
138
+ Expect(tmpQuery.query.body)
139
+ .to.equal('SELECT `Animal`.* FROM `Animal` USE INDEX (AnimalIndex_1,AnimalIndex_2) ORDER BY Cost DESC;');
140
+ }
141
+ );
142
+ test
127
143
  (
128
144
  'Read Query with Distinct',
129
145
  function()
@@ -244,14 +260,15 @@ suite
244
260
  .setDataElements(['Name', 'Age', 'Cost'])
245
261
  .setSort([{Column:'Age',Direction:'Ascending'},{Column:'Cost',Direction:'Descending'}])
246
262
  .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
263
+ tmpQuery.indexHints = ['AnimalIndex_1', 'AnimalIndex_2'];
247
264
  tmpQuery.parameters.CustomFields = 'Name, Age * 5, Cost';
248
- tmpQuery.parameters.queryOverride = 'SELECT <%= _Params.CustomFields %> FROM <%= TableName %> <%= Where %> <%= Limit %>;';
265
+ tmpQuery.parameters.queryOverride = 'SELECT <%= _Params.CustomFields %> FROM <%= TableName %><%= IndexHints %> <%= Where %> <%= Limit %>;';
249
266
  // Build the query
250
267
  tmpQuery.buildReadQuery();
251
268
  // This is the query generated by the MySQL dialect
252
269
  _Fable.log.trace('Custom Select Query', tmpQuery.query);
253
270
  Expect(tmpQuery.query.body)
254
- .to.equal('SELECT Name, Age * 5, Cost FROM `Animal` WHERE Age = :Age_w0 LIMIT 0, 10;');
271
+ .to.equal('SELECT Name, Age * 5, Cost FROM `Animal` USE INDEX (AnimalIndex_1,AnimalIndex_2) WHERE Age = :Age_w0 LIMIT 0, 10;');
255
272
  }
256
273
  );
257
274
  test
@@ -303,13 +320,14 @@ suite
303
320
  .setDialect('MySQL')
304
321
  .setScope('Animal')
305
322
  .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
306
- tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %> <%= Where %>;';
323
+ tmpQuery.indexHints = ['AnimalIndex_1', 'AnimalIndex_2'];
324
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %><%= IndexHints %> <%= Where %>;';
307
325
  // Build the query
308
326
  tmpQuery.buildCountQuery();
309
327
  // This is the query generated by the MySQL dialect
310
328
  _Fable.log.trace('Custom Count Query', tmpQuery.query);
311
329
  Expect(tmpQuery.query.body)
312
- .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal` WHERE Age = :Age_w0;');
330
+ .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal` USE INDEX (AnimalIndex_1,AnimalIndex_2) WHERE Age = :Age_w0;');
313
331
  }
314
332
  );
315
333
  test
@@ -126,6 +126,22 @@ suite
126
126
  }
127
127
  );
128
128
  test
129
+ (
130
+ 'Read Query with Index Hinting',
131
+ function()
132
+ {
133
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
134
+ tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
135
+ tmpQuery.indexHints = ['AnimalIndex_1'];
136
+ // Build the query
137
+ tmpQuery.buildReadQuery();
138
+ // This is the query generated by the MSSQL dialect
139
+ _Fable.log.trace('Simple Select Query', tmpQuery.query);
140
+ Expect(tmpQuery.query.body)
141
+ .to.equal('SELECT Animal.* FROM Animal WITH(INDEX(AnimalIndex_1)) ORDER BY Cost DESC;');
142
+ }
143
+ );
144
+ test
129
145
  (
130
146
  'Read Query with Distinct',
131
147
  function()
@@ -301,7 +317,7 @@ suite
301
317
  .setDialect('MSSQL')
302
318
  .setScope('Animal')
303
319
  .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
304
- tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %> <%= Where %>;';
320
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %><%= IndexHints %> <%= Where %>;';
305
321
  // Build the query
306
322
  tmpQuery.buildCountQuery();
307
323
  // This is the query generated by the MSSQL dialect
@@ -311,6 +327,25 @@ suite
311
327
  }
312
328
  );
313
329
  test
330
+ (
331
+ 'Custom Count Query with Index Hinting',
332
+ function()
333
+ {
334
+ var tmpQuery = libFoxHound.new(_Fable)
335
+ .setDialect('MSSQL')
336
+ .setScope('Animal')
337
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
338
+ tmpQuery.indexHints = ['AnimalIndex_1'];
339
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %><%= IndexHints %> <%= Where %>;';
340
+ // Build the query
341
+ tmpQuery.buildCountQuery();
342
+ // This is the query generated by the MSSQL dialect
343
+ _Fable.log.trace('Custom Count Query', tmpQuery.query);
344
+ Expect(tmpQuery.query.body)
345
+ .to.equal('SELECT COUNT(*) AS RowCount FROM Animal WITH(INDEX(AnimalIndex_1)) WHERE Age = @Age_w0;');
346
+ }
347
+ );
348
+ test
314
349
  (
315
350
  'Custom Count Query with Custom Parameters',
316
351
  function()
@@ -390,13 +425,14 @@ suite
390
425
  var tmpQuery = libFoxHound.new(_Fable)
391
426
  .setDialect('MSSQL')
392
427
  .setScope('Animal');
428
+ tmpQuery.indexHints = ['AnimalIndex_1'];
393
429
 
394
430
  // Build the query
395
431
  tmpQuery.buildCountQuery();
396
432
  // This is the query generated by the MSSQL dialect
397
433
  _Fable.log.trace('Count Query', tmpQuery.query);
398
434
  Expect(tmpQuery.query.body)
399
- .to.equal('SELECT COUNT(*) AS Row_Count FROM Animal;');
435
+ .to.equal('SELECT COUNT(*) AS Row_Count FROM Animal WITH(INDEX(AnimalIndex_1));');
400
436
  }
401
437
  );
402
438
  test