foxhound 2.0.16 → 2.0.17
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/docs/.nojekyll +0 -1
- package/docs/css/docuserve.css +73 -0
- package/docs/index.html +1 -1
- package/docs/retold-catalog.json +125 -0
- package/docs/retold-keyword-index.json +6358 -0
- package/package.json +1 -1
- package/source/dialects/SQLite/FoxHound-Dialect-SQLite.js +21 -4
- package/test/FoxHound-Dialect-SQLite_tests.js +2 -2
- package/dist/foxhound.js +0 -3020
- package/dist/foxhound.min.js +0 -15
- package/dist/foxhound.min.js.map +0 -1
package/dist/foxhound.js
DELETED
|
@@ -1,3020 +0,0 @@
|
|
|
1
|
-
(function (f) {
|
|
2
|
-
if (typeof exports === "object" && typeof module !== "undefined") {
|
|
3
|
-
module.exports = f();
|
|
4
|
-
} else if (typeof define === "function" && define.amd) {
|
|
5
|
-
define([], f);
|
|
6
|
-
} else {
|
|
7
|
-
var g;
|
|
8
|
-
if (typeof window !== "undefined") {
|
|
9
|
-
g = window;
|
|
10
|
-
} else if (typeof global !== "undefined") {
|
|
11
|
-
g = global;
|
|
12
|
-
} else if (typeof self !== "undefined") {
|
|
13
|
-
g = self;
|
|
14
|
-
} else {
|
|
15
|
-
g = this;
|
|
16
|
-
}
|
|
17
|
-
g.Foxhound = f();
|
|
18
|
-
}
|
|
19
|
-
})(function () {
|
|
20
|
-
var define, module, exports;
|
|
21
|
-
return function () {
|
|
22
|
-
function r(e, n, t) {
|
|
23
|
-
function o(i, f) {
|
|
24
|
-
if (!n[i]) {
|
|
25
|
-
if (!e[i]) {
|
|
26
|
-
var c = "function" == typeof require && require;
|
|
27
|
-
if (!f && c) return c(i, !0);
|
|
28
|
-
if (u) return u(i, !0);
|
|
29
|
-
var a = new Error("Cannot find module '" + i + "'");
|
|
30
|
-
throw a.code = "MODULE_NOT_FOUND", a;
|
|
31
|
-
}
|
|
32
|
-
var p = n[i] = {
|
|
33
|
-
exports: {}
|
|
34
|
-
};
|
|
35
|
-
e[i][0].call(p.exports, function (r) {
|
|
36
|
-
var n = e[i][1][r];
|
|
37
|
-
return o(n || r);
|
|
38
|
-
}, p, p.exports, r, e, n, t);
|
|
39
|
-
}
|
|
40
|
-
return n[i].exports;
|
|
41
|
-
}
|
|
42
|
-
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
|
|
43
|
-
return o;
|
|
44
|
-
}
|
|
45
|
-
return r;
|
|
46
|
-
}()({
|
|
47
|
-
1: [function (require, module, exports) {
|
|
48
|
-
/**
|
|
49
|
-
* Simple browser shim loader - assign the npm module to a window global automatically
|
|
50
|
-
*
|
|
51
|
-
* @license MIT
|
|
52
|
-
* @author <steven@velozo.com>
|
|
53
|
-
*/
|
|
54
|
-
var libNPMModuleWrapper = require('./Foxhound.js');
|
|
55
|
-
if (typeof window === 'object' && !window.hasOwnProperty('Foxhound')) {
|
|
56
|
-
window.Foxhound = libNPMModuleWrapper;
|
|
57
|
-
}
|
|
58
|
-
module.exports = libNPMModuleWrapper;
|
|
59
|
-
}, {
|
|
60
|
-
"./Foxhound.js": 3
|
|
61
|
-
}],
|
|
62
|
-
2: [function (require, module, exports) {
|
|
63
|
-
getDialects = () => {
|
|
64
|
-
let tmpDialects = {};
|
|
65
|
-
tmpDialects.ALASQL = require('./dialects/ALASQL/FoxHound-Dialect-ALASQL.js');
|
|
66
|
-
tmpDialects.English = require('./dialects/English/FoxHound-Dialect-English.js');
|
|
67
|
-
tmpDialects.MeadowEndpoints = require('./dialects/MeadowEndpoints/FoxHound-Dialect-MeadowEndpoints.js');
|
|
68
|
-
tmpDialects.MySQL = require('./dialects/MySQL/FoxHound-Dialect-MySQL.js');
|
|
69
|
-
tmpDialects.default = tmpDialects.English;
|
|
70
|
-
return tmpDialects;
|
|
71
|
-
};
|
|
72
|
-
module.exports = getDialects();
|
|
73
|
-
}, {
|
|
74
|
-
"./dialects/ALASQL/FoxHound-Dialect-ALASQL.js": 5,
|
|
75
|
-
"./dialects/English/FoxHound-Dialect-English.js": 6,
|
|
76
|
-
"./dialects/MeadowEndpoints/FoxHound-Dialect-MeadowEndpoints.js": 7,
|
|
77
|
-
"./dialects/MySQL/FoxHound-Dialect-MySQL.js": 8
|
|
78
|
-
}],
|
|
79
|
-
3: [function (require, module, exports) {
|
|
80
|
-
/**
|
|
81
|
-
* FoxHound Query Generation Library
|
|
82
|
-
* @license MIT
|
|
83
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
84
|
-
*/
|
|
85
|
-
|
|
86
|
-
// Load our base parameters skeleton object
|
|
87
|
-
const baseParameters = require('./Parameters.js');
|
|
88
|
-
var FoxHound = function () {
|
|
89
|
-
function createNew(pFable, pFromParameters) {
|
|
90
|
-
// If a valid Fable object isn't passed in, return a constructor
|
|
91
|
-
if (typeof pFable !== 'object' || !('fable' in pFable)) {
|
|
92
|
-
return {
|
|
93
|
-
new: createNew
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
var _Fable = pFable;
|
|
97
|
-
|
|
98
|
-
// The default parameters config object, used as a template for all new
|
|
99
|
-
// queries created from this query.
|
|
100
|
-
var _DefaultParameters = typeof pFromParameters === 'undefined' ? {} : pFromParameters;
|
|
101
|
-
|
|
102
|
-
// The parameters config object for the current query. This is the only
|
|
103
|
-
// piece of internal state that is important to operation.
|
|
104
|
-
var _Parameters = false;
|
|
105
|
-
var _Dialects = require('./Foxhound-Dialects.js');
|
|
106
|
-
|
|
107
|
-
// The unique identifier for a query
|
|
108
|
-
var _UUID = _Fable.getUUID();
|
|
109
|
-
|
|
110
|
-
// The log level, for debugging chattiness.
|
|
111
|
-
var _LogLevel = 0;
|
|
112
|
-
|
|
113
|
-
// The dialect to use when generating queries
|
|
114
|
-
var _Dialect = false;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Clone the current FoxHound Query into a new Query object, copying all
|
|
118
|
-
* parameters as the new default. Clone also copies the log level.
|
|
119
|
-
*
|
|
120
|
-
* @method clone
|
|
121
|
-
* @return {Object} Returns a cloned Query. This is still chainable.
|
|
122
|
-
*/
|
|
123
|
-
var clone = function () {
|
|
124
|
-
var tmpFoxHound = createNew(_Fable, baseParameters).setScope(_Parameters.scope).setBegin(_Parameters.begin).setCap(_Parameters.cap);
|
|
125
|
-
|
|
126
|
-
// Schema is the only part of a query that carries forward.
|
|
127
|
-
tmpFoxHound.query.schema = _Parameters.query.schema;
|
|
128
|
-
if (_Parameters.dataElements) {
|
|
129
|
-
tmpFoxHound.parameters.dataElements = _Parameters.dataElements.slice(); // Copy the array of dataElements
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (_Parameters.sort) {
|
|
133
|
-
tmpFoxHound.parameters.sort = _Parameters.sort.slice(); // Copy the sort array.
|
|
134
|
-
// TODO: Fix the side affect nature of these being objects in the array .. they are technically clones of the previous.
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (_Parameters.filter) {
|
|
138
|
-
tmpFoxHound.parameters.filter = _Parameters.filter.slice(); // Copy the filter array.
|
|
139
|
-
// TODO: Fix the side affect nature of these being objects in the array .. they are technically clones of the previous.
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
return tmpFoxHound;
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Reset the parameters of the FoxHound Query to the Default. Default
|
|
147
|
-
* parameters were set during object construction.
|
|
148
|
-
*
|
|
149
|
-
* @method resetParameters
|
|
150
|
-
* @return {Object} Returns the current Query for chaining.
|
|
151
|
-
*/
|
|
152
|
-
var resetParameters = function () {
|
|
153
|
-
_Parameters = _Fable.Utility.extend({}, baseParameters, _DefaultParameters);
|
|
154
|
-
_Parameters.query = {
|
|
155
|
-
disableAutoIdentity: false,
|
|
156
|
-
disableAutoDateStamp: false,
|
|
157
|
-
disableAutoUserStamp: false,
|
|
158
|
-
disableDeleteTracking: false,
|
|
159
|
-
body: false,
|
|
160
|
-
schema: false,
|
|
161
|
-
// The schema to intersect with our records
|
|
162
|
-
IDUser: 0,
|
|
163
|
-
// The user to stamp into records
|
|
164
|
-
UUID: _Fable.getUUID(),
|
|
165
|
-
// A UUID for this record
|
|
166
|
-
records: false,
|
|
167
|
-
// The records to be created or changed
|
|
168
|
-
parameters: {}
|
|
169
|
-
};
|
|
170
|
-
_Parameters.result = {
|
|
171
|
-
executed: false,
|
|
172
|
-
// True once we've run a query.
|
|
173
|
-
value: false,
|
|
174
|
-
// The return value of the last query run
|
|
175
|
-
// Updated below due to changes in how Async.js responds to a false value here
|
|
176
|
-
error: undefined // The error message of the last run query
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
return this;
|
|
180
|
-
};
|
|
181
|
-
resetParameters();
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Reset the parameters of the FoxHound Query to the Default. Default
|
|
185
|
-
* parameters were set during object construction.
|
|
186
|
-
*
|
|
187
|
-
* @method mergeParameters
|
|
188
|
-
* @param {Object} pFromParameters A Parameters Object to merge from
|
|
189
|
-
* @return {Object} Returns the current Query for chaining.
|
|
190
|
-
*/
|
|
191
|
-
var mergeParameters = function (pFromParameters) {
|
|
192
|
-
_Parameters = _Fable.Utility.extend({}, _Parameters, pFromParameters);
|
|
193
|
-
return this;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Set the the Logging level.
|
|
198
|
-
*
|
|
199
|
-
* The log levels are:
|
|
200
|
-
* 0 - Don't log anything
|
|
201
|
-
* 1 - Log queries
|
|
202
|
-
* 2 - Log queries and non-parameterized queries
|
|
203
|
-
* 3 - Log everything
|
|
204
|
-
*
|
|
205
|
-
* @method setLogLevel
|
|
206
|
-
* @param {Number} pLogLevel The log level for our object
|
|
207
|
-
* @return {Object} Returns the current Query for chaining.
|
|
208
|
-
*/
|
|
209
|
-
var setLogLevel = function (pLogLevel) {
|
|
210
|
-
var tmpLogLevel = 0;
|
|
211
|
-
if (typeof pLogLevel === 'number' && pLogLevel % 1 === 0) {
|
|
212
|
-
tmpLogLevel = pLogLevel;
|
|
213
|
-
}
|
|
214
|
-
_LogLevel = tmpLogLevel;
|
|
215
|
-
return this;
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Set the Scope for the Query. *Scope* is the source for the data being
|
|
220
|
-
* pulled. In TSQL this would be the _table_, whereas in MongoDB this
|
|
221
|
-
* would be the _collection_.
|
|
222
|
-
*
|
|
223
|
-
* A scope can be either a string, or an array (for JOINs and such).
|
|
224
|
-
*
|
|
225
|
-
* @method setScope
|
|
226
|
-
* @param {String} pScope A Scope for the Query.
|
|
227
|
-
* @return {Object} Returns the current Query for chaining.
|
|
228
|
-
*/
|
|
229
|
-
var setScope = function (pScope) {
|
|
230
|
-
var tmpScope = false;
|
|
231
|
-
if (typeof pScope === 'string') {
|
|
232
|
-
tmpScope = pScope;
|
|
233
|
-
} else if (pScope !== false) {
|
|
234
|
-
_Fable.log.error('Scope set failed. You must pass in a string or array.', {
|
|
235
|
-
queryUUID: _UUID,
|
|
236
|
-
parameters: _Parameters,
|
|
237
|
-
invalidScope: pScope
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
_Parameters.scope = tmpScope;
|
|
241
|
-
if (_LogLevel > 2) {
|
|
242
|
-
_Fable.log.info('Scope set: ' + tmpScope, {
|
|
243
|
-
queryUUID: _UUID,
|
|
244
|
-
parameters: _Parameters
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
return this;
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Set whether the query returns DISTINCT results.
|
|
252
|
-
* For count queries, returns the distinct for the selected fields, or all fields in the base table by default.
|
|
253
|
-
*
|
|
254
|
-
* @method setDistinct
|
|
255
|
-
* @param {Boolean} pDistinct True if the query should be distinct.
|
|
256
|
-
* @return {Object} Returns the current Query for chaining.
|
|
257
|
-
*/
|
|
258
|
-
var setDistinct = function (pDistinct) {
|
|
259
|
-
_Parameters.distinct = !!pDistinct;
|
|
260
|
-
if (_LogLevel > 2) {
|
|
261
|
-
_Fable.log.info('Distinct set: ' + _Parameters.distinct, {
|
|
262
|
-
queryUUID: _UUID,
|
|
263
|
-
parameters: _Parameters
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
return this;
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Set the Data Elements for the Query. *Data Elements* are the fields
|
|
271
|
-
* being pulled by the query. In TSQL this would be the _columns_,
|
|
272
|
-
* whereas in MongoDB this would be the _fields_.
|
|
273
|
-
*
|
|
274
|
-
* The passed values can be either a string, or an array.
|
|
275
|
-
*
|
|
276
|
-
* @method setDataElements
|
|
277
|
-
* @param {String} pDataElements The Data Element(s) for the Query.
|
|
278
|
-
* @return {Object} Returns the current Query for chaining.
|
|
279
|
-
*/
|
|
280
|
-
var setDataElements = function (pDataElements) {
|
|
281
|
-
var tmpDataElements = false;
|
|
282
|
-
if (Array.isArray(pDataElements)) {
|
|
283
|
-
// TODO: Check each entry of the array are all strings
|
|
284
|
-
tmpDataElements = pDataElements;
|
|
285
|
-
}
|
|
286
|
-
if (typeof pDataElements === 'string') {
|
|
287
|
-
tmpDataElements = [pDataElements];
|
|
288
|
-
}
|
|
289
|
-
_Parameters.dataElements = tmpDataElements;
|
|
290
|
-
if (_LogLevel > 2) {
|
|
291
|
-
_Fable.log.info('Data Elements set', {
|
|
292
|
-
queryUUID: _UUID,
|
|
293
|
-
parameters: _Parameters
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
return this;
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Set the sort data element
|
|
301
|
-
*
|
|
302
|
-
* The passed values can be either a string, an object or an array of objects.
|
|
303
|
-
*
|
|
304
|
-
* The Sort object has two values:
|
|
305
|
-
* {Column:'Birthday', Direction:'Ascending'}
|
|
306
|
-
*
|
|
307
|
-
* @method setSort
|
|
308
|
-
* @param {String} pSort The sort criteria(s) for the Query.
|
|
309
|
-
* @return {Object} Returns the current Query for chaining.
|
|
310
|
-
*/
|
|
311
|
-
var setSort = function (pSort) {
|
|
312
|
-
var tmpSort = false;
|
|
313
|
-
if (Array.isArray(pSort)) {
|
|
314
|
-
// TODO: Check each entry of the array are all conformant sort objects
|
|
315
|
-
tmpSort = pSort;
|
|
316
|
-
} else if (typeof pSort === 'string') {
|
|
317
|
-
// Default to ascending
|
|
318
|
-
tmpSort = [{
|
|
319
|
-
Column: pSort,
|
|
320
|
-
Direction: 'Ascending'
|
|
321
|
-
}];
|
|
322
|
-
} else if (typeof pSort === 'object') {
|
|
323
|
-
// TODO: Check that this sort entry conforms to a sort entry
|
|
324
|
-
tmpSort = [pSort];
|
|
325
|
-
}
|
|
326
|
-
_Parameters.sort = tmpSort;
|
|
327
|
-
if (_LogLevel > 2) {
|
|
328
|
-
_Fable.log.info('Sort set', {
|
|
329
|
-
queryUUID: _UUID,
|
|
330
|
-
parameters: _Parameters
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
return this;
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Set the join data element
|
|
338
|
-
*
|
|
339
|
-
* The passed values can be either an object or an array of objects.
|
|
340
|
-
*
|
|
341
|
-
* The join object has four values:
|
|
342
|
-
* {Type:'INNER JOIN', Table:'Test', From:'Test.ID', To:'Scope.IDItem'}
|
|
343
|
-
*
|
|
344
|
-
* @method setJoin
|
|
345
|
-
* @param {Object} pJoin The join criteria(s) for the Query.
|
|
346
|
-
* @return {Object} Returns the current Query for chaining.
|
|
347
|
-
*/
|
|
348
|
-
var setJoin = function (pJoin) {
|
|
349
|
-
_Parameters.join = [];
|
|
350
|
-
if (Array.isArray(pJoin)) {
|
|
351
|
-
pJoin.forEach(function (join) {
|
|
352
|
-
addJoin(join.Table, join.From, join.To, join.Type);
|
|
353
|
-
});
|
|
354
|
-
} else if (typeof pJoin === 'object') {
|
|
355
|
-
addJoin(pJoin.Table, pJoin.From, pJoin.To, pJoin.Type);
|
|
356
|
-
}
|
|
357
|
-
return this;
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Add a sort data element
|
|
362
|
-
*
|
|
363
|
-
* The passed values can be either a string, an object or an array of objects.
|
|
364
|
-
*
|
|
365
|
-
* The Sort object has two values:
|
|
366
|
-
* {Column:'Birthday', Direction:'Ascending'}
|
|
367
|
-
*
|
|
368
|
-
* @method setSort
|
|
369
|
-
* @param {String} pSort The sort criteria to add to the Query.
|
|
370
|
-
* @return {Object} Returns the current Query for chaining.
|
|
371
|
-
*/
|
|
372
|
-
var addSort = function (pSort) {
|
|
373
|
-
var tmpSort = false;
|
|
374
|
-
if (typeof pSort === 'string') {
|
|
375
|
-
// Default to ascending
|
|
376
|
-
tmpSort = {
|
|
377
|
-
Column: pSort,
|
|
378
|
-
Direction: 'Ascending'
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
if (typeof pSort === 'object') {
|
|
382
|
-
// TODO: Check that this sort entry conforms to a sort entry
|
|
383
|
-
tmpSort = pSort;
|
|
384
|
-
}
|
|
385
|
-
if (!_Parameters.sort) {
|
|
386
|
-
_Parameters.sort = [];
|
|
387
|
-
}
|
|
388
|
-
_Parameters.sort.push(tmpSort);
|
|
389
|
-
if (_LogLevel > 2) {
|
|
390
|
-
_Fable.log.info('Sort set', {
|
|
391
|
-
queryUUID: _UUID,
|
|
392
|
-
parameters: _Parameters
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
return this;
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
/**
|
|
399
|
-
* Set the the Begin index for the Query. *Begin* is the index at which
|
|
400
|
-
* a query should start returning rows. In TSQL this would be the n
|
|
401
|
-
* parameter of ```LIMIT 1,n```, whereas in MongoDB this would be the
|
|
402
|
-
* n in ```skip(n)```.
|
|
403
|
-
*
|
|
404
|
-
* The passed value must be an Integer >= 0.
|
|
405
|
-
*
|
|
406
|
-
* @method setBegin
|
|
407
|
-
* @param {Number} pBeginAmount The index to begin returning Query data.
|
|
408
|
-
* @return {Object} Returns the current Query for chaining.
|
|
409
|
-
*/
|
|
410
|
-
var setBegin = function (pBeginAmount) {
|
|
411
|
-
var tmpBegin = false;
|
|
412
|
-
|
|
413
|
-
// Test if it is an integer > -1
|
|
414
|
-
// http://jsperf.com/numbers-and-integers
|
|
415
|
-
if (typeof pBeginAmount === 'number' && pBeginAmount % 1 === 0 && pBeginAmount >= 0) {
|
|
416
|
-
tmpBegin = pBeginAmount;
|
|
417
|
-
} else if (pBeginAmount !== false) {
|
|
418
|
-
_Fable.log.error('Begin set failed; non-positive or non-numeric argument.', {
|
|
419
|
-
queryUUID: _UUID,
|
|
420
|
-
parameters: _Parameters,
|
|
421
|
-
invalidBeginAmount: pBeginAmount
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
_Parameters.begin = tmpBegin;
|
|
425
|
-
if (_LogLevel > 2) {
|
|
426
|
-
_Fable.log.info('Begin set: ' + pBeginAmount, {
|
|
427
|
-
queryUUID: _UUID,
|
|
428
|
-
parameters: _Parameters
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
return this;
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
/**
|
|
435
|
-
* Set the the Cap for the Query. *Cap* is the maximum number of records
|
|
436
|
-
* a Query should return in a set. In TSQL this would be the n
|
|
437
|
-
* parameter of ```LIMIT n```, whereas in MongoDB this would be the
|
|
438
|
-
* n in ```limit(n)```.
|
|
439
|
-
*
|
|
440
|
-
* The passed value must be an Integer >= 0.
|
|
441
|
-
*
|
|
442
|
-
* @method setCap
|
|
443
|
-
* @param {Number} pCapAmount The maximum records for the Query set.
|
|
444
|
-
* @return {Object} Returns the current Query for chaining.
|
|
445
|
-
*/
|
|
446
|
-
var setCap = function (pCapAmount) {
|
|
447
|
-
var tmpCapAmount = false;
|
|
448
|
-
if (typeof pCapAmount === 'number' && pCapAmount % 1 === 0 && pCapAmount >= 0) {
|
|
449
|
-
tmpCapAmount = pCapAmount;
|
|
450
|
-
} else if (pCapAmount !== false) {
|
|
451
|
-
_Fable.log.error('Cap set failed; non-positive or non-numeric argument.', {
|
|
452
|
-
queryUUID: _UUID,
|
|
453
|
-
parameters: _Parameters,
|
|
454
|
-
invalidCapAmount: pCapAmount
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
_Parameters.cap = tmpCapAmount;
|
|
458
|
-
if (_LogLevel > 2) {
|
|
459
|
-
_Fable.log.info('Cap set to: ' + tmpCapAmount, {
|
|
460
|
-
queryUUID: _UUID,
|
|
461
|
-
parameters: _Parameters
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
return this;
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
/**
|
|
468
|
-
* Set the filter expression
|
|
469
|
-
*
|
|
470
|
-
* The passed values can be either an object or an array of objects.
|
|
471
|
-
*
|
|
472
|
-
* The Filter object has a minimum of two values (which expands to the following):
|
|
473
|
-
* {Column:'Name', Value:'John'}
|
|
474
|
-
* {Column:'Name', Operator:'EQ', Value:'John', Connector:'And', Parameter:'Name'}
|
|
475
|
-
*
|
|
476
|
-
* @method setFilter
|
|
477
|
-
* @param {String} pFilter The filter(s) for the Query.
|
|
478
|
-
* @return {Object} Returns the current Query for chaining.
|
|
479
|
-
*/
|
|
480
|
-
var setFilter = function (pFilter) {
|
|
481
|
-
var tmpFilter = false;
|
|
482
|
-
if (Array.isArray(pFilter)) {
|
|
483
|
-
// TODO: Check each entry of the array are all conformant Filter objects
|
|
484
|
-
tmpFilter = pFilter;
|
|
485
|
-
} else if (typeof pFilter === 'object') {
|
|
486
|
-
// TODO: Check that this Filter entry conforms to a Filter entry
|
|
487
|
-
tmpFilter = [pFilter];
|
|
488
|
-
}
|
|
489
|
-
_Parameters.filter = tmpFilter;
|
|
490
|
-
if (_LogLevel > 2) {
|
|
491
|
-
_Fable.log.info('Filter set', {
|
|
492
|
-
queryUUID: _UUID,
|
|
493
|
-
parameters: _Parameters
|
|
494
|
-
});
|
|
495
|
-
}
|
|
496
|
-
return this;
|
|
497
|
-
};
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Add a filter expression
|
|
501
|
-
*
|
|
502
|
-
* {Column:'Name', Operator:'EQ', Value:'John', Connector:'And', Parameter:'Name'}
|
|
503
|
-
*
|
|
504
|
-
* @method addFilter
|
|
505
|
-
* @return {Object} Returns the current Query for chaining.
|
|
506
|
-
*/
|
|
507
|
-
var addFilter = function (pColumn, pValue, pOperator, pConnector, pParameter) {
|
|
508
|
-
if (typeof pColumn !== 'string') {
|
|
509
|
-
_Fable.log.warn('Tried to add an invalid query filter column', {
|
|
510
|
-
queryUUID: _UUID,
|
|
511
|
-
parameters: _Parameters
|
|
512
|
-
});
|
|
513
|
-
return this;
|
|
514
|
-
}
|
|
515
|
-
if (typeof pValue === 'undefined') {
|
|
516
|
-
_Fable.log.warn('Tried to add an invalid query filter value', {
|
|
517
|
-
queryUUID: _UUID,
|
|
518
|
-
parameters: _Parameters,
|
|
519
|
-
invalidColumn: pColumn
|
|
520
|
-
});
|
|
521
|
-
return this;
|
|
522
|
-
}
|
|
523
|
-
var tmpOperator = typeof pOperator === 'undefined' ? '=' : pOperator;
|
|
524
|
-
var tmpConnector = typeof pConnector === 'undefined' ? 'AND' : pConnector;
|
|
525
|
-
var tmpParameter = typeof pParameter === 'undefined' ? pColumn : pParameter;
|
|
526
|
-
|
|
527
|
-
//support table.field notation (mysql2 requires this)
|
|
528
|
-
tmpParameter = tmpParameter.replace('.', '_');
|
|
529
|
-
var tmpFilter = {
|
|
530
|
-
Column: pColumn,
|
|
531
|
-
Operator: tmpOperator,
|
|
532
|
-
Value: pValue,
|
|
533
|
-
Connector: tmpConnector,
|
|
534
|
-
Parameter: tmpParameter
|
|
535
|
-
};
|
|
536
|
-
if (!Array.isArray(_Parameters.filter)) {
|
|
537
|
-
_Parameters.filter = [tmpFilter];
|
|
538
|
-
} else {
|
|
539
|
-
_Parameters.filter.push(tmpFilter);
|
|
540
|
-
}
|
|
541
|
-
if (_LogLevel > 2) {
|
|
542
|
-
_Fable.log.info('Added a filter', {
|
|
543
|
-
queryUUID: _UUID,
|
|
544
|
-
parameters: _Parameters,
|
|
545
|
-
newFilter: tmpFilter
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
return this;
|
|
549
|
-
};
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Add a join expression
|
|
553
|
-
*
|
|
554
|
-
* {Type:'INNER JOIN', Table:'Test', From:'Test.ID', To:'Scope.IDItem'}
|
|
555
|
-
*
|
|
556
|
-
* @method addJoin
|
|
557
|
-
* @return {Object} Returns the current Query for chaining.
|
|
558
|
-
*/
|
|
559
|
-
var addJoin = function (pTable, pFrom, pTo, pType) {
|
|
560
|
-
if (typeof pTable !== 'string') {
|
|
561
|
-
_Fable.log.warn('Tried to add an invalid query join table', {
|
|
562
|
-
queryUUID: _UUID,
|
|
563
|
-
parameters: _Parameters
|
|
564
|
-
});
|
|
565
|
-
return this;
|
|
566
|
-
}
|
|
567
|
-
if (typeof pFrom === 'undefined' || typeof pTo === 'undefined') {
|
|
568
|
-
_Fable.log.warn('Tried to add an invalid query join field', {
|
|
569
|
-
queryUUID: _UUID,
|
|
570
|
-
parameters: _Parameters
|
|
571
|
-
});
|
|
572
|
-
return this;
|
|
573
|
-
}
|
|
574
|
-
//sanity check the join fields
|
|
575
|
-
if (pFrom.indexOf(pTable) != 0) {
|
|
576
|
-
_Fable.log.warn('Tried to add an invalid query join field, join must come FROM the join table!', {
|
|
577
|
-
queryUUID: _UUID,
|
|
578
|
-
parameters: _Parameters,
|
|
579
|
-
invalidField: pFrom
|
|
580
|
-
});
|
|
581
|
-
return this;
|
|
582
|
-
}
|
|
583
|
-
if (pTo.indexOf('.') <= 0) {
|
|
584
|
-
_Fable.log.warn('Tried to add an invalid query join field, join must go TO a field on another table ([table].[field])!', {
|
|
585
|
-
queryUUID: _UUID,
|
|
586
|
-
parameters: _Parameters,
|
|
587
|
-
invalidField: pTo
|
|
588
|
-
});
|
|
589
|
-
return this;
|
|
590
|
-
}
|
|
591
|
-
var tmpType = typeof pType === 'undefined' ? 'INNER JOIN' : pType;
|
|
592
|
-
var tmpJoin = {
|
|
593
|
-
Type: tmpType,
|
|
594
|
-
Table: pTable,
|
|
595
|
-
From: pFrom,
|
|
596
|
-
To: pTo
|
|
597
|
-
};
|
|
598
|
-
if (!Array.isArray(_Parameters.join)) {
|
|
599
|
-
_Parameters.join = [tmpJoin];
|
|
600
|
-
} else {
|
|
601
|
-
_Parameters.join.push(tmpJoin);
|
|
602
|
-
}
|
|
603
|
-
if (_LogLevel > 2) {
|
|
604
|
-
_Fable.log.info('Added a join', {
|
|
605
|
-
queryUUID: _UUID,
|
|
606
|
-
parameters: _Parameters
|
|
607
|
-
});
|
|
608
|
-
}
|
|
609
|
-
return this;
|
|
610
|
-
};
|
|
611
|
-
|
|
612
|
-
/**
|
|
613
|
-
* Add a record (for UPDATE and INSERT)
|
|
614
|
-
*
|
|
615
|
-
*
|
|
616
|
-
* @method addRecord
|
|
617
|
-
* @param {Object} pRecord The record to add.
|
|
618
|
-
* @return {Object} Returns the current Query for chaining.
|
|
619
|
-
*/
|
|
620
|
-
var addRecord = function (pRecord) {
|
|
621
|
-
if (typeof pRecord !== 'object') {
|
|
622
|
-
_Fable.log.warn('Tried to add an invalid record to the query -- records must be an object', {
|
|
623
|
-
queryUUID: _UUID,
|
|
624
|
-
parameters: _Parameters
|
|
625
|
-
});
|
|
626
|
-
return this;
|
|
627
|
-
}
|
|
628
|
-
if (!Array.isArray(_Parameters.query.records)) {
|
|
629
|
-
_Parameters.query.records = [pRecord];
|
|
630
|
-
} else {
|
|
631
|
-
_Parameters.query.records.push(pRecord);
|
|
632
|
-
}
|
|
633
|
-
if (_LogLevel > 2) {
|
|
634
|
-
_Fable.log.info('Added a record to the query', {
|
|
635
|
-
queryUUID: _UUID,
|
|
636
|
-
parameters: _Parameters,
|
|
637
|
-
newRecord: pRecord
|
|
638
|
-
});
|
|
639
|
-
}
|
|
640
|
-
return this;
|
|
641
|
-
};
|
|
642
|
-
|
|
643
|
-
/**
|
|
644
|
-
* Set the Dialect for Query generation.
|
|
645
|
-
*
|
|
646
|
-
* This function expects a string, case sensitive, which matches both the
|
|
647
|
-
* folder and filename
|
|
648
|
-
*
|
|
649
|
-
* @method setDialect
|
|
650
|
-
* @param {String} pDialectName The dialect for query generation.
|
|
651
|
-
* @return {Object} Returns the current Query for chaining.
|
|
652
|
-
*/
|
|
653
|
-
var setDialect = function (pDialectName) {
|
|
654
|
-
if (typeof pDialectName !== 'string') {
|
|
655
|
-
_Fable.log.warn('Dialect set to English - invalid name', {
|
|
656
|
-
queryUUID: _UUID,
|
|
657
|
-
parameters: _Parameters,
|
|
658
|
-
invalidDialect: pDialectName
|
|
659
|
-
});
|
|
660
|
-
return setDialect('English');
|
|
661
|
-
}
|
|
662
|
-
if (_Dialects.hasOwnProperty(pDialectName)) {
|
|
663
|
-
_Dialect = _Dialects[pDialectName](_Fable);
|
|
664
|
-
if (_LogLevel > 2) {
|
|
665
|
-
_Fable.log.info('Dialog set to: ' + pDialectName, {
|
|
666
|
-
queryUUID: _UUID,
|
|
667
|
-
parameters: _Parameters
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
} else {
|
|
671
|
-
_Fable.log.error('Dialect not set - unknown dialect "' + pDialectName + "'", {
|
|
672
|
-
queryUUID: _UUID,
|
|
673
|
-
parameters: _Parameters,
|
|
674
|
-
invalidDialect: pDialectName
|
|
675
|
-
});
|
|
676
|
-
setDialect('English');
|
|
677
|
-
}
|
|
678
|
-
return this;
|
|
679
|
-
};
|
|
680
|
-
|
|
681
|
-
/**
|
|
682
|
-
* User to use for this query
|
|
683
|
-
*
|
|
684
|
-
* @method setIDUser
|
|
685
|
-
*/
|
|
686
|
-
var setIDUser = function (pIDUser) {
|
|
687
|
-
var tmpUserID = 0;
|
|
688
|
-
if (typeof pIDUser === 'number' && pIDUser % 1 === 0 && pIDUser >= 0) {
|
|
689
|
-
tmpUserID = pIDUser;
|
|
690
|
-
} else if (pIDUser !== false) {
|
|
691
|
-
_Fable.log.error('User set failed; non-positive or non-numeric argument.', {
|
|
692
|
-
queryUUID: _UUID,
|
|
693
|
-
parameters: _Parameters,
|
|
694
|
-
invalidIDUser: pIDUser
|
|
695
|
-
});
|
|
696
|
-
}
|
|
697
|
-
_Parameters.userID = tmpUserID;
|
|
698
|
-
_Parameters.query.IDUser = tmpUserID;
|
|
699
|
-
if (_LogLevel > 2) {
|
|
700
|
-
_Fable.log.info('IDUser set to: ' + tmpUserID, {
|
|
701
|
-
queryUUID: _UUID,
|
|
702
|
-
parameters: _Parameters
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
return this;
|
|
706
|
-
};
|
|
707
|
-
|
|
708
|
-
/**
|
|
709
|
-
* Flag to disable auto identity
|
|
710
|
-
*
|
|
711
|
-
* @method setDisableAutoIdentity
|
|
712
|
-
*/
|
|
713
|
-
var setDisableAutoIdentity = function (pFlag) {
|
|
714
|
-
_Parameters.query.disableAutoIdentity = pFlag;
|
|
715
|
-
return this; //chainable
|
|
716
|
-
};
|
|
717
|
-
|
|
718
|
-
/**
|
|
719
|
-
* Flag to disable auto datestamp
|
|
720
|
-
*
|
|
721
|
-
* @method setDisableAutoDateStamp
|
|
722
|
-
*/
|
|
723
|
-
var setDisableAutoDateStamp = function (pFlag) {
|
|
724
|
-
_Parameters.query.disableAutoDateStamp = pFlag;
|
|
725
|
-
return this; //chainable
|
|
726
|
-
};
|
|
727
|
-
|
|
728
|
-
/**
|
|
729
|
-
* Flag to disable auto userstamp
|
|
730
|
-
*
|
|
731
|
-
* @method setDisableAutoUserStamp
|
|
732
|
-
*/
|
|
733
|
-
var setDisableAutoUserStamp = function (pFlag) {
|
|
734
|
-
_Parameters.query.disableAutoUserStamp = pFlag;
|
|
735
|
-
return this; //chainable
|
|
736
|
-
};
|
|
737
|
-
|
|
738
|
-
/**
|
|
739
|
-
* Flag to disable delete tracking
|
|
740
|
-
*
|
|
741
|
-
* @method setDisableDeleteTracking
|
|
742
|
-
*/
|
|
743
|
-
var setDisableDeleteTracking = function (pFlag) {
|
|
744
|
-
_Parameters.query.disableDeleteTracking = pFlag;
|
|
745
|
-
return this; //chainable
|
|
746
|
-
};
|
|
747
|
-
|
|
748
|
-
/**
|
|
749
|
-
* Check that a valid Dialect has been set
|
|
750
|
-
*
|
|
751
|
-
* If there has not been a dialect set, it defaults to English.
|
|
752
|
-
* TODO: Have the json configuration define a "default" dialect.
|
|
753
|
-
*
|
|
754
|
-
* @method checkDialect
|
|
755
|
-
*/
|
|
756
|
-
var checkDialect = function () {
|
|
757
|
-
if (_Dialect === false) {
|
|
758
|
-
setDialect('English');
|
|
759
|
-
}
|
|
760
|
-
};
|
|
761
|
-
var buildCreateQuery = function () {
|
|
762
|
-
checkDialect();
|
|
763
|
-
_Parameters.query.body = _Dialect.Create(_Parameters);
|
|
764
|
-
return this;
|
|
765
|
-
};
|
|
766
|
-
var buildReadQuery = function () {
|
|
767
|
-
checkDialect();
|
|
768
|
-
_Parameters.query.body = _Dialect.Read(_Parameters);
|
|
769
|
-
return this;
|
|
770
|
-
};
|
|
771
|
-
var buildUpdateQuery = function () {
|
|
772
|
-
checkDialect();
|
|
773
|
-
_Parameters.query.body = _Dialect.Update(_Parameters);
|
|
774
|
-
return this;
|
|
775
|
-
};
|
|
776
|
-
var buildDeleteQuery = function () {
|
|
777
|
-
checkDialect();
|
|
778
|
-
_Parameters.query.body = _Dialect.Delete(_Parameters);
|
|
779
|
-
return this;
|
|
780
|
-
};
|
|
781
|
-
var buildUndeleteQuery = function () {
|
|
782
|
-
checkDialect();
|
|
783
|
-
_Parameters.query.body = _Dialect.Undelete(_Parameters);
|
|
784
|
-
return this;
|
|
785
|
-
};
|
|
786
|
-
var buildCountQuery = function () {
|
|
787
|
-
checkDialect();
|
|
788
|
-
_Parameters.query.body = _Dialect.Count(_Parameters);
|
|
789
|
-
return this;
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
/**
|
|
793
|
-
* Container Object for our Factory Pattern
|
|
794
|
-
*/
|
|
795
|
-
var tmpNewFoxHoundObject = {
|
|
796
|
-
resetParameters: resetParameters,
|
|
797
|
-
mergeParameters: mergeParameters,
|
|
798
|
-
setLogLevel: setLogLevel,
|
|
799
|
-
setScope: setScope,
|
|
800
|
-
setDistinct: setDistinct,
|
|
801
|
-
setIDUser: setIDUser,
|
|
802
|
-
setDataElements: setDataElements,
|
|
803
|
-
setBegin: setBegin,
|
|
804
|
-
setCap: setCap,
|
|
805
|
-
setFilter: setFilter,
|
|
806
|
-
addFilter: addFilter,
|
|
807
|
-
setSort: setSort,
|
|
808
|
-
addSort: addSort,
|
|
809
|
-
setJoin: setJoin,
|
|
810
|
-
addJoin: addJoin,
|
|
811
|
-
addRecord: addRecord,
|
|
812
|
-
setDisableAutoIdentity: setDisableAutoIdentity,
|
|
813
|
-
setDisableAutoDateStamp: setDisableAutoDateStamp,
|
|
814
|
-
setDisableAutoUserStamp: setDisableAutoUserStamp,
|
|
815
|
-
setDisableDeleteTracking: setDisableDeleteTracking,
|
|
816
|
-
setDialect: setDialect,
|
|
817
|
-
buildCreateQuery: buildCreateQuery,
|
|
818
|
-
buildReadQuery: buildReadQuery,
|
|
819
|
-
buildUpdateQuery: buildUpdateQuery,
|
|
820
|
-
buildDeleteQuery: buildDeleteQuery,
|
|
821
|
-
buildUndeleteQuery: buildUndeleteQuery,
|
|
822
|
-
buildCountQuery: buildCountQuery,
|
|
823
|
-
clone: clone,
|
|
824
|
-
new: createNew
|
|
825
|
-
};
|
|
826
|
-
|
|
827
|
-
/**
|
|
828
|
-
* Query
|
|
829
|
-
*
|
|
830
|
-
* @property query
|
|
831
|
-
* @type Object
|
|
832
|
-
*/
|
|
833
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'query', {
|
|
834
|
-
get: function () {
|
|
835
|
-
return _Parameters.query;
|
|
836
|
-
},
|
|
837
|
-
set: function (pQuery) {
|
|
838
|
-
_Parameters.query = pQuery;
|
|
839
|
-
},
|
|
840
|
-
enumerable: true
|
|
841
|
-
});
|
|
842
|
-
|
|
843
|
-
/**
|
|
844
|
-
* Result
|
|
845
|
-
*
|
|
846
|
-
* @property result
|
|
847
|
-
* @type Object
|
|
848
|
-
*/
|
|
849
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'result', {
|
|
850
|
-
get: function () {
|
|
851
|
-
return _Parameters.result;
|
|
852
|
-
},
|
|
853
|
-
set: function (pResult) {
|
|
854
|
-
_Parameters.result = pResult;
|
|
855
|
-
},
|
|
856
|
-
enumerable: true
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
/**
|
|
860
|
-
* Query Parameters
|
|
861
|
-
*
|
|
862
|
-
* @property parameters
|
|
863
|
-
* @type Object
|
|
864
|
-
*/
|
|
865
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'parameters', {
|
|
866
|
-
get: function () {
|
|
867
|
-
return _Parameters;
|
|
868
|
-
},
|
|
869
|
-
set: function (pParameters) {
|
|
870
|
-
_Parameters = pParameters;
|
|
871
|
-
},
|
|
872
|
-
enumerable: true
|
|
873
|
-
});
|
|
874
|
-
|
|
875
|
-
/**
|
|
876
|
-
* Dialect
|
|
877
|
-
*
|
|
878
|
-
* @property dialect
|
|
879
|
-
* @type Object
|
|
880
|
-
*/
|
|
881
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'dialect', {
|
|
882
|
-
get: function () {
|
|
883
|
-
return _Dialect;
|
|
884
|
-
},
|
|
885
|
-
enumerable: true
|
|
886
|
-
});
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
* Universally Unique Identifier
|
|
890
|
-
*
|
|
891
|
-
* @property uuid
|
|
892
|
-
* @type String
|
|
893
|
-
*/
|
|
894
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'uuid', {
|
|
895
|
-
get: function () {
|
|
896
|
-
return _UUID;
|
|
897
|
-
},
|
|
898
|
-
enumerable: true
|
|
899
|
-
});
|
|
900
|
-
|
|
901
|
-
/**
|
|
902
|
-
* Log Level
|
|
903
|
-
*
|
|
904
|
-
* @property logLevel
|
|
905
|
-
* @type Integer
|
|
906
|
-
*/
|
|
907
|
-
Object.defineProperty(tmpNewFoxHoundObject, 'logLevel', {
|
|
908
|
-
get: function () {
|
|
909
|
-
return _LogLevel;
|
|
910
|
-
},
|
|
911
|
-
enumerable: true
|
|
912
|
-
});
|
|
913
|
-
return tmpNewFoxHoundObject;
|
|
914
|
-
}
|
|
915
|
-
return createNew();
|
|
916
|
-
};
|
|
917
|
-
module.exports = FoxHound();
|
|
918
|
-
}, {
|
|
919
|
-
"./Foxhound-Dialects.js": 2,
|
|
920
|
-
"./Parameters.js": 4
|
|
921
|
-
}],
|
|
922
|
-
4: [function (require, module, exports) {
|
|
923
|
-
/**
|
|
924
|
-
* Query Parameters Object
|
|
925
|
-
*
|
|
926
|
-
* @class FoxHoundQueryParameters
|
|
927
|
-
* @constructor
|
|
928
|
-
*/
|
|
929
|
-
var FoxHoundQueryParameters = {
|
|
930
|
-
scope: false,
|
|
931
|
-
// STR: The scope of the data
|
|
932
|
-
// TSQL: the "Table" or "View"
|
|
933
|
-
// MongoDB: the "Collection"
|
|
934
|
-
|
|
935
|
-
dataElements: false,
|
|
936
|
-
// ARR of STR: The data elements to return
|
|
937
|
-
// TSQL: the "Columns"
|
|
938
|
-
// MongoDB: the "Fields"
|
|
939
|
-
|
|
940
|
-
begin: false,
|
|
941
|
-
// INT: Record index to start at
|
|
942
|
-
// TSQL: n in LIMIT 1,n
|
|
943
|
-
// MongoDB: n in Skip(n)
|
|
944
|
-
|
|
945
|
-
cap: false,
|
|
946
|
-
// INT: Maximum number of records to return
|
|
947
|
-
// TSQL: n in LIMIT n
|
|
948
|
-
// MongoDB: n in limit(n)
|
|
949
|
-
|
|
950
|
-
// Serialization example for a query:
|
|
951
|
-
// Take the filter and return an array of filter instructions
|
|
952
|
-
// Basic instruction anatomy:
|
|
953
|
-
// INSTRUCTION~FIELD~OPERATOR~VALUE
|
|
954
|
-
// FOP - Filter Open Paren
|
|
955
|
-
// FOP~~(~
|
|
956
|
-
// FCP - Filter Close Paren
|
|
957
|
-
// FCP~~)~
|
|
958
|
-
// FBV - Filter By Value
|
|
959
|
-
// FBV~Category~EQ~Books
|
|
960
|
-
// Possible comparisons:
|
|
961
|
-
// * EQ - Equals To (=)
|
|
962
|
-
// * NE - Not Equals To (!=)
|
|
963
|
-
// * GT - Greater Than (>)
|
|
964
|
-
// * GE - Greater Than or Equals To (>=)
|
|
965
|
-
// * LT - Less Than (<)
|
|
966
|
-
// * LE - Less Than or Equals To (<=)
|
|
967
|
-
// * LK - Like (Like)
|
|
968
|
-
// FBL - Filter By List (value list, separated by commas)
|
|
969
|
-
// FBL~Category~EQ~Books,Movies
|
|
970
|
-
// FSF - Filter Sort Field
|
|
971
|
-
// FSF~Category~ASC~0
|
|
972
|
-
// FSF~Category~DESC~0
|
|
973
|
-
// FCC - Filter Constraint Cap (the limit of what is returned)
|
|
974
|
-
// FCC~~10~
|
|
975
|
-
// FCB - Filter Constraint Begin (the zero-based start index of what is returned)
|
|
976
|
-
// FCB~~10~
|
|
977
|
-
//
|
|
978
|
-
// This means: FBV~Category~EQ~Books~FBV~PublishedYear~GT~2000~FSF~PublishedYear~DESC~0
|
|
979
|
-
// Filters down to ALL BOOKS PUBLISHED AFTER 2000 IN DESCENDING ORDER
|
|
980
|
-
filter: false,
|
|
981
|
-
// ARR of OBJ: Data filter expression list {Column:'Name', Operator:'EQ', Value:'John', Connector:'And', Parameter:'Name'}
|
|
982
|
-
// TSQL: the WHERE clause
|
|
983
|
-
// MongoDB: a find() expression
|
|
984
|
-
|
|
985
|
-
sort: false,
|
|
986
|
-
// ARR of OBJ: The sort order {Column:'Birthday', Direction:'Ascending'}
|
|
987
|
-
// TSQL: ORDER BY
|
|
988
|
-
// MongoDB: sort()
|
|
989
|
-
|
|
990
|
-
join: false,
|
|
991
|
-
// ARR of OBJ: The join tables {Type:'INNER JOIN', Table:'test', From: 'Test.ID', To: 'Scope.IDItem' }
|
|
992
|
-
// TSQL: JOIN
|
|
993
|
-
|
|
994
|
-
// Force a specific query to run regardless of above ... this is used to override the query generator.
|
|
995
|
-
queryOverride: false,
|
|
996
|
-
// Where the generated query goes
|
|
997
|
-
query: false,
|
|
998
|
-
/*
|
|
999
|
-
{
|
|
1000
|
-
body: false,
|
|
1001
|
-
schema: false, // The schema to intersect with our records
|
|
1002
|
-
IDUser: 0, // The User ID to stamp into records
|
|
1003
|
-
UUID: A_UUID, // Some globally unique record id, different per cloned query.
|
|
1004
|
-
records: false, // The records to be created or changed
|
|
1005
|
-
parameters: {}
|
|
1006
|
-
}
|
|
1007
|
-
*/
|
|
1008
|
-
|
|
1009
|
-
// Who is making the query
|
|
1010
|
-
userID: 0,
|
|
1011
|
-
// Where the query results are stuck
|
|
1012
|
-
result: false
|
|
1013
|
-
/*
|
|
1014
|
-
{
|
|
1015
|
-
executed: false, // True once we've run a query.
|
|
1016
|
-
value: false, // The return value of the last query run
|
|
1017
|
-
error: false // The error message of the last run query
|
|
1018
|
-
}
|
|
1019
|
-
*/
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
module.exports = FoxHoundQueryParameters;
|
|
1023
|
-
}, {}],
|
|
1024
|
-
5: [function (require, module, exports) {
|
|
1025
|
-
/**
|
|
1026
|
-
* FoxHound ALASQL Dialect
|
|
1027
|
-
*
|
|
1028
|
-
* @license MIT
|
|
1029
|
-
*
|
|
1030
|
-
* For an ALASQL query override:
|
|
1031
|
-
// An underscore template with the following values:
|
|
1032
|
-
// <%= DataElements %> = Field1, Field2, Field3, Field4
|
|
1033
|
-
// <%= Begin %> = 0
|
|
1034
|
-
// <%= Cap %> = 10
|
|
1035
|
-
// <%= Filter %> = WHERE StartDate > :MyStartDate
|
|
1036
|
-
// <%= Sort %> = ORDER BY Field1
|
|
1037
|
-
// The values are empty strings if they aren't set.
|
|
1038
|
-
*
|
|
1039
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
1040
|
-
* @class FoxHoundDialectALASQL
|
|
1041
|
-
*/
|
|
1042
|
-
|
|
1043
|
-
var FoxHoundDialectALASQL = function (pFable) {
|
|
1044
|
-
//Request time from SQL server with microseconds resolution
|
|
1045
|
-
const SQL_NOW = "NOW(3)";
|
|
1046
|
-
_Fable = pFable;
|
|
1047
|
-
|
|
1048
|
-
/**
|
|
1049
|
-
* Generate a table name from the scope.
|
|
1050
|
-
*
|
|
1051
|
-
* Because ALASQL is all in-memory, and can be run in two modes (anonymous
|
|
1052
|
-
* working on arrays or table-based) we are going to make this a programmable
|
|
1053
|
-
* value. Then we can share the code across both providers.
|
|
1054
|
-
*
|
|
1055
|
-
* @method: generateTableName
|
|
1056
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1057
|
-
* @return: {String} Returns the table name clause
|
|
1058
|
-
*/
|
|
1059
|
-
var generateTableName = function (pParameters) {
|
|
1060
|
-
return ' ' + pParameters.scope;
|
|
1061
|
-
};
|
|
1062
|
-
|
|
1063
|
-
/**
|
|
1064
|
-
* Escape columns, because ALASQL has more reserved KWs than most SQL dialects
|
|
1065
|
-
*/
|
|
1066
|
-
var escapeColumn = (pColumn, pParameters) => {
|
|
1067
|
-
if (pColumn.indexOf('.') < 0) {
|
|
1068
|
-
return '`' + pColumn + '`';
|
|
1069
|
-
} else {
|
|
1070
|
-
// This could suck if the scope is not the same
|
|
1071
|
-
var tmpTableName = pParameters.scope;
|
|
1072
|
-
if (pColumn.indexOf(tmpTableName + '.') > -1) {
|
|
1073
|
-
return '`' + pColumn.replace(tmpTableName + '.', '') + '`';
|
|
1074
|
-
} else {
|
|
1075
|
-
// This doesn't work well but we'll try it.
|
|
1076
|
-
return '`' + pColumn + '`';
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
};
|
|
1080
|
-
|
|
1081
|
-
/**
|
|
1082
|
-
* Generate a field list from the array of dataElements
|
|
1083
|
-
*
|
|
1084
|
-
* Each entry in the dataElements is a simple string
|
|
1085
|
-
*
|
|
1086
|
-
* @method: generateFieldList
|
|
1087
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1088
|
-
* @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
|
|
1089
|
-
* @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
|
|
1090
|
-
* due to missing schema.
|
|
1091
|
-
*/
|
|
1092
|
-
var generateFieldList = function (pParameters, pIsForCountClause) {
|
|
1093
|
-
var tmpDataElements = pParameters.dataElements;
|
|
1094
|
-
if (!Array.isArray(tmpDataElements) || tmpDataElements.length < 1) {
|
|
1095
|
-
if (!pIsForCountClause) {
|
|
1096
|
-
return ' *';
|
|
1097
|
-
}
|
|
1098
|
-
// we need to list all of the table fields explicitly; get them from the schema
|
|
1099
|
-
const tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1100
|
-
if (tmpSchema.length < 1) {
|
|
1101
|
-
// this means we have no schema; returning an empty string here signals the calling code to handle this case
|
|
1102
|
-
return '';
|
|
1103
|
-
}
|
|
1104
|
-
const idColumn = tmpSchema.find(entry => entry.Type === 'AutoIdentity');
|
|
1105
|
-
if (!idColumn) {
|
|
1106
|
-
// this means there is no autoincrementing unique ID column; treat as above
|
|
1107
|
-
return '';
|
|
1108
|
-
}
|
|
1109
|
-
return ` ${idColumn.Column}`;
|
|
1110
|
-
}
|
|
1111
|
-
var tmpFieldList = ' ';
|
|
1112
|
-
for (var i = 0; i < tmpDataElements.length; i++) {
|
|
1113
|
-
if (i > 0) {
|
|
1114
|
-
tmpFieldList += ', ';
|
|
1115
|
-
}
|
|
1116
|
-
tmpFieldList += escapeColumn(tmpDataElements[i], pParameters);
|
|
1117
|
-
}
|
|
1118
|
-
return tmpFieldList;
|
|
1119
|
-
};
|
|
1120
|
-
|
|
1121
|
-
/**
|
|
1122
|
-
* Generate a query from the array of where clauses
|
|
1123
|
-
*
|
|
1124
|
-
* Each clause is an object like:
|
|
1125
|
-
{
|
|
1126
|
-
Column:'Name',
|
|
1127
|
-
Operator:'EQ',
|
|
1128
|
-
Value:'John',
|
|
1129
|
-
Connector:'And',
|
|
1130
|
-
Parameter:'Name'
|
|
1131
|
-
}
|
|
1132
|
-
*
|
|
1133
|
-
* @method: generateWhere
|
|
1134
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1135
|
-
* @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
|
|
1136
|
-
*/
|
|
1137
|
-
var generateWhere = function (pParameters) {
|
|
1138
|
-
var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
|
|
1139
|
-
var tmpTableName = generateTableName(pParameters).trim();
|
|
1140
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
1141
|
-
// Check if there is a Deleted column on the Schema. If so, we add this to the filters automatically (if not already present)
|
|
1142
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1143
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1144
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1145
|
-
var tmpSchemaEntry = tmpSchema[i];
|
|
1146
|
-
if (tmpSchemaEntry.Type === 'Deleted') {
|
|
1147
|
-
var tmpHasDeletedParameter = false;
|
|
1148
|
-
|
|
1149
|
-
//first, check to see if filters are already looking for Deleted column
|
|
1150
|
-
if (tmpFilter.length > 0) {
|
|
1151
|
-
for (var x = 0; x < tmpFilter.length; x++) {
|
|
1152
|
-
if (tmpFilter[x].Column === tmpSchemaEntry.Column) {
|
|
1153
|
-
tmpHasDeletedParameter = true;
|
|
1154
|
-
break;
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
}
|
|
1158
|
-
if (!tmpHasDeletedParameter) {
|
|
1159
|
-
//if not, we need to add it
|
|
1160
|
-
tmpFilter.push({
|
|
1161
|
-
Column: tmpTableName + '.' + tmpSchemaEntry.Column,
|
|
1162
|
-
Operator: '=',
|
|
1163
|
-
Value: 0,
|
|
1164
|
-
Connector: 'AND',
|
|
1165
|
-
Parameter: 'Deleted'
|
|
1166
|
-
});
|
|
1167
|
-
}
|
|
1168
|
-
break;
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
if (tmpFilter.length < 1) {
|
|
1173
|
-
return '';
|
|
1174
|
-
}
|
|
1175
|
-
var tmpWhere = ' WHERE';
|
|
1176
|
-
|
|
1177
|
-
// This is used to disable the connectors for subsequent queries.
|
|
1178
|
-
// Only the open parenthesis operator uses this, currently.
|
|
1179
|
-
var tmpLastOperatorNoConnector = false;
|
|
1180
|
-
for (var i = 0; i < tmpFilter.length; i++) {
|
|
1181
|
-
if (tmpFilter[i].Connector != 'NONE' && tmpFilter[i].Operator != ')' && tmpWhere != ' WHERE' && tmpLastOperatorNoConnector == false) {
|
|
1182
|
-
tmpWhere += ' ' + tmpFilter[i].Connector;
|
|
1183
|
-
}
|
|
1184
|
-
tmpLastOperatorNoConnector = false;
|
|
1185
|
-
var tmpColumnParameter;
|
|
1186
|
-
if (tmpFilter[i].Operator === '(') {
|
|
1187
|
-
// Open a logical grouping
|
|
1188
|
-
tmpWhere += ' (';
|
|
1189
|
-
tmpLastOperatorNoConnector = true;
|
|
1190
|
-
} else if (tmpFilter[i].Operator === ')') {
|
|
1191
|
-
// Close a logical grouping
|
|
1192
|
-
tmpWhere += ' )';
|
|
1193
|
-
} else if (tmpFilter[i].Operator === 'IN') {
|
|
1194
|
-
tmpColumnParameter = tmpFilter[i].Parameter + '_w' + i;
|
|
1195
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
1196
|
-
tmpWhere += ' ' + escapeColumn(tmpFilter[i].Column, pParameters) + ' ' + tmpFilter[i].Operator + ' ( :' + tmpColumnParameter + ' )';
|
|
1197
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpFilter[i].Value;
|
|
1198
|
-
} else if (tmpFilter[i].Operator === 'IS NOT NULL') {
|
|
1199
|
-
// IS NOT NULL is a special operator which doesn't require a value, or parameter
|
|
1200
|
-
tmpWhere += ' ' + escapeColumn(tmpFilter[i].Column, pParameters) + ' ' + tmpFilter[i].Operator;
|
|
1201
|
-
} else {
|
|
1202
|
-
tmpColumnParameter = tmpFilter[i].Parameter + '_w' + i;
|
|
1203
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
1204
|
-
tmpWhere += ' ' + escapeColumn(tmpFilter[i].Column, pParameters) + ' ' + tmpFilter[i].Operator + ' :' + tmpColumnParameter;
|
|
1205
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpFilter[i].Value;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
return tmpWhere;
|
|
1209
|
-
};
|
|
1210
|
-
|
|
1211
|
-
/**
|
|
1212
|
-
* Generate an ORDER BY clause from the sort array
|
|
1213
|
-
*
|
|
1214
|
-
* Each entry in the sort is an object like:
|
|
1215
|
-
* {Column:'Color',Direction:'Descending'}
|
|
1216
|
-
*
|
|
1217
|
-
* @method: generateOrderBy
|
|
1218
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1219
|
-
* @return: {String} Returns the field list clause
|
|
1220
|
-
*/
|
|
1221
|
-
var generateOrderBy = function (pParameters) {
|
|
1222
|
-
var tmpOrderBy = pParameters.sort;
|
|
1223
|
-
if (!Array.isArray(tmpOrderBy) || tmpOrderBy.length < 1) {
|
|
1224
|
-
return '';
|
|
1225
|
-
}
|
|
1226
|
-
var tmpOrderClause = ' ORDER BY';
|
|
1227
|
-
for (var i = 0; i < tmpOrderBy.length; i++) {
|
|
1228
|
-
if (i > 0) {
|
|
1229
|
-
tmpOrderClause += ',';
|
|
1230
|
-
}
|
|
1231
|
-
tmpOrderClause += ' ' + escapeColumn(tmpOrderBy[i].Column, pParameters);
|
|
1232
|
-
if (tmpOrderBy[i].Direction == 'Descending') {
|
|
1233
|
-
tmpOrderClause += ' DESC';
|
|
1234
|
-
}
|
|
1235
|
-
}
|
|
1236
|
-
return tmpOrderClause;
|
|
1237
|
-
};
|
|
1238
|
-
|
|
1239
|
-
/**
|
|
1240
|
-
* Generate the limit clause
|
|
1241
|
-
*
|
|
1242
|
-
* @method: generateLimit
|
|
1243
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1244
|
-
* @return: {String} Returns the table name clause
|
|
1245
|
-
*/
|
|
1246
|
-
var generateLimit = function (pParameters) {
|
|
1247
|
-
if (!pParameters.cap) {
|
|
1248
|
-
return '';
|
|
1249
|
-
}
|
|
1250
|
-
var tmpLimit = ' LIMIT';
|
|
1251
|
-
// Cap is required for a limit clause.
|
|
1252
|
-
tmpLimit += ' ' + pParameters.cap;
|
|
1253
|
-
|
|
1254
|
-
// If there is a begin record, we'll pass that in as well.
|
|
1255
|
-
if (pParameters.begin !== false) {
|
|
1256
|
-
tmpLimit += ' FETCH ' + pParameters.begin;
|
|
1257
|
-
}
|
|
1258
|
-
return tmpLimit;
|
|
1259
|
-
};
|
|
1260
|
-
|
|
1261
|
-
/**
|
|
1262
|
-
* Generate the update SET clause
|
|
1263
|
-
*
|
|
1264
|
-
* @method: generateUpdateSetters
|
|
1265
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1266
|
-
* @return: {String} Returns the table name clause
|
|
1267
|
-
*/
|
|
1268
|
-
var generateUpdateSetters = function (pParameters) {
|
|
1269
|
-
var tmpRecords = pParameters.query.records;
|
|
1270
|
-
// We need to tell the query not to generate improperly if there are no values to set.
|
|
1271
|
-
if (!Array.isArray(tmpRecords) || tmpRecords.length < 1) {
|
|
1272
|
-
return false;
|
|
1273
|
-
}
|
|
1274
|
-
|
|
1275
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
1276
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1277
|
-
var tmpUpdate = '';
|
|
1278
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
1279
|
-
var tmpCurrentColumn = 0;
|
|
1280
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
1281
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
1282
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
1283
|
-
var tmpSchemaEntry = {
|
|
1284
|
-
Column: tmpColumn,
|
|
1285
|
-
Type: 'Default'
|
|
1286
|
-
};
|
|
1287
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1288
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
1289
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1290
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
1291
|
-
break;
|
|
1292
|
-
}
|
|
1293
|
-
}
|
|
1294
|
-
if (pParameters.query.disableAutoDateStamp && tmpSchemaEntry.Type === 'UpdateDate') {
|
|
1295
|
-
// This is ignored if flag is set
|
|
1296
|
-
continue;
|
|
1297
|
-
}
|
|
1298
|
-
if (pParameters.query.disableAutoUserStamp && tmpSchemaEntry.Type === 'UpdateIDUser') {
|
|
1299
|
-
// This is ignored if flag is set
|
|
1300
|
-
continue;
|
|
1301
|
-
}
|
|
1302
|
-
switch (tmpSchemaEntry.Type) {
|
|
1303
|
-
case 'AutoIdentity':
|
|
1304
|
-
case 'CreateDate':
|
|
1305
|
-
case 'CreateIDUser':
|
|
1306
|
-
case 'DeleteDate':
|
|
1307
|
-
case 'DeleteIDUser':
|
|
1308
|
-
// These are all ignored on update
|
|
1309
|
-
continue;
|
|
1310
|
-
}
|
|
1311
|
-
if (tmpCurrentColumn > 0) {
|
|
1312
|
-
tmpUpdate += ',';
|
|
1313
|
-
}
|
|
1314
|
-
switch (tmpSchemaEntry.Type) {
|
|
1315
|
-
case 'UpdateDate':
|
|
1316
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
1317
|
-
tmpUpdate += ' ' + escapeColumn(tmpColumn, pParameters) + ' = NOW()';
|
|
1318
|
-
break;
|
|
1319
|
-
case 'UpdateIDUser':
|
|
1320
|
-
// This is the user ID, which we hope is in the query.
|
|
1321
|
-
// This is how to deal with a normal column
|
|
1322
|
-
var tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
1323
|
-
tmpUpdate += ' ' + escapeColumn(tmpColumn, pParameters) + ' = :' + tmpColumnParameter;
|
|
1324
|
-
// Set the query parameter
|
|
1325
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
1326
|
-
break;
|
|
1327
|
-
default:
|
|
1328
|
-
var tmpColumnDefaultParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
1329
|
-
tmpUpdate += ' ' + escapeColumn(tmpColumn, pParameters) + ' = :' + tmpColumnDefaultParameter;
|
|
1330
|
-
|
|
1331
|
-
// Set the query parameter
|
|
1332
|
-
pParameters.query.parameters[tmpColumnDefaultParameter] = tmpRecords[0][tmpColumn];
|
|
1333
|
-
break;
|
|
1334
|
-
}
|
|
1335
|
-
|
|
1336
|
-
// We use a number to make sure parameters are unique.
|
|
1337
|
-
tmpCurrentColumn++;
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
1341
|
-
if (tmpUpdate === '') {
|
|
1342
|
-
return false;
|
|
1343
|
-
}
|
|
1344
|
-
return tmpUpdate;
|
|
1345
|
-
};
|
|
1346
|
-
|
|
1347
|
-
/**
|
|
1348
|
-
* Generate the update-delete SET clause
|
|
1349
|
-
*
|
|
1350
|
-
* @method: generateUpdateDeleteSetters
|
|
1351
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1352
|
-
* @return: {String} Returns the table name clause
|
|
1353
|
-
*/
|
|
1354
|
-
var generateUpdateDeleteSetters = function (pParameters) {
|
|
1355
|
-
if (pParameters.query.disableDeleteTracking) {
|
|
1356
|
-
//Don't generate an UPDATE query if Delete tracking is disabled
|
|
1357
|
-
return false;
|
|
1358
|
-
}
|
|
1359
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
1360
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1361
|
-
var tmpCurrentColumn = 0;
|
|
1362
|
-
var tmpHasDeletedField = false;
|
|
1363
|
-
var tmpUpdate = '';
|
|
1364
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
1365
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
1366
|
-
var tmpSchemaEntry = {
|
|
1367
|
-
Type: 'Default'
|
|
1368
|
-
};
|
|
1369
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1370
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1371
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
1372
|
-
var tmpUpdateSql = null;
|
|
1373
|
-
switch (tmpSchemaEntry.Type) {
|
|
1374
|
-
case 'Deleted':
|
|
1375
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = 1';
|
|
1376
|
-
tmpHasDeletedField = true; //this field is required in order for query to be built
|
|
1377
|
-
break;
|
|
1378
|
-
case 'DeleteDate':
|
|
1379
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = NOW()';
|
|
1380
|
-
break;
|
|
1381
|
-
case 'UpdateDate':
|
|
1382
|
-
// Delete operation is an Update, so we should stamp the update time
|
|
1383
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = NOW()';
|
|
1384
|
-
break;
|
|
1385
|
-
case 'DeleteIDUser':
|
|
1386
|
-
// This is the user ID, which we hope is in the query.
|
|
1387
|
-
// This is how to deal with a normal column
|
|
1388
|
-
var tmpColumnParameter = tmpSchemaEntry.Column + '_' + tmpCurrentColumn;
|
|
1389
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = :' + tmpColumnParameter;
|
|
1390
|
-
// Set the query parameter
|
|
1391
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
1392
|
-
break;
|
|
1393
|
-
default:
|
|
1394
|
-
//DON'T allow update of other fields in this query
|
|
1395
|
-
continue;
|
|
1396
|
-
}
|
|
1397
|
-
if (tmpCurrentColumn > 0) {
|
|
1398
|
-
tmpUpdate += ',';
|
|
1399
|
-
}
|
|
1400
|
-
tmpUpdate += tmpUpdateSql;
|
|
1401
|
-
|
|
1402
|
-
// We use a number to make sure parameters are unique.
|
|
1403
|
-
tmpCurrentColumn++;
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
1407
|
-
if (!tmpHasDeletedField || tmpUpdate === '') {
|
|
1408
|
-
return false;
|
|
1409
|
-
}
|
|
1410
|
-
return tmpUpdate;
|
|
1411
|
-
};
|
|
1412
|
-
|
|
1413
|
-
/**
|
|
1414
|
-
* Generate the update-delete SET clause
|
|
1415
|
-
*
|
|
1416
|
-
* @method: generateUpdateDeleteSetters
|
|
1417
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1418
|
-
* @return: {String} Returns the table name clause
|
|
1419
|
-
*/
|
|
1420
|
-
var generateUpdateUndeleteSetters = function (pParameters) {
|
|
1421
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
1422
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1423
|
-
var tmpCurrentColumn = 0;
|
|
1424
|
-
var tmpHasDeletedField = false;
|
|
1425
|
-
var tmpUpdate = '';
|
|
1426
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
1427
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
1428
|
-
var tmpSchemaEntry = {
|
|
1429
|
-
Type: 'Default'
|
|
1430
|
-
};
|
|
1431
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1432
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1433
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
1434
|
-
var tmpUpdateSql = null;
|
|
1435
|
-
switch (tmpSchemaEntry.Type) {
|
|
1436
|
-
case 'Deleted':
|
|
1437
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = 0';
|
|
1438
|
-
tmpHasDeletedField = true; //this field is required in order for query to be built
|
|
1439
|
-
break;
|
|
1440
|
-
case 'UpdateDate':
|
|
1441
|
-
// Delete operation is an Update, so we should stamp the update time
|
|
1442
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = NOW()';
|
|
1443
|
-
break;
|
|
1444
|
-
case 'UpdateIDUser':
|
|
1445
|
-
// This is the user ID, which we hope is in the query.
|
|
1446
|
-
// This is how to deal with a normal column
|
|
1447
|
-
var tmpColumnParameter = tmpSchemaEntry.Column + '_' + tmpCurrentColumn;
|
|
1448
|
-
tmpUpdateSql = ' ' + escapeColumn(tmpSchemaEntry.Column, pParameters) + ' = :' + tmpColumnParameter;
|
|
1449
|
-
// Set the query parameter
|
|
1450
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
1451
|
-
break;
|
|
1452
|
-
default:
|
|
1453
|
-
//DON'T allow update of other fields in this query
|
|
1454
|
-
continue;
|
|
1455
|
-
}
|
|
1456
|
-
if (tmpCurrentColumn > 0) {
|
|
1457
|
-
tmpUpdate += ',';
|
|
1458
|
-
}
|
|
1459
|
-
tmpUpdate += tmpUpdateSql;
|
|
1460
|
-
|
|
1461
|
-
// We use a number to make sure parameters are unique.
|
|
1462
|
-
tmpCurrentColumn++;
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
1466
|
-
if (!tmpHasDeletedField || tmpUpdate === '') {
|
|
1467
|
-
return false;
|
|
1468
|
-
}
|
|
1469
|
-
return tmpUpdate;
|
|
1470
|
-
};
|
|
1471
|
-
|
|
1472
|
-
/**
|
|
1473
|
-
* Generate the create SET clause
|
|
1474
|
-
*
|
|
1475
|
-
* @method: generateCreateSetList
|
|
1476
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1477
|
-
* @return: {String} Returns the table name clause
|
|
1478
|
-
*/
|
|
1479
|
-
var generateCreateSetValues = function (pParameters) {
|
|
1480
|
-
var tmpRecords = pParameters.query.records;
|
|
1481
|
-
// We need to tell the query not to generate improperly if there are no values to set.
|
|
1482
|
-
if (!Array.isArray(tmpRecords) || tmpRecords.length < 1) {
|
|
1483
|
-
return false;
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
1487
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1488
|
-
var tmpCreateSet = '';
|
|
1489
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
1490
|
-
var tmpCurrentColumn = 0;
|
|
1491
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
1492
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
1493
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
1494
|
-
var tmpSchemaEntry = {
|
|
1495
|
-
Column: tmpColumn,
|
|
1496
|
-
Type: 'Default'
|
|
1497
|
-
};
|
|
1498
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1499
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
1500
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1501
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
1502
|
-
break;
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
1506
|
-
if (tmpSchemaEntry.Type === 'DeleteDate' || tmpSchemaEntry.Type === 'DeleteIDUser') {
|
|
1507
|
-
// These are all ignored on insert (if delete tracking is enabled as normal)
|
|
1508
|
-
continue;
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
if (tmpCurrentColumn > 0) {
|
|
1512
|
-
tmpCreateSet += ',';
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
//define a re-usable method for setting up field definitions in a default pattern
|
|
1516
|
-
var buildDefaultDefinition = function () {
|
|
1517
|
-
var tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
1518
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
1519
|
-
// Set the query parameter
|
|
1520
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpRecords[0][tmpColumn];
|
|
1521
|
-
};
|
|
1522
|
-
var tmpColumnParameter;
|
|
1523
|
-
switch (tmpSchemaEntry.Type) {
|
|
1524
|
-
case 'AutoIdentity':
|
|
1525
|
-
if (pParameters.query.disableAutoIdentity) {
|
|
1526
|
-
buildDefaultDefinition();
|
|
1527
|
-
} else {
|
|
1528
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
1529
|
-
tmpCreateSet += ' NULL';
|
|
1530
|
-
}
|
|
1531
|
-
break;
|
|
1532
|
-
case 'AutoGUID':
|
|
1533
|
-
if (pParameters.query.disableAutoIdentity) {
|
|
1534
|
-
buildDefaultDefinition();
|
|
1535
|
-
} else if (tmpRecords[0][tmpColumn] && tmpRecords[0][tmpColumn].length >= 5 && tmpRecords[0][tmpColumn] !== '0x0000000000000000')
|
|
1536
|
-
//stricture default
|
|
1537
|
-
{
|
|
1538
|
-
// Allow consumer to override AutoGUID
|
|
1539
|
-
buildDefaultDefinition();
|
|
1540
|
-
} else {
|
|
1541
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
1542
|
-
tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
1543
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
1544
|
-
// Set the query parameter
|
|
1545
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.UUID;
|
|
1546
|
-
}
|
|
1547
|
-
break;
|
|
1548
|
-
case 'UpdateDate':
|
|
1549
|
-
case 'CreateDate':
|
|
1550
|
-
case 'DeleteDate':
|
|
1551
|
-
if (pParameters.query.disableAutoDateStamp) {
|
|
1552
|
-
buildDefaultDefinition();
|
|
1553
|
-
} else {
|
|
1554
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
1555
|
-
tmpCreateSet += ' NOW()';
|
|
1556
|
-
}
|
|
1557
|
-
break;
|
|
1558
|
-
case 'UpdateIDUser':
|
|
1559
|
-
case 'CreateIDUser':
|
|
1560
|
-
case 'DeleteIDUser':
|
|
1561
|
-
if (pParameters.query.disableAutoUserStamp) {
|
|
1562
|
-
buildDefaultDefinition();
|
|
1563
|
-
} else {
|
|
1564
|
-
// This is the user ID, which we hope is in the query.
|
|
1565
|
-
// This is how to deal with a normal column
|
|
1566
|
-
tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
1567
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
1568
|
-
// Set the query parameter
|
|
1569
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
1570
|
-
}
|
|
1571
|
-
break;
|
|
1572
|
-
default:
|
|
1573
|
-
buildDefaultDefinition();
|
|
1574
|
-
break;
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
// We use an appended number to make sure parameters are unique.
|
|
1578
|
-
tmpCurrentColumn++;
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
1582
|
-
if (tmpCreateSet === '') {
|
|
1583
|
-
return false;
|
|
1584
|
-
}
|
|
1585
|
-
return tmpCreateSet;
|
|
1586
|
-
};
|
|
1587
|
-
|
|
1588
|
-
/**
|
|
1589
|
-
* Generate the create SET clause
|
|
1590
|
-
*
|
|
1591
|
-
* @method: generateCreateSetList
|
|
1592
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1593
|
-
* @return: {String} Returns the table name clause
|
|
1594
|
-
*/
|
|
1595
|
-
var generateCreateSetList = function (pParameters) {
|
|
1596
|
-
// The records were already validated by generateCreateSetValues
|
|
1597
|
-
var tmpRecords = pParameters.query.records;
|
|
1598
|
-
|
|
1599
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
1600
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
1601
|
-
var tmpCreateSet = '';
|
|
1602
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
1603
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
1604
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
1605
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
1606
|
-
var tmpSchemaEntry = {
|
|
1607
|
-
Column: tmpColumn,
|
|
1608
|
-
Type: 'Default'
|
|
1609
|
-
};
|
|
1610
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
1611
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
1612
|
-
// There is a schema entry for it. Process it accordingly.
|
|
1613
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
1614
|
-
break;
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
1618
|
-
if (tmpSchemaEntry.Type === 'DeleteDate' || tmpSchemaEntry.Type === 'DeleteIDUser') {
|
|
1619
|
-
// These are all ignored on insert (if delete tracking is enabled as normal)
|
|
1620
|
-
continue;
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
switch (tmpSchemaEntry.Type) {
|
|
1624
|
-
default:
|
|
1625
|
-
if (tmpCreateSet != '') {
|
|
1626
|
-
tmpCreateSet += ',';
|
|
1627
|
-
}
|
|
1628
|
-
tmpCreateSet += ' ' + escapeColumn(tmpColumn, pParameters);
|
|
1629
|
-
break;
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
return tmpCreateSet;
|
|
1633
|
-
};
|
|
1634
|
-
var Create = function (pParameters) {
|
|
1635
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1636
|
-
var tmpCreateSetList = generateCreateSetList(pParameters);
|
|
1637
|
-
var tmpCreateSetValues = generateCreateSetValues(pParameters);
|
|
1638
|
-
if (!tmpCreateSetValues) {
|
|
1639
|
-
return false;
|
|
1640
|
-
}
|
|
1641
|
-
return 'INSERT INTO' + tmpTableName + ' (' + tmpCreateSetList + ') VALUES (' + tmpCreateSetValues + ');';
|
|
1642
|
-
};
|
|
1643
|
-
|
|
1644
|
-
/**
|
|
1645
|
-
* Read one or many records
|
|
1646
|
-
*
|
|
1647
|
-
* Some examples:
|
|
1648
|
-
* SELECT * FROM WIDGETS;
|
|
1649
|
-
* SELECT * FROM WIDGETS LIMIT 0, 20;
|
|
1650
|
-
* SELECT * FROM WIDGETS LIMIT 5, 20;
|
|
1651
|
-
* SELECT ID, Name, Cost FROM WIDGETS LIMIT 5, 20;
|
|
1652
|
-
* SELECT ID, Name, Cost FROM WIDGETS LIMIT 5, 20 WHERE LastName = 'Smith';
|
|
1653
|
-
*
|
|
1654
|
-
* @method Read
|
|
1655
|
-
* @param {Object} pParameters SQL Query parameters
|
|
1656
|
-
* @return {String} Returns the current Query for chaining.
|
|
1657
|
-
*/
|
|
1658
|
-
var Read = function (pParameters) {
|
|
1659
|
-
var tmpFieldList = generateFieldList(pParameters);
|
|
1660
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1661
|
-
var tmpWhere = generateWhere(pParameters);
|
|
1662
|
-
var tmpOrderBy = generateOrderBy(pParameters);
|
|
1663
|
-
var tmpLimit = generateLimit(pParameters);
|
|
1664
|
-
const tmpOptDistinct = pParameters.distinct ? ' DISTINCT' : '';
|
|
1665
|
-
if (pParameters.queryOverride) {
|
|
1666
|
-
try {
|
|
1667
|
-
var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
|
|
1668
|
-
return tmpQueryTemplate({
|
|
1669
|
-
FieldList: tmpFieldList,
|
|
1670
|
-
TableName: tmpTableName,
|
|
1671
|
-
Where: tmpWhere,
|
|
1672
|
-
OrderBy: tmpOrderBy,
|
|
1673
|
-
Limit: tmpLimit,
|
|
1674
|
-
Distinct: tmpOptDistinct,
|
|
1675
|
-
_Params: pParameters
|
|
1676
|
-
});
|
|
1677
|
-
} catch (pError) {
|
|
1678
|
-
// This pokemon is here to give us a convenient way of not throwing up totally if the query fails.
|
|
1679
|
-
console.log('Error with custom Read Query [' + pParameters.queryOverride + ']: ' + pError);
|
|
1680
|
-
return false;
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
|
|
1684
|
-
};
|
|
1685
|
-
var Update = function (pParameters) {
|
|
1686
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1687
|
-
var tmpWhere = generateWhere(pParameters);
|
|
1688
|
-
var tmpUpdateSetters = generateUpdateSetters(pParameters);
|
|
1689
|
-
if (!tmpUpdateSetters) {
|
|
1690
|
-
return false;
|
|
1691
|
-
}
|
|
1692
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateSetters + tmpWhere + ';';
|
|
1693
|
-
};
|
|
1694
|
-
var Delete = function (pParameters) {
|
|
1695
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1696
|
-
var tmpWhere = generateWhere(pParameters);
|
|
1697
|
-
var tmpUpdateDeleteSetters = generateUpdateDeleteSetters(pParameters);
|
|
1698
|
-
if (tmpUpdateDeleteSetters) {
|
|
1699
|
-
//If it has a deleted bit, update it instead of actually deleting the record
|
|
1700
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateDeleteSetters + tmpWhere + ';';
|
|
1701
|
-
} else {
|
|
1702
|
-
return 'DELETE FROM' + tmpTableName + tmpWhere + ';';
|
|
1703
|
-
}
|
|
1704
|
-
};
|
|
1705
|
-
var Undelete = function (pParameters) {
|
|
1706
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1707
|
-
let tmpDeleteTrackingState = pParameters.query.disableDeleteTracking;
|
|
1708
|
-
pParameters.query.disableDeleteTracking = true;
|
|
1709
|
-
var tmpWhere = generateWhere(pParameters);
|
|
1710
|
-
var tmpUpdateUndeleteSetters = generateUpdateUndeleteSetters(pParameters);
|
|
1711
|
-
pParameters.query.disableDeleteTracking = tmpDeleteTrackingState;
|
|
1712
|
-
if (tmpUpdateUndeleteSetters) {
|
|
1713
|
-
//If it has a deleted bit, update it instead of actually deleting the record
|
|
1714
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateUndeleteSetters + tmpWhere + ';';
|
|
1715
|
-
} else {
|
|
1716
|
-
return 'SELECT NULL;';
|
|
1717
|
-
}
|
|
1718
|
-
};
|
|
1719
|
-
var Count = function (pParameters) {
|
|
1720
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1721
|
-
var tmpWhere = generateWhere(pParameters);
|
|
1722
|
-
const tmpFieldList = pParameters.distinct ? generateFieldList(pParameters, true) : '*';
|
|
1723
|
-
|
|
1724
|
-
// here, we ignore the distinct keyword if no fields have been specified and
|
|
1725
|
-
if (pParameters.distinct && tmpFieldList.length < 1) {
|
|
1726
|
-
console.warn('Distinct requested but no field list or schema are available, so not honoring distinct for count query.');
|
|
1727
|
-
}
|
|
1728
|
-
const tmpOptDistinct = pParameters.distinct && tmpFieldList.length > 0 ? 'DISTINCT' : '';
|
|
1729
|
-
if (pParameters.queryOverride) {
|
|
1730
|
-
try {
|
|
1731
|
-
var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
|
|
1732
|
-
return tmpQueryTemplate({
|
|
1733
|
-
FieldList: [],
|
|
1734
|
-
TableName: tmpTableName,
|
|
1735
|
-
Where: tmpWhere,
|
|
1736
|
-
OrderBy: '',
|
|
1737
|
-
Limit: '',
|
|
1738
|
-
Distinct: tmpOptDistinct,
|
|
1739
|
-
_Params: pParameters
|
|
1740
|
-
});
|
|
1741
|
-
} catch (pError) {
|
|
1742
|
-
// This pokemon is here to give us a convenient way of not throwing up totally if the query fails.
|
|
1743
|
-
console.log('Error with custom Count Query [' + pParameters.queryOverride + ']: ' + pError);
|
|
1744
|
-
return false;
|
|
1745
|
-
}
|
|
1746
|
-
}
|
|
1747
|
-
return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS RowCount FROM${tmpTableName}${tmpWhere};`;
|
|
1748
|
-
};
|
|
1749
|
-
var tmpDialect = {
|
|
1750
|
-
Create: Create,
|
|
1751
|
-
Read: Read,
|
|
1752
|
-
Update: Update,
|
|
1753
|
-
Delete: Delete,
|
|
1754
|
-
Undelete: Undelete,
|
|
1755
|
-
Count: Count
|
|
1756
|
-
};
|
|
1757
|
-
|
|
1758
|
-
/**
|
|
1759
|
-
* Dialect Name
|
|
1760
|
-
*
|
|
1761
|
-
* @property name
|
|
1762
|
-
* @type string
|
|
1763
|
-
*/
|
|
1764
|
-
Object.defineProperty(tmpDialect, 'name', {
|
|
1765
|
-
get: function () {
|
|
1766
|
-
return 'ALASQL';
|
|
1767
|
-
},
|
|
1768
|
-
enumerable: true
|
|
1769
|
-
});
|
|
1770
|
-
return tmpDialect;
|
|
1771
|
-
};
|
|
1772
|
-
module.exports = FoxHoundDialectALASQL;
|
|
1773
|
-
}, {}],
|
|
1774
|
-
6: [function (require, module, exports) {
|
|
1775
|
-
/**
|
|
1776
|
-
* FoxHound English Dialect
|
|
1777
|
-
*
|
|
1778
|
-
* Because if I can't ask for it in my native tongue, how am I going to ask a
|
|
1779
|
-
* complicated server for it?
|
|
1780
|
-
*
|
|
1781
|
-
* @license MIT
|
|
1782
|
-
*
|
|
1783
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
1784
|
-
* @class FoxHoundDialectEnglish
|
|
1785
|
-
*/
|
|
1786
|
-
var FoxHoundDialectEnglish = function () {
|
|
1787
|
-
var Create = function (pParameters) {
|
|
1788
|
-
var tmpScope = pParameters.scope;
|
|
1789
|
-
return 'Here is a ' + tmpScope + '.';
|
|
1790
|
-
};
|
|
1791
|
-
|
|
1792
|
-
/**
|
|
1793
|
-
* Read one or many records
|
|
1794
|
-
*
|
|
1795
|
-
* Some examples:
|
|
1796
|
-
* Please give me all your Widget records. Thanks.
|
|
1797
|
-
* Please give me 20 Widget records. Thanks.
|
|
1798
|
-
* Please give me 20 Widget records starting with record 5. Thanks.
|
|
1799
|
-
* Please give me the ID, Name and Cost of 20 Widget records starting with record 5. Thanks.
|
|
1800
|
-
* Please give me the ID and Name of 20 Widget records starting with record 5, when LastName equals "Smith". Thanks.
|
|
1801
|
-
*
|
|
1802
|
-
* @method Read
|
|
1803
|
-
* @param {Number} pLogLevel The log level for our object
|
|
1804
|
-
* @return {String} Returns the current Query for chaining.
|
|
1805
|
-
*/
|
|
1806
|
-
var Read = function (pParameters) {
|
|
1807
|
-
var tmpScope = pParameters.scope;
|
|
1808
|
-
const tmpDistinct = pParameters.distinct ? 'unique ' : '';
|
|
1809
|
-
return `Please give me all your ${tmpDistinct}${tmpScope} records. Thanks.`;
|
|
1810
|
-
};
|
|
1811
|
-
var Update = function (pParameters) {
|
|
1812
|
-
var tmpScope = pParameters.scope;
|
|
1813
|
-
return 'I am changing your ' + tmpScope + '.';
|
|
1814
|
-
};
|
|
1815
|
-
var Delete = function (pParameters) {
|
|
1816
|
-
var tmpScope = pParameters.scope;
|
|
1817
|
-
return 'I am deleting your ' + tmpScope + '.';
|
|
1818
|
-
};
|
|
1819
|
-
var Undelete = function (pParameters) {
|
|
1820
|
-
var tmpScope = pParameters.scope;
|
|
1821
|
-
return 'I am undeleting your ' + tmpScope + '.';
|
|
1822
|
-
};
|
|
1823
|
-
var Count = function (pParameters) {
|
|
1824
|
-
var tmpScope = pParameters.scope;
|
|
1825
|
-
const tmpDistinct = pParameters.distinct ? 'unique ' : '';
|
|
1826
|
-
return `Count your ${tmpDistinct}${tmpScope}.`;
|
|
1827
|
-
};
|
|
1828
|
-
var tmpDialect = {
|
|
1829
|
-
Create: Create,
|
|
1830
|
-
Read: Read,
|
|
1831
|
-
Update: Update,
|
|
1832
|
-
Delete: Delete,
|
|
1833
|
-
Undelete: Undelete,
|
|
1834
|
-
Count: Count
|
|
1835
|
-
};
|
|
1836
|
-
|
|
1837
|
-
/**
|
|
1838
|
-
* Dialect Name
|
|
1839
|
-
*
|
|
1840
|
-
* @property name
|
|
1841
|
-
* @type string
|
|
1842
|
-
*/
|
|
1843
|
-
Object.defineProperty(tmpDialect, 'name', {
|
|
1844
|
-
get: function () {
|
|
1845
|
-
return 'English';
|
|
1846
|
-
},
|
|
1847
|
-
enumerable: true
|
|
1848
|
-
});
|
|
1849
|
-
return tmpDialect;
|
|
1850
|
-
};
|
|
1851
|
-
module.exports = FoxHoundDialectEnglish;
|
|
1852
|
-
}, {}],
|
|
1853
|
-
7: [function (require, module, exports) {
|
|
1854
|
-
/**
|
|
1855
|
-
* FoxHound Meadow Endpoints Dialect
|
|
1856
|
-
*
|
|
1857
|
-
* @license MIT
|
|
1858
|
-
*
|
|
1859
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
1860
|
-
* @class FoxHoundDialectMeadowEndpoints
|
|
1861
|
-
*/
|
|
1862
|
-
|
|
1863
|
-
var FoxHoundDialectMeadowEndpoints = function () {
|
|
1864
|
-
/**
|
|
1865
|
-
* Generate a table name from the scope
|
|
1866
|
-
*
|
|
1867
|
-
* @method: generateTableName
|
|
1868
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1869
|
-
* @return: {String} Returns the table name clause
|
|
1870
|
-
*/
|
|
1871
|
-
var generateTableName = function (pParameters) {
|
|
1872
|
-
return pParameters.scope;
|
|
1873
|
-
};
|
|
1874
|
-
|
|
1875
|
-
/**
|
|
1876
|
-
* Generate the Identity column from the schema or scope
|
|
1877
|
-
*
|
|
1878
|
-
* @method: generateIdentityColumnName
|
|
1879
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1880
|
-
* @return: {String} Returns the table name clause
|
|
1881
|
-
*/
|
|
1882
|
-
var generateIdentityColumnName = function (pParameters) {
|
|
1883
|
-
// TODO: See about using the Schema or the Schemata for this
|
|
1884
|
-
return `ID${pParameters.scope}`;
|
|
1885
|
-
};
|
|
1886
|
-
|
|
1887
|
-
/**
|
|
1888
|
-
* Generate a field list from the array of dataElements
|
|
1889
|
-
*
|
|
1890
|
-
* Each entry in the dataElements is a simple string
|
|
1891
|
-
*
|
|
1892
|
-
* @method: generateFieldList
|
|
1893
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1894
|
-
* @return: {String} Returns the field list clause
|
|
1895
|
-
*/
|
|
1896
|
-
var generateFieldList = function (pParameters) {
|
|
1897
|
-
var tmpDataElements = pParameters.dataElements;
|
|
1898
|
-
if (!Array.isArray(tmpDataElements) || tmpDataElements.length < 1) {
|
|
1899
|
-
return '';
|
|
1900
|
-
}
|
|
1901
|
-
var tmpFieldList = '';
|
|
1902
|
-
for (var i = 0; i < tmpDataElements.length; i++) {
|
|
1903
|
-
if (i > 0) {
|
|
1904
|
-
tmpFieldList += ',';
|
|
1905
|
-
}
|
|
1906
|
-
tmpFieldList += tmpDataElements[i];
|
|
1907
|
-
}
|
|
1908
|
-
return tmpFieldList;
|
|
1909
|
-
};
|
|
1910
|
-
|
|
1911
|
-
/**
|
|
1912
|
-
* Generate a query from the array of where clauses
|
|
1913
|
-
*
|
|
1914
|
-
* Each clause is an object like:
|
|
1915
|
-
{
|
|
1916
|
-
Column:'Name',
|
|
1917
|
-
Operator:'EQ',
|
|
1918
|
-
Value:'John',
|
|
1919
|
-
Connector:'And',
|
|
1920
|
-
Parameter:'Name'
|
|
1921
|
-
}
|
|
1922
|
-
*
|
|
1923
|
-
* @method: generateWhere
|
|
1924
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
1925
|
-
* @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
|
|
1926
|
-
*/
|
|
1927
|
-
var generateWhere = function (pParameters) {
|
|
1928
|
-
var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
|
|
1929
|
-
var tmpTableName = generateTableName(pParameters);
|
|
1930
|
-
var tmpURL = '';
|
|
1931
|
-
let tmpfAddFilter = (pFilterCommand, pFilterParameters) => {
|
|
1932
|
-
if (tmpURL.length > 0) {
|
|
1933
|
-
tmpURL += '~';
|
|
1934
|
-
}
|
|
1935
|
-
tmpURL += `${pFilterCommand}~${pFilterParameters[0]}~${pFilterParameters[1]}~${pFilterParameters[2]}`;
|
|
1936
|
-
};
|
|
1937
|
-
let tmpfTranslateOperator = pOperator => {
|
|
1938
|
-
tmpNewOperator = 'EQ';
|
|
1939
|
-
switch (pOperator.toUpperCase()) {
|
|
1940
|
-
case '!=':
|
|
1941
|
-
tmpNewOperator = 'NE';
|
|
1942
|
-
break;
|
|
1943
|
-
case '>':
|
|
1944
|
-
tmpNewOperator = 'GT';
|
|
1945
|
-
break;
|
|
1946
|
-
case '>=':
|
|
1947
|
-
tmpNewOperator = 'GE';
|
|
1948
|
-
break;
|
|
1949
|
-
case '<=':
|
|
1950
|
-
tmpNewOperator = 'LE';
|
|
1951
|
-
break;
|
|
1952
|
-
case '<':
|
|
1953
|
-
tmpNewOperator = 'LT';
|
|
1954
|
-
break;
|
|
1955
|
-
case 'LIKE':
|
|
1956
|
-
tmpNewOperator = 'LK';
|
|
1957
|
-
break;
|
|
1958
|
-
case 'IN':
|
|
1959
|
-
tmpNewOperator = 'INN';
|
|
1960
|
-
break;
|
|
1961
|
-
case 'NOT IN':
|
|
1962
|
-
tmpNewOperator = 'NI';
|
|
1963
|
-
break;
|
|
1964
|
-
}
|
|
1965
|
-
return tmpNewOperator;
|
|
1966
|
-
};
|
|
1967
|
-
|
|
1968
|
-
// Translating Delete Tracking bit on query to a query with automagic
|
|
1969
|
-
// This will eventually deprecate this as part of the necessary query
|
|
1970
|
-
if (pParameters.query.disableDeleteTracking) {
|
|
1971
|
-
tmpfAddFilter('FBV', ['Deleted', 'GE', '0']);
|
|
1972
|
-
}
|
|
1973
|
-
for (var i = 0; i < tmpFilter.length; i++) {
|
|
1974
|
-
if (tmpFilter[i].Operator === '(') {
|
|
1975
|
-
tmpfAddFilter('FOP', ['0', '(', '0']);
|
|
1976
|
-
} else if (tmpFilter[i].Operator === ')') {
|
|
1977
|
-
// Close a logical grouping
|
|
1978
|
-
tmpfAddFilter('FCP', ['0', ')', '0']);
|
|
1979
|
-
} else if (tmpFilter[i].Operator === 'IN' || tmpFilter[i].Operator === "NOT IN") {
|
|
1980
|
-
let tmpFilterCommand = 'FBV';
|
|
1981
|
-
if (tmpFilter[i].Connector == 'OR') {
|
|
1982
|
-
tmpFilterCommand = 'FBVOR';
|
|
1983
|
-
}
|
|
1984
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
1985
|
-
tmpfAddFilter(tmpFilterCommand, [tmpFilter[i].Column, tmpfTranslateOperator(tmpFilter[i].Operator), tmpFilter[i].Value.map(encodeURIComponent).join(',')]);
|
|
1986
|
-
} else if (tmpFilter[i].Operator === 'IS NULL') {
|
|
1987
|
-
// IS NULL is a special operator which doesn't require a value, or parameter
|
|
1988
|
-
tmpfAddFilter('FBV', [tmpFilter[i].Column, 'IN', '0']);
|
|
1989
|
-
} else if (tmpFilter[i].Operator === 'IS NOT NULL') {
|
|
1990
|
-
// IS NOT NULL is a special operator which doesn't require a value, or parameter
|
|
1991
|
-
tmpfAddFilter('FBV', [tmpFilter[i].Column, 'NN', '0']);
|
|
1992
|
-
} else {
|
|
1993
|
-
let tmpFilterCommand = 'FBV';
|
|
1994
|
-
if (tmpFilter[i].Connector == 'OR') {
|
|
1995
|
-
tmpFilterCommand = 'FBVOR';
|
|
1996
|
-
}
|
|
1997
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
1998
|
-
tmpfAddFilter(tmpFilterCommand, [tmpFilter[i].Column, tmpfTranslateOperator(tmpFilter[i].Operator), encodeURIComponent(tmpFilter[i].Value)]);
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
let tmpOrderBy = generateOrderBy(pParameters);
|
|
2002
|
-
if (tmpOrderBy) {
|
|
2003
|
-
if (tmpURL) {
|
|
2004
|
-
tmpURL += '~';
|
|
2005
|
-
}
|
|
2006
|
-
tmpURL += tmpOrderBy;
|
|
2007
|
-
}
|
|
2008
|
-
return tmpURL;
|
|
2009
|
-
};
|
|
2010
|
-
|
|
2011
|
-
/**
|
|
2012
|
-
* Get the flags for the request
|
|
2013
|
-
*
|
|
2014
|
-
* These are usually passed in for Update and Create when extra tracking is disabled.
|
|
2015
|
-
*
|
|
2016
|
-
* @method: generateFlags
|
|
2017
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2018
|
-
* @return: {String} Flags to be sent, if any.
|
|
2019
|
-
*/
|
|
2020
|
-
function generateFlags(pParameters) {
|
|
2021
|
-
let tmpDisableAutoDateStamp = pParameters.query.disableAutoDateStamp;
|
|
2022
|
-
let tmpDisableDeleteTracking = pParameters.query.disableDeleteTracking;
|
|
2023
|
-
let tmpDisableAutoIdentity = pParameters.query.disableAutoIdentity;
|
|
2024
|
-
let tmpDisableAutoUserStamp = pParameters.query.disableAutoUserStamp;
|
|
2025
|
-
let tmpFlags = '';
|
|
2026
|
-
let fAddFlag = (pFlagSet, pFlag) => {
|
|
2027
|
-
if (pFlagSet) {
|
|
2028
|
-
if (tmpFlags.length > 0) {
|
|
2029
|
-
tmpFlags += ',';
|
|
2030
|
-
}
|
|
2031
|
-
tmpFlags += pFlag;
|
|
2032
|
-
}
|
|
2033
|
-
};
|
|
2034
|
-
fAddFlag(tmpDisableAutoDateStamp, 'DisableAutoDateStamp');
|
|
2035
|
-
fAddFlag(tmpDisableDeleteTracking, 'DisableDeleteTracking');
|
|
2036
|
-
fAddFlag(tmpDisableAutoIdentity, 'DisableAutoIdentity');
|
|
2037
|
-
fAddFlag(tmpDisableAutoUserStamp, 'DisableAutoUserStamp');
|
|
2038
|
-
return tmpFlags;
|
|
2039
|
-
}
|
|
2040
|
-
;
|
|
2041
|
-
|
|
2042
|
-
/**
|
|
2043
|
-
* Get the ID for the record, to be used in URIs
|
|
2044
|
-
*
|
|
2045
|
-
* @method: getIDRecord
|
|
2046
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2047
|
-
* @return: {String} ID of the record in string form for the URI
|
|
2048
|
-
*/
|
|
2049
|
-
var getIDRecord = function (pParameters) {
|
|
2050
|
-
var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
|
|
2051
|
-
var tmpIDRecord = false;
|
|
2052
|
-
if (tmpFilter.length < 1) {
|
|
2053
|
-
return tmpIDRecord;
|
|
2054
|
-
}
|
|
2055
|
-
for (var i = 0; i < tmpFilter.length; i++) {
|
|
2056
|
-
// Check Schema Entry Type
|
|
2057
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2058
|
-
var tmpSchemaEntry = {
|
|
2059
|
-
Column: tmpFilter[i].Column,
|
|
2060
|
-
Type: 'Default'
|
|
2061
|
-
};
|
|
2062
|
-
for (var j = 0; j < tmpSchema.length; j++) {
|
|
2063
|
-
// If this column is the AutoIdentity, set it.
|
|
2064
|
-
if (tmpFilter[i].Column == tmpSchema[j].Column && tmpSchema[j].Type == 'AutoIdentity') {
|
|
2065
|
-
tmpIDRecord = tmpFilter[i].Value;
|
|
2066
|
-
break;
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
return tmpIDRecord;
|
|
2071
|
-
};
|
|
2072
|
-
|
|
2073
|
-
/**
|
|
2074
|
-
* Generate an ORDER BY clause from the sort array
|
|
2075
|
-
*
|
|
2076
|
-
* Each entry in the sort is an object like:
|
|
2077
|
-
* {Column:'Color',Direction:'Descending'}
|
|
2078
|
-
*
|
|
2079
|
-
* @method: generateOrderBy
|
|
2080
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2081
|
-
* @return: {String} Returns the field list clause
|
|
2082
|
-
*/
|
|
2083
|
-
var generateOrderBy = function (pParameters) {
|
|
2084
|
-
var tmpOrderBy = pParameters.sort;
|
|
2085
|
-
var tmpOrderClause = false;
|
|
2086
|
-
if (!Array.isArray(tmpOrderBy) || tmpOrderBy.length < 1) {
|
|
2087
|
-
return tmpOrderClause;
|
|
2088
|
-
}
|
|
2089
|
-
tmpOrderClause = '';
|
|
2090
|
-
for (var i = 0; i < tmpOrderBy.length; i++) {
|
|
2091
|
-
if (i > 0) {
|
|
2092
|
-
tmpOrderClause += '~';
|
|
2093
|
-
}
|
|
2094
|
-
tmpOrderClause += `FSF~${tmpOrderBy[i].Column}~`;
|
|
2095
|
-
if (tmpOrderBy[i].Direction == 'Descending') {
|
|
2096
|
-
tmpOrderClause += 'DESC~0';
|
|
2097
|
-
} else {
|
|
2098
|
-
tmpOrderClause += 'ASC~0';
|
|
2099
|
-
}
|
|
2100
|
-
}
|
|
2101
|
-
return tmpOrderClause;
|
|
2102
|
-
};
|
|
2103
|
-
|
|
2104
|
-
/**
|
|
2105
|
-
* Generate the limit clause
|
|
2106
|
-
*
|
|
2107
|
-
* @method: generateLimit
|
|
2108
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2109
|
-
* @return: {String} Returns the table name clause
|
|
2110
|
-
*/
|
|
2111
|
-
var generateLimit = function (pParameters) {
|
|
2112
|
-
if (!pParameters.cap) {
|
|
2113
|
-
return '';
|
|
2114
|
-
}
|
|
2115
|
-
let tmpBegin = pParameters.begin !== false ? pParameters.begin : 0;
|
|
2116
|
-
return `${tmpBegin}/${pParameters.cap}`;
|
|
2117
|
-
};
|
|
2118
|
-
var Create = function (pParameters) {
|
|
2119
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2120
|
-
var tmpFlags = generateFlags(pParameters);
|
|
2121
|
-
if (tmpTableName) {
|
|
2122
|
-
let tmpURL = tmpTableName;
|
|
2123
|
-
if (tmpFlags) {
|
|
2124
|
-
tmpURL = `${tmpURL}/WithFlags/${tmpFlags}`;
|
|
2125
|
-
}
|
|
2126
|
-
return tmpURL;
|
|
2127
|
-
} else {
|
|
2128
|
-
return false;
|
|
2129
|
-
}
|
|
2130
|
-
};
|
|
2131
|
-
|
|
2132
|
-
/**
|
|
2133
|
-
* Read one or many records
|
|
2134
|
-
*
|
|
2135
|
-
* @method Read
|
|
2136
|
-
* @param {Object} pParameters SQL Query parameters
|
|
2137
|
-
* @return {String} Returns the current Query for chaining.
|
|
2138
|
-
*/
|
|
2139
|
-
var Read = function (pParameters) {
|
|
2140
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2141
|
-
var tmpFieldList = generateFieldList(pParameters);
|
|
2142
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2143
|
-
var tmpLimit = generateLimit(pParameters);
|
|
2144
|
-
var tmpURL = `${tmpTableName}`;
|
|
2145
|
-
// In the case that there is only a single query parameter, and the parameter is a single identity,
|
|
2146
|
-
// we will cast it to the READ endpoint rather than READS.
|
|
2147
|
-
if (pParameters.filter && pParameters.filter.length == 1
|
|
2148
|
-
// If there is exactly one query filter parameter
|
|
2149
|
-
&& pParameters.filter[0].Column === generateIdentityColumnName(pParameters)
|
|
2150
|
-
// AND It is the Identity column
|
|
2151
|
-
&& pParameters.filter[0].Operator === '='
|
|
2152
|
-
// AND The comparators is a simple equals
|
|
2153
|
-
&& tmpLimit == '' && tmpFieldList == ''
|
|
2154
|
-
// AND There is no limit or field list set
|
|
2155
|
-
&& !pParameters.sort)
|
|
2156
|
-
// AND There is no sort clause
|
|
2157
|
-
{
|
|
2158
|
-
// THEN This is a SINGLE READ by presumption.
|
|
2159
|
-
// There are some bad side affects this could cause with chaining and overridden behaviors, if
|
|
2160
|
-
// we are requesting a filtered list of 1 record.
|
|
2161
|
-
tmpURL = `${tmpURL}/${pParameters.filter[0].Value}`;
|
|
2162
|
-
} else {
|
|
2163
|
-
tmpURL = `${tmpURL}s`;
|
|
2164
|
-
if (tmpFieldList) {
|
|
2165
|
-
tmpURL = `${tmpURL}/LiteExtended/${tmpFieldList}`;
|
|
2166
|
-
}
|
|
2167
|
-
if (tmpWhere) {
|
|
2168
|
-
tmpURL = `${tmpURL}/FilteredTo/${tmpWhere}`;
|
|
2169
|
-
}
|
|
2170
|
-
if (tmpLimit) {
|
|
2171
|
-
tmpURL = `${tmpURL}/${tmpLimit}`;
|
|
2172
|
-
}
|
|
2173
|
-
}
|
|
2174
|
-
return tmpURL;
|
|
2175
|
-
};
|
|
2176
|
-
var Update = function (pParameters) {
|
|
2177
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2178
|
-
var tmpFlags = generateFlags(pParameters);
|
|
2179
|
-
if (tmpTableName) {
|
|
2180
|
-
let tmpURL = tmpTableName;
|
|
2181
|
-
if (tmpFlags) {
|
|
2182
|
-
tmpURL = `${tmpURL}/WithFlags/${tmpFlags}`;
|
|
2183
|
-
}
|
|
2184
|
-
return tmpURL;
|
|
2185
|
-
} else {
|
|
2186
|
-
return false;
|
|
2187
|
-
}
|
|
2188
|
-
};
|
|
2189
|
-
var Delete = function (pParameters) {
|
|
2190
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2191
|
-
var tmpIDRecord = getIDRecord(pParameters);
|
|
2192
|
-
if (!tmpIDRecord) {
|
|
2193
|
-
return false;
|
|
2194
|
-
}
|
|
2195
|
-
return `${tmpTableName}/${tmpIDRecord}`;
|
|
2196
|
-
};
|
|
2197
|
-
var Count = function (pParameters) {
|
|
2198
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2199
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2200
|
-
let tmpCountQuery = `${tmpTableName}s/Count`;
|
|
2201
|
-
if (tmpWhere) {
|
|
2202
|
-
return `${tmpTableName}s/Count/FilteredTo/${tmpWhere}`;
|
|
2203
|
-
}
|
|
2204
|
-
return tmpCountQuery;
|
|
2205
|
-
};
|
|
2206
|
-
var tmpDialect = {
|
|
2207
|
-
Create: Create,
|
|
2208
|
-
Read: Read,
|
|
2209
|
-
Update: Update,
|
|
2210
|
-
Delete: Delete,
|
|
2211
|
-
Count: Count
|
|
2212
|
-
};
|
|
2213
|
-
|
|
2214
|
-
/**
|
|
2215
|
-
* Dialect Name
|
|
2216
|
-
*
|
|
2217
|
-
* @property name
|
|
2218
|
-
* @type string
|
|
2219
|
-
*/
|
|
2220
|
-
Object.defineProperty(tmpDialect, 'name', {
|
|
2221
|
-
get: function () {
|
|
2222
|
-
return 'MeadowEndpoints';
|
|
2223
|
-
},
|
|
2224
|
-
enumerable: true
|
|
2225
|
-
});
|
|
2226
|
-
return tmpDialect;
|
|
2227
|
-
};
|
|
2228
|
-
module.exports = FoxHoundDialectMeadowEndpoints;
|
|
2229
|
-
}, {}],
|
|
2230
|
-
8: [function (require, module, exports) {
|
|
2231
|
-
/**
|
|
2232
|
-
* FoxHound MySQL Dialect
|
|
2233
|
-
*
|
|
2234
|
-
* @license MIT
|
|
2235
|
-
*
|
|
2236
|
-
* For a MySQL query override:
|
|
2237
|
-
// An underscore template with the following values:
|
|
2238
|
-
// <%= DataElements %> = Field1, Field2, Field3, Field4
|
|
2239
|
-
// <%= Begin %> = 0
|
|
2240
|
-
// <%= Cap %> = 10
|
|
2241
|
-
// <%= Filter %> = WHERE StartDate > :MyStartDate
|
|
2242
|
-
// <%= Sort %> = ORDER BY Field1
|
|
2243
|
-
// The values are empty strings if they aren't set.
|
|
2244
|
-
*
|
|
2245
|
-
* @author Steven Velozo <steven@velozo.com>
|
|
2246
|
-
* @class FoxHoundDialectMySQL
|
|
2247
|
-
*/
|
|
2248
|
-
|
|
2249
|
-
var FoxHoundDialectMySQL = function (pFable) {
|
|
2250
|
-
//Request time from SQL server with microseconds resolution
|
|
2251
|
-
const SQL_NOW = "NOW(3)";
|
|
2252
|
-
_Fable = pFable;
|
|
2253
|
-
|
|
2254
|
-
/**
|
|
2255
|
-
* Generate a table name from the scope
|
|
2256
|
-
*
|
|
2257
|
-
* @method: generateTableName
|
|
2258
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2259
|
-
* @return: {String} Returns the table name clause
|
|
2260
|
-
*/
|
|
2261
|
-
var generateTableName = function (pParameters) {
|
|
2262
|
-
if (pParameters.scope && pParameters.scope.indexOf('`') >= 0) return ' ' + pParameters.scope + '';else return ' `' + pParameters.scope + '`';
|
|
2263
|
-
};
|
|
2264
|
-
|
|
2265
|
-
/**
|
|
2266
|
-
* Generate a field list from the array of dataElements
|
|
2267
|
-
*
|
|
2268
|
-
* Each entry in the dataElements is a simple string
|
|
2269
|
-
*
|
|
2270
|
-
* @method: generateFieldList
|
|
2271
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2272
|
-
* @param {Boolean} pIsForCountClause (optional) If true, generate fields for use within a count clause.
|
|
2273
|
-
* @return: {String} Returns the field list clause, or empty string if explicit fields are requested but cannot be fulfilled
|
|
2274
|
-
* due to missing schema.
|
|
2275
|
-
*/
|
|
2276
|
-
var generateFieldList = function (pParameters, pIsForCountClause) {
|
|
2277
|
-
var tmpDataElements = pParameters.dataElements;
|
|
2278
|
-
if (!Array.isArray(tmpDataElements) || tmpDataElements.length < 1) {
|
|
2279
|
-
const tmpTableName = generateTableName(pParameters);
|
|
2280
|
-
if (!pIsForCountClause) {
|
|
2281
|
-
return tmpTableName + '.*';
|
|
2282
|
-
}
|
|
2283
|
-
// we need to list all of the table fields explicitly; get them from the schema
|
|
2284
|
-
const tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2285
|
-
if (tmpSchema.length < 1) {
|
|
2286
|
-
// this means we have no schema; returning an empty string here signals the calling code to handle this case
|
|
2287
|
-
return '';
|
|
2288
|
-
}
|
|
2289
|
-
const idColumn = tmpSchema.find(entry => entry.Type === 'AutoIdentity');
|
|
2290
|
-
if (!idColumn) {
|
|
2291
|
-
// this means there is no autoincrementing unique ID column; treat as above
|
|
2292
|
-
return '';
|
|
2293
|
-
}
|
|
2294
|
-
const qualifiedIDColumn = `${tmpTableName}.${idColumn.Column}`;
|
|
2295
|
-
return ` ${generateSafeFieldName(qualifiedIDColumn)}`;
|
|
2296
|
-
}
|
|
2297
|
-
var tmpFieldList = ' ';
|
|
2298
|
-
for (var i = 0; i < tmpDataElements.length; i++) {
|
|
2299
|
-
if (i > 0) {
|
|
2300
|
-
tmpFieldList += ', ';
|
|
2301
|
-
}
|
|
2302
|
-
if (Array.isArray(tmpDataElements[i])) {
|
|
2303
|
-
tmpFieldList += generateSafeFieldName(tmpDataElements[i][0]);
|
|
2304
|
-
if (tmpDataElements[i].length > 1 && tmpDataElements[i][1]) {
|
|
2305
|
-
tmpFieldList += " AS " + generateSafeFieldName(tmpDataElements[i][1]);
|
|
2306
|
-
}
|
|
2307
|
-
} else {
|
|
2308
|
-
tmpFieldList += generateSafeFieldName(tmpDataElements[i]);
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
return tmpFieldList;
|
|
2312
|
-
};
|
|
2313
|
-
const SURROUNDING_QUOTES_AND_WHITESPACE_REGEX = /^[` ]+|[` ]+$/g;
|
|
2314
|
-
const cleanseQuoting = str => {
|
|
2315
|
-
return str.replace(SURROUNDING_QUOTES_AND_WHITESPACE_REGEX, '');
|
|
2316
|
-
};
|
|
2317
|
-
|
|
2318
|
-
/**
|
|
2319
|
-
* Ensure a field name is properly escaped.
|
|
2320
|
-
*/
|
|
2321
|
-
var generateSafeFieldName = function (pFieldName) {
|
|
2322
|
-
let pFieldNames = pFieldName.split('.');
|
|
2323
|
-
if (pFieldNames.length > 1) {
|
|
2324
|
-
const cleansedFieldName = cleanseQuoting(pFieldNames[1]);
|
|
2325
|
-
if (cleansedFieldName === '*') {
|
|
2326
|
-
// do not put * as `*`
|
|
2327
|
-
return "`" + cleanseQuoting(pFieldNames[0]) + "`.*";
|
|
2328
|
-
}
|
|
2329
|
-
return "`" + cleanseQuoting(pFieldNames[0]) + "`.`" + cleansedFieldName + "`";
|
|
2330
|
-
}
|
|
2331
|
-
const cleansedFieldName = cleanseQuoting(pFieldNames[0]);
|
|
2332
|
-
if (cleansedFieldName === '*') {
|
|
2333
|
-
// do not put * as `*`
|
|
2334
|
-
return '*';
|
|
2335
|
-
}
|
|
2336
|
-
return "`" + cleanseQuoting(pFieldNames[0]) + "`";
|
|
2337
|
-
};
|
|
2338
|
-
|
|
2339
|
-
/**
|
|
2340
|
-
* Generate a query from the array of where clauses
|
|
2341
|
-
*
|
|
2342
|
-
* Each clause is an object like:
|
|
2343
|
-
{
|
|
2344
|
-
Column:'Name',
|
|
2345
|
-
Operator:'EQ',
|
|
2346
|
-
Value:'John',
|
|
2347
|
-
Connector:'And',
|
|
2348
|
-
Parameter:'Name'
|
|
2349
|
-
}
|
|
2350
|
-
*
|
|
2351
|
-
* @method: generateWhere
|
|
2352
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2353
|
-
* @return: {String} Returns the WHERE clause prefixed with WHERE, or an empty string if unnecessary
|
|
2354
|
-
*/
|
|
2355
|
-
var generateWhere = function (pParameters) {
|
|
2356
|
-
var tmpFilter = Array.isArray(pParameters.filter) ? pParameters.filter : [];
|
|
2357
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2358
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
2359
|
-
// Check if there is a Deleted column on the Schema. If so, we add this to the filters automatically (if not already present)
|
|
2360
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2361
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2362
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2363
|
-
var tmpSchemaEntry = tmpSchema[i];
|
|
2364
|
-
if (tmpSchemaEntry.Type === 'Deleted') {
|
|
2365
|
-
var tmpHasDeletedParameter = false;
|
|
2366
|
-
|
|
2367
|
-
//first, check to see if filters are already looking for Deleted column
|
|
2368
|
-
if (tmpFilter.length > 0) {
|
|
2369
|
-
for (var x = 0; x < tmpFilter.length; x++) {
|
|
2370
|
-
if (tmpFilter[x].Column === tmpSchemaEntry.Column) {
|
|
2371
|
-
tmpHasDeletedParameter = true;
|
|
2372
|
-
break;
|
|
2373
|
-
}
|
|
2374
|
-
}
|
|
2375
|
-
}
|
|
2376
|
-
if (!tmpHasDeletedParameter) {
|
|
2377
|
-
//if not, we need to add it
|
|
2378
|
-
tmpFilter.push({
|
|
2379
|
-
Column: tmpTableName + '.' + tmpSchemaEntry.Column,
|
|
2380
|
-
Operator: '=',
|
|
2381
|
-
Value: 0,
|
|
2382
|
-
Connector: 'AND',
|
|
2383
|
-
Parameter: 'Deleted'
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
|
-
break;
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
if (tmpFilter.length < 1) {
|
|
2391
|
-
return '';
|
|
2392
|
-
}
|
|
2393
|
-
var tmpWhere = ' WHERE';
|
|
2394
|
-
|
|
2395
|
-
// This is used to disable the connectors for subsequent queries.
|
|
2396
|
-
// Only the open parenthesis operator uses this, currently.
|
|
2397
|
-
var tmpLastOperatorNoConnector = false;
|
|
2398
|
-
for (var i = 0; i < tmpFilter.length; i++) {
|
|
2399
|
-
if (tmpFilter[i].Connector != 'NONE' && tmpFilter[i].Operator != ')' && tmpWhere != ' WHERE' && tmpLastOperatorNoConnector == false) {
|
|
2400
|
-
tmpWhere += ' ' + tmpFilter[i].Connector;
|
|
2401
|
-
}
|
|
2402
|
-
tmpLastOperatorNoConnector = false;
|
|
2403
|
-
var tmpColumnParameter;
|
|
2404
|
-
if (tmpFilter[i].Operator === '(') {
|
|
2405
|
-
// Open a logical grouping
|
|
2406
|
-
tmpWhere += ' (';
|
|
2407
|
-
tmpLastOperatorNoConnector = true;
|
|
2408
|
-
} else if (tmpFilter[i].Operator === ')') {
|
|
2409
|
-
// Close a logical grouping
|
|
2410
|
-
tmpWhere += ' )';
|
|
2411
|
-
} else if (tmpFilter[i].Operator === 'IN' || tmpFilter[i].Operator === "NOT IN") {
|
|
2412
|
-
tmpColumnParameter = tmpFilter[i].Parameter + '_w' + i;
|
|
2413
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
2414
|
-
tmpWhere += ' ' + tmpFilter[i].Column + ' ' + tmpFilter[i].Operator + ' ( :' + tmpColumnParameter + ' )';
|
|
2415
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpFilter[i].Value;
|
|
2416
|
-
} else if (tmpFilter[i].Operator === 'IS NULL') {
|
|
2417
|
-
// IS NULL is a special operator which doesn't require a value, or parameter
|
|
2418
|
-
tmpWhere += ' ' + tmpFilter[i].Column + ' ' + tmpFilter[i].Operator;
|
|
2419
|
-
} else if (tmpFilter[i].Operator === 'IS NOT NULL') {
|
|
2420
|
-
// IS NOT NULL is a special operator which doesn't require a value, or parameter
|
|
2421
|
-
tmpWhere += ' ' + tmpFilter[i].Column + ' ' + tmpFilter[i].Operator;
|
|
2422
|
-
} else {
|
|
2423
|
-
tmpColumnParameter = tmpFilter[i].Parameter + '_w' + i;
|
|
2424
|
-
// Add the column name, operator and parameter name to the list of where value parenthetical
|
|
2425
|
-
tmpWhere += ' ' + tmpFilter[i].Column + ' ' + tmpFilter[i].Operator + ' :' + tmpColumnParameter;
|
|
2426
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpFilter[i].Value;
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
return tmpWhere;
|
|
2430
|
-
};
|
|
2431
|
-
|
|
2432
|
-
/**
|
|
2433
|
-
* Generate an ORDER BY clause from the sort array
|
|
2434
|
-
*
|
|
2435
|
-
* Each entry in the sort is an object like:
|
|
2436
|
-
* {Column:'Color',Direction:'Descending'}
|
|
2437
|
-
*
|
|
2438
|
-
* @method: generateOrderBy
|
|
2439
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2440
|
-
* @return: {String} Returns the field list clause
|
|
2441
|
-
*/
|
|
2442
|
-
var generateOrderBy = function (pParameters) {
|
|
2443
|
-
var tmpOrderBy = pParameters.sort;
|
|
2444
|
-
if (!Array.isArray(tmpOrderBy) || tmpOrderBy.length < 1) {
|
|
2445
|
-
return '';
|
|
2446
|
-
}
|
|
2447
|
-
var tmpOrderClause = ' ORDER BY';
|
|
2448
|
-
for (var i = 0; i < tmpOrderBy.length; i++) {
|
|
2449
|
-
if (i > 0) {
|
|
2450
|
-
tmpOrderClause += ',';
|
|
2451
|
-
}
|
|
2452
|
-
tmpOrderClause += ' ' + tmpOrderBy[i].Column;
|
|
2453
|
-
if (tmpOrderBy[i].Direction == 'Descending') {
|
|
2454
|
-
tmpOrderClause += ' DESC';
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
|
-
return tmpOrderClause;
|
|
2458
|
-
};
|
|
2459
|
-
|
|
2460
|
-
/**
|
|
2461
|
-
* Generate the limit clause
|
|
2462
|
-
*
|
|
2463
|
-
* @method: generateLimit
|
|
2464
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2465
|
-
* @return: {String} Returns the table name clause
|
|
2466
|
-
*/
|
|
2467
|
-
var generateLimit = function (pParameters) {
|
|
2468
|
-
if (!pParameters.cap) {
|
|
2469
|
-
return '';
|
|
2470
|
-
}
|
|
2471
|
-
var tmpLimit = ' LIMIT';
|
|
2472
|
-
// If there is a begin record, we'll pass that in as well.
|
|
2473
|
-
if (pParameters.begin !== false) {
|
|
2474
|
-
tmpLimit += ' ' + pParameters.begin + ',';
|
|
2475
|
-
}
|
|
2476
|
-
// Cap is required for a limit clause.
|
|
2477
|
-
tmpLimit += ' ' + pParameters.cap;
|
|
2478
|
-
return tmpLimit;
|
|
2479
|
-
};
|
|
2480
|
-
|
|
2481
|
-
/**
|
|
2482
|
-
* Generate the join clause
|
|
2483
|
-
*
|
|
2484
|
-
* @method: generateJoins
|
|
2485
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2486
|
-
* @return: {String} Returns the join clause
|
|
2487
|
-
*/
|
|
2488
|
-
var generateJoins = function (pParameters) {
|
|
2489
|
-
var tmpJoins = pParameters.join;
|
|
2490
|
-
if (!Array.isArray(tmpJoins) || tmpJoins.length < 1) {
|
|
2491
|
-
return '';
|
|
2492
|
-
}
|
|
2493
|
-
var tmpJoinClause = ''; //ex. ' INNER JOIN';
|
|
2494
|
-
for (var i = 0; i < tmpJoins.length; i++) {
|
|
2495
|
-
var join = tmpJoins[i];
|
|
2496
|
-
//verify that all required fields are valid
|
|
2497
|
-
if (join.Type && join.Table && join.From && join.To) {
|
|
2498
|
-
tmpJoinClause += ` ${join.Type} ${join.Table} ON ${join.From} = ${join.To}`;
|
|
2499
|
-
}
|
|
2500
|
-
}
|
|
2501
|
-
return tmpJoinClause;
|
|
2502
|
-
};
|
|
2503
|
-
|
|
2504
|
-
/**
|
|
2505
|
-
* Generate the update SET clause
|
|
2506
|
-
*
|
|
2507
|
-
* @method: generateUpdateSetters
|
|
2508
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2509
|
-
* @return: {String} Returns the table name clause
|
|
2510
|
-
*/
|
|
2511
|
-
var generateUpdateSetters = function (pParameters) {
|
|
2512
|
-
var tmpRecords = pParameters.query.records;
|
|
2513
|
-
// We need to tell the query not to generate improperly if there are no values to set.
|
|
2514
|
-
if (!Array.isArray(tmpRecords) || tmpRecords.length < 1) {
|
|
2515
|
-
return false;
|
|
2516
|
-
}
|
|
2517
|
-
|
|
2518
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
2519
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2520
|
-
var tmpUpdate = '';
|
|
2521
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
2522
|
-
var tmpCurrentColumn = 0;
|
|
2523
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
2524
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
2525
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
2526
|
-
var tmpSchemaEntry = {
|
|
2527
|
-
Column: tmpColumn,
|
|
2528
|
-
Type: 'Default'
|
|
2529
|
-
};
|
|
2530
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2531
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
2532
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2533
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
2534
|
-
break;
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
|
-
if (pParameters.query.disableAutoDateStamp && tmpSchemaEntry.Type === 'UpdateDate') {
|
|
2538
|
-
// This is ignored if flag is set
|
|
2539
|
-
continue;
|
|
2540
|
-
}
|
|
2541
|
-
if (pParameters.query.disableAutoUserStamp && tmpSchemaEntry.Type === 'UpdateIDUser') {
|
|
2542
|
-
// This is ignored if flag is set
|
|
2543
|
-
continue;
|
|
2544
|
-
}
|
|
2545
|
-
switch (tmpSchemaEntry.Type) {
|
|
2546
|
-
case 'AutoIdentity':
|
|
2547
|
-
case 'CreateDate':
|
|
2548
|
-
case 'CreateIDUser':
|
|
2549
|
-
case 'DeleteDate':
|
|
2550
|
-
case 'DeleteIDUser':
|
|
2551
|
-
// These are all ignored on update
|
|
2552
|
-
continue;
|
|
2553
|
-
}
|
|
2554
|
-
if (tmpCurrentColumn > 0) {
|
|
2555
|
-
tmpUpdate += ',';
|
|
2556
|
-
}
|
|
2557
|
-
switch (tmpSchemaEntry.Type) {
|
|
2558
|
-
case 'UpdateDate':
|
|
2559
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
2560
|
-
tmpUpdate += ' ' + tmpColumn + ' = ' + SQL_NOW;
|
|
2561
|
-
break;
|
|
2562
|
-
case 'UpdateIDUser':
|
|
2563
|
-
// This is the user ID, which we hope is in the query.
|
|
2564
|
-
// This is how to deal with a normal column
|
|
2565
|
-
var tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
2566
|
-
tmpUpdate += ' ' + tmpColumn + ' = :' + tmpColumnParameter;
|
|
2567
|
-
// Set the query parameter
|
|
2568
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
2569
|
-
break;
|
|
2570
|
-
default:
|
|
2571
|
-
var tmpColumnDefaultParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
2572
|
-
tmpUpdate += ' ' + tmpColumn + ' = :' + tmpColumnDefaultParameter;
|
|
2573
|
-
|
|
2574
|
-
// Set the query parameter
|
|
2575
|
-
pParameters.query.parameters[tmpColumnDefaultParameter] = tmpRecords[0][tmpColumn];
|
|
2576
|
-
break;
|
|
2577
|
-
}
|
|
2578
|
-
|
|
2579
|
-
// We use a number to make sure parameters are unique.
|
|
2580
|
-
tmpCurrentColumn++;
|
|
2581
|
-
}
|
|
2582
|
-
|
|
2583
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
2584
|
-
if (tmpUpdate === '') {
|
|
2585
|
-
return false;
|
|
2586
|
-
}
|
|
2587
|
-
return tmpUpdate;
|
|
2588
|
-
};
|
|
2589
|
-
|
|
2590
|
-
/**
|
|
2591
|
-
* Generate the update-delete SET clause
|
|
2592
|
-
*
|
|
2593
|
-
* @method: generateUpdateDeleteSetters
|
|
2594
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2595
|
-
* @return: {String} Returns the table name clause
|
|
2596
|
-
*/
|
|
2597
|
-
var generateUpdateDeleteSetters = function (pParameters) {
|
|
2598
|
-
if (pParameters.query.disableDeleteTracking) {
|
|
2599
|
-
//Don't generate an UPDATE query if Delete tracking is disabled
|
|
2600
|
-
return false;
|
|
2601
|
-
}
|
|
2602
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
2603
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2604
|
-
var tmpCurrentColumn = 0;
|
|
2605
|
-
var tmpHasDeletedField = false;
|
|
2606
|
-
var tmpUpdate = '';
|
|
2607
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
2608
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
2609
|
-
var tmpSchemaEntry = {
|
|
2610
|
-
Type: 'Default'
|
|
2611
|
-
};
|
|
2612
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2613
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2614
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
2615
|
-
var tmpUpdateSql = null;
|
|
2616
|
-
switch (tmpSchemaEntry.Type) {
|
|
2617
|
-
case 'Deleted':
|
|
2618
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = 1';
|
|
2619
|
-
tmpHasDeletedField = true; //this field is required in order for query to be built
|
|
2620
|
-
break;
|
|
2621
|
-
case 'DeleteDate':
|
|
2622
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = ' + SQL_NOW;
|
|
2623
|
-
break;
|
|
2624
|
-
case 'UpdateDate':
|
|
2625
|
-
// Delete operation is an Update, so we should stamp the update time
|
|
2626
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = ' + SQL_NOW;
|
|
2627
|
-
break;
|
|
2628
|
-
case 'DeleteIDUser':
|
|
2629
|
-
// This is the user ID, which we hope is in the query.
|
|
2630
|
-
// This is how to deal with a normal column
|
|
2631
|
-
var tmpColumnParameter = tmpSchemaEntry.Column + '_' + tmpCurrentColumn;
|
|
2632
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = :' + tmpColumnParameter;
|
|
2633
|
-
// Set the query parameter
|
|
2634
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
2635
|
-
break;
|
|
2636
|
-
default:
|
|
2637
|
-
//DON'T allow update of other fields in this query
|
|
2638
|
-
continue;
|
|
2639
|
-
}
|
|
2640
|
-
if (tmpCurrentColumn > 0) {
|
|
2641
|
-
tmpUpdate += ',';
|
|
2642
|
-
}
|
|
2643
|
-
tmpUpdate += tmpUpdateSql;
|
|
2644
|
-
|
|
2645
|
-
// We use a number to make sure parameters are unique.
|
|
2646
|
-
tmpCurrentColumn++;
|
|
2647
|
-
}
|
|
2648
|
-
|
|
2649
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
2650
|
-
if (!tmpHasDeletedField || tmpUpdate === '') {
|
|
2651
|
-
return false;
|
|
2652
|
-
}
|
|
2653
|
-
return tmpUpdate;
|
|
2654
|
-
};
|
|
2655
|
-
|
|
2656
|
-
/**
|
|
2657
|
-
* Generate the update-undelete SET clause
|
|
2658
|
-
*
|
|
2659
|
-
* @method: generateUpdateUndeleteSetters
|
|
2660
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2661
|
-
* @return: {String} Returns the table name clause
|
|
2662
|
-
*/
|
|
2663
|
-
var generateUpdateUndeleteSetters = function (pParameters) {
|
|
2664
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
2665
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2666
|
-
var tmpCurrentColumn = 0;
|
|
2667
|
-
var tmpHasDeletedField = false;
|
|
2668
|
-
var tmpUpdate = '';
|
|
2669
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
2670
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
2671
|
-
var tmpSchemaEntry = {
|
|
2672
|
-
Type: 'Default'
|
|
2673
|
-
};
|
|
2674
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2675
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2676
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
2677
|
-
var tmpUpdateSql = null;
|
|
2678
|
-
switch (tmpSchemaEntry.Type) {
|
|
2679
|
-
case 'Deleted':
|
|
2680
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = 0';
|
|
2681
|
-
tmpHasDeletedField = true; //this field is required in order for query to be built
|
|
2682
|
-
break;
|
|
2683
|
-
case 'UpdateDate':
|
|
2684
|
-
// The undelete operation is an Update, so we should stamp the update time
|
|
2685
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = ' + SQL_NOW;
|
|
2686
|
-
break;
|
|
2687
|
-
case 'UpdateIDUser':
|
|
2688
|
-
var tmpColumnParameter = tmpSchemaEntry.Column + '_' + tmpCurrentColumn;
|
|
2689
|
-
tmpUpdateSql = ' ' + tmpSchemaEntry.Column + ' = :' + tmpColumnParameter;
|
|
2690
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
2691
|
-
break;
|
|
2692
|
-
default:
|
|
2693
|
-
//DON'T allow update of other fields in this query
|
|
2694
|
-
continue;
|
|
2695
|
-
}
|
|
2696
|
-
if (tmpCurrentColumn > 0) {
|
|
2697
|
-
tmpUpdate += ',';
|
|
2698
|
-
}
|
|
2699
|
-
tmpUpdate += tmpUpdateSql;
|
|
2700
|
-
|
|
2701
|
-
// We use a number to make sure parameters are unique.
|
|
2702
|
-
tmpCurrentColumn++;
|
|
2703
|
-
}
|
|
2704
|
-
|
|
2705
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
2706
|
-
if (!tmpHasDeletedField || tmpUpdate === '') {
|
|
2707
|
-
return false;
|
|
2708
|
-
}
|
|
2709
|
-
return tmpUpdate;
|
|
2710
|
-
};
|
|
2711
|
-
|
|
2712
|
-
/**
|
|
2713
|
-
* Generate the create SET clause
|
|
2714
|
-
*
|
|
2715
|
-
* @method: generateCreateSetList
|
|
2716
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2717
|
-
* @return: {String} Returns the table name clause
|
|
2718
|
-
*/
|
|
2719
|
-
var generateCreateSetValues = function (pParameters) {
|
|
2720
|
-
var tmpRecords = pParameters.query.records;
|
|
2721
|
-
// We need to tell the query not to generate improperly if there are no values to set.
|
|
2722
|
-
if (!Array.isArray(tmpRecords) || tmpRecords.length < 1) {
|
|
2723
|
-
return false;
|
|
2724
|
-
}
|
|
2725
|
-
|
|
2726
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
2727
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2728
|
-
var tmpCreateSet = '';
|
|
2729
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
2730
|
-
var tmpCurrentColumn = 0;
|
|
2731
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
2732
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
2733
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
2734
|
-
var tmpSchemaEntry = {
|
|
2735
|
-
Column: tmpColumn,
|
|
2736
|
-
Type: 'Default'
|
|
2737
|
-
};
|
|
2738
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2739
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
2740
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2741
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
2742
|
-
break;
|
|
2743
|
-
}
|
|
2744
|
-
}
|
|
2745
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
2746
|
-
if (tmpSchemaEntry.Type === 'DeleteDate' || tmpSchemaEntry.Type === 'DeleteIDUser') {
|
|
2747
|
-
// These are all ignored on insert (if delete tracking is enabled as normal)
|
|
2748
|
-
continue;
|
|
2749
|
-
}
|
|
2750
|
-
}
|
|
2751
|
-
if (tmpCurrentColumn > 0) {
|
|
2752
|
-
tmpCreateSet += ',';
|
|
2753
|
-
}
|
|
2754
|
-
|
|
2755
|
-
//define a re-usable method for setting up field definitions in a default pattern
|
|
2756
|
-
var buildDefaultDefinition = function () {
|
|
2757
|
-
var tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
2758
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
2759
|
-
// Set the query parameter
|
|
2760
|
-
pParameters.query.parameters[tmpColumnParameter] = tmpRecords[0][tmpColumn];
|
|
2761
|
-
};
|
|
2762
|
-
var tmpColumnParameter;
|
|
2763
|
-
switch (tmpSchemaEntry.Type) {
|
|
2764
|
-
case 'AutoIdentity':
|
|
2765
|
-
if (pParameters.query.disableAutoIdentity) {
|
|
2766
|
-
buildDefaultDefinition();
|
|
2767
|
-
} else {
|
|
2768
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
2769
|
-
tmpCreateSet += ' NULL';
|
|
2770
|
-
}
|
|
2771
|
-
break;
|
|
2772
|
-
case 'AutoGUID':
|
|
2773
|
-
if (pParameters.query.disableAutoIdentity) {
|
|
2774
|
-
buildDefaultDefinition();
|
|
2775
|
-
} else if (tmpRecords[0][tmpColumn] && tmpRecords[0][tmpColumn].length >= 5 && tmpRecords[0][tmpColumn] !== '0x0000000000000000')
|
|
2776
|
-
//stricture default
|
|
2777
|
-
{
|
|
2778
|
-
// Allow consumer to override AutoGUID
|
|
2779
|
-
buildDefaultDefinition();
|
|
2780
|
-
} else {
|
|
2781
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
2782
|
-
tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
2783
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
2784
|
-
// Set the query parameter
|
|
2785
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.UUID;
|
|
2786
|
-
}
|
|
2787
|
-
break;
|
|
2788
|
-
case 'UpdateDate':
|
|
2789
|
-
case 'CreateDate':
|
|
2790
|
-
case 'DeleteDate':
|
|
2791
|
-
if (pParameters.query.disableAutoDateStamp) {
|
|
2792
|
-
buildDefaultDefinition();
|
|
2793
|
-
} else {
|
|
2794
|
-
// This is an autoidentity, so we don't parameterize it and just pass in NULL
|
|
2795
|
-
tmpCreateSet += ' ' + SQL_NOW;
|
|
2796
|
-
}
|
|
2797
|
-
break;
|
|
2798
|
-
case 'DeleteIDUser':
|
|
2799
|
-
case 'UpdateIDUser':
|
|
2800
|
-
case 'CreateIDUser':
|
|
2801
|
-
if (pParameters.query.disableAutoUserStamp) {
|
|
2802
|
-
buildDefaultDefinition();
|
|
2803
|
-
} else {
|
|
2804
|
-
// This is the user ID, which we hope is in the query.
|
|
2805
|
-
// This is how to deal with a normal column
|
|
2806
|
-
tmpColumnParameter = tmpColumn + '_' + tmpCurrentColumn;
|
|
2807
|
-
tmpCreateSet += ' :' + tmpColumnParameter;
|
|
2808
|
-
// Set the query parameter
|
|
2809
|
-
pParameters.query.parameters[tmpColumnParameter] = pParameters.query.IDUser;
|
|
2810
|
-
}
|
|
2811
|
-
break;
|
|
2812
|
-
default:
|
|
2813
|
-
buildDefaultDefinition();
|
|
2814
|
-
break;
|
|
2815
|
-
}
|
|
2816
|
-
|
|
2817
|
-
// We use an appended number to make sure parameters are unique.
|
|
2818
|
-
tmpCurrentColumn++;
|
|
2819
|
-
}
|
|
2820
|
-
|
|
2821
|
-
// We need to tell the query not to generate improperly if there are no values set.
|
|
2822
|
-
if (tmpCreateSet === '') {
|
|
2823
|
-
return false;
|
|
2824
|
-
}
|
|
2825
|
-
return tmpCreateSet;
|
|
2826
|
-
};
|
|
2827
|
-
|
|
2828
|
-
/**
|
|
2829
|
-
* Generate the create SET clause
|
|
2830
|
-
*
|
|
2831
|
-
* @method: generateCreateSetList
|
|
2832
|
-
* @param: {Object} pParameters SQL Query Parameters
|
|
2833
|
-
* @return: {String} Returns the table name clause
|
|
2834
|
-
*/
|
|
2835
|
-
var generateCreateSetList = function (pParameters) {
|
|
2836
|
-
// The records were already validated by generateCreateSetValues
|
|
2837
|
-
var tmpRecords = pParameters.query.records;
|
|
2838
|
-
|
|
2839
|
-
// Check if there is a schema. If so, we will use it to decide if these are parameterized or not.
|
|
2840
|
-
var tmpSchema = Array.isArray(pParameters.query.schema) ? pParameters.query.schema : [];
|
|
2841
|
-
var tmpCreateSet = '';
|
|
2842
|
-
// If there is more than one record in records, we are going to ignore them for now.
|
|
2843
|
-
for (var tmpColumn in tmpRecords[0]) {
|
|
2844
|
-
// No hash table yet, so, we will just linear search it for now.
|
|
2845
|
-
// This uses the schema to decide if we want to treat a column differently on insert
|
|
2846
|
-
var tmpSchemaEntry = {
|
|
2847
|
-
Column: tmpColumn,
|
|
2848
|
-
Type: 'Default'
|
|
2849
|
-
};
|
|
2850
|
-
for (var i = 0; i < tmpSchema.length; i++) {
|
|
2851
|
-
if (tmpColumn == tmpSchema[i].Column) {
|
|
2852
|
-
// There is a schema entry for it. Process it accordingly.
|
|
2853
|
-
tmpSchemaEntry = tmpSchema[i];
|
|
2854
|
-
break;
|
|
2855
|
-
}
|
|
2856
|
-
}
|
|
2857
|
-
if (!pParameters.query.disableDeleteTracking) {
|
|
2858
|
-
if (tmpSchemaEntry.Type === 'DeleteDate' || tmpSchemaEntry.Type === 'DeleteIDUser') {
|
|
2859
|
-
// These are all ignored on insert (if delete tracking is enabled as normal)
|
|
2860
|
-
continue;
|
|
2861
|
-
}
|
|
2862
|
-
}
|
|
2863
|
-
switch (tmpSchemaEntry.Type) {
|
|
2864
|
-
default:
|
|
2865
|
-
if (tmpCreateSet != '') {
|
|
2866
|
-
tmpCreateSet += ',';
|
|
2867
|
-
}
|
|
2868
|
-
tmpCreateSet += ' ' + tmpColumn;
|
|
2869
|
-
break;
|
|
2870
|
-
}
|
|
2871
|
-
}
|
|
2872
|
-
return tmpCreateSet;
|
|
2873
|
-
};
|
|
2874
|
-
var Create = function (pParameters) {
|
|
2875
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2876
|
-
var tmpCreateSetList = generateCreateSetList(pParameters);
|
|
2877
|
-
var tmpCreateSetValues = generateCreateSetValues(pParameters);
|
|
2878
|
-
if (!tmpCreateSetValues) {
|
|
2879
|
-
return false;
|
|
2880
|
-
}
|
|
2881
|
-
return 'INSERT INTO' + tmpTableName + ' (' + tmpCreateSetList + ') VALUES (' + tmpCreateSetValues + ');';
|
|
2882
|
-
};
|
|
2883
|
-
|
|
2884
|
-
/**
|
|
2885
|
-
* Read one or many records
|
|
2886
|
-
*
|
|
2887
|
-
* Some examples:
|
|
2888
|
-
* SELECT * FROM WIDGETS;
|
|
2889
|
-
* SELECT * FROM WIDGETS LIMIT 0, 20;
|
|
2890
|
-
* SELECT * FROM WIDGETS LIMIT 5, 20;
|
|
2891
|
-
* SELECT ID, Name, Cost FROM WIDGETS LIMIT 5, 20;
|
|
2892
|
-
* SELECT ID, Name, Cost FROM WIDGETS LIMIT 5, 20 WHERE LastName = 'Smith';
|
|
2893
|
-
*
|
|
2894
|
-
* @method Read
|
|
2895
|
-
* @param {Object} pParameters SQL Query parameters
|
|
2896
|
-
* @return {String} Returns the current Query for chaining.
|
|
2897
|
-
*/
|
|
2898
|
-
var Read = function (pParameters) {
|
|
2899
|
-
var tmpFieldList = generateFieldList(pParameters);
|
|
2900
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2901
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2902
|
-
var tmpJoin = generateJoins(pParameters);
|
|
2903
|
-
var tmpOrderBy = generateOrderBy(pParameters);
|
|
2904
|
-
var tmpLimit = generateLimit(pParameters);
|
|
2905
|
-
const tmpOptDistinct = pParameters.distinct ? ' DISTINCT' : '';
|
|
2906
|
-
if (pParameters.queryOverride) {
|
|
2907
|
-
try {
|
|
2908
|
-
var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
|
|
2909
|
-
return tmpQueryTemplate({
|
|
2910
|
-
FieldList: tmpFieldList,
|
|
2911
|
-
TableName: tmpTableName,
|
|
2912
|
-
Where: tmpWhere,
|
|
2913
|
-
Join: tmpJoin,
|
|
2914
|
-
OrderBy: tmpOrderBy,
|
|
2915
|
-
Limit: tmpLimit,
|
|
2916
|
-
Distinct: tmpOptDistinct,
|
|
2917
|
-
_Params: pParameters
|
|
2918
|
-
});
|
|
2919
|
-
} catch (pError) {
|
|
2920
|
-
// This pokemon is here to give us a convenient way of not throwing up totally if the query fails.
|
|
2921
|
-
console.log('Error with custom Read Query [' + pParameters.queryOverride + ']: ' + pError);
|
|
2922
|
-
return false;
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
return `SELECT${tmpOptDistinct}${tmpFieldList} FROM${tmpTableName}${tmpJoin}${tmpWhere}${tmpOrderBy}${tmpLimit};`;
|
|
2926
|
-
};
|
|
2927
|
-
var Update = function (pParameters) {
|
|
2928
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2929
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2930
|
-
var tmpUpdateSetters = generateUpdateSetters(pParameters);
|
|
2931
|
-
if (!tmpUpdateSetters) {
|
|
2932
|
-
return false;
|
|
2933
|
-
}
|
|
2934
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateSetters + tmpWhere + ';';
|
|
2935
|
-
};
|
|
2936
|
-
var Delete = function (pParameters) {
|
|
2937
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2938
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2939
|
-
var tmpUpdateDeleteSetters = generateUpdateDeleteSetters(pParameters);
|
|
2940
|
-
if (tmpUpdateDeleteSetters) {
|
|
2941
|
-
//If it has a deleted bit, update it instead of actually deleting the record
|
|
2942
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateDeleteSetters + tmpWhere + ';';
|
|
2943
|
-
} else {
|
|
2944
|
-
return 'DELETE FROM' + tmpTableName + tmpWhere + ';';
|
|
2945
|
-
}
|
|
2946
|
-
};
|
|
2947
|
-
var Undelete = function (pParameters) {
|
|
2948
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2949
|
-
// TODO: Fix these
|
|
2950
|
-
let tmpDeleteTrackingState = pParameters.query.disableDeleteTracking;
|
|
2951
|
-
pParameters.query.disableDeleteTracking = true;
|
|
2952
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2953
|
-
var tmpUpdateUndeleteSetters = generateUpdateUndeleteSetters(pParameters);
|
|
2954
|
-
pParameters.query.disableDeleteTracking = tmpDeleteTrackingState;
|
|
2955
|
-
if (tmpUpdateUndeleteSetters) {
|
|
2956
|
-
//If the table has a deleted bit, go forward with the update to change things.
|
|
2957
|
-
return 'UPDATE' + tmpTableName + ' SET' + tmpUpdateUndeleteSetters + tmpWhere + ';';
|
|
2958
|
-
} else {
|
|
2959
|
-
// This is a no-op because the record can't be undeleted.
|
|
2960
|
-
// TODO: Should it throw instead?
|
|
2961
|
-
return 'SELECT NULL;';
|
|
2962
|
-
}
|
|
2963
|
-
};
|
|
2964
|
-
var Count = function (pParameters) {
|
|
2965
|
-
var tmpFieldList = pParameters.distinct ? generateFieldList(pParameters, true) : '*';
|
|
2966
|
-
var tmpTableName = generateTableName(pParameters);
|
|
2967
|
-
var tmpJoin = generateJoins(pParameters);
|
|
2968
|
-
var tmpWhere = generateWhere(pParameters);
|
|
2969
|
-
// here, we ignore the distinct keyword if no fields have been specified and
|
|
2970
|
-
if (pParameters.distinct && tmpFieldList.length < 1) {
|
|
2971
|
-
console.warn('Distinct requested but no field list or schema are available, so not honoring distinct for count query.');
|
|
2972
|
-
}
|
|
2973
|
-
const tmpOptDistinct = pParameters.distinct && tmpFieldList.length > 0 ? 'DISTINCT' : '';
|
|
2974
|
-
if (pParameters.queryOverride) {
|
|
2975
|
-
try {
|
|
2976
|
-
var tmpQueryTemplate = _Fable.Utility.template(pParameters.queryOverride);
|
|
2977
|
-
return tmpQueryTemplate({
|
|
2978
|
-
FieldList: [],
|
|
2979
|
-
TableName: tmpTableName,
|
|
2980
|
-
Where: tmpWhere,
|
|
2981
|
-
OrderBy: '',
|
|
2982
|
-
Limit: '',
|
|
2983
|
-
Distinct: tmpOptDistinct,
|
|
2984
|
-
_Params: pParameters
|
|
2985
|
-
});
|
|
2986
|
-
} catch (pError) {
|
|
2987
|
-
// This pokemon is here to give us a convenient way of not throwing up totally if the query fails.
|
|
2988
|
-
console.log('Error with custom Count Query [' + pParameters.queryOverride + ']: ' + pError);
|
|
2989
|
-
return false;
|
|
2990
|
-
}
|
|
2991
|
-
}
|
|
2992
|
-
return `SELECT COUNT(${tmpOptDistinct}${tmpFieldList || '*'}) AS RowCount FROM${tmpTableName}${tmpJoin}${tmpWhere};`;
|
|
2993
|
-
};
|
|
2994
|
-
var tmpDialect = {
|
|
2995
|
-
Create: Create,
|
|
2996
|
-
Read: Read,
|
|
2997
|
-
Update: Update,
|
|
2998
|
-
Delete: Delete,
|
|
2999
|
-
Undelete: Undelete,
|
|
3000
|
-
Count: Count
|
|
3001
|
-
};
|
|
3002
|
-
|
|
3003
|
-
/**
|
|
3004
|
-
* Dialect Name
|
|
3005
|
-
*
|
|
3006
|
-
* @property name
|
|
3007
|
-
* @type string
|
|
3008
|
-
*/
|
|
3009
|
-
Object.defineProperty(tmpDialect, 'name', {
|
|
3010
|
-
get: function () {
|
|
3011
|
-
return 'MySQL';
|
|
3012
|
-
},
|
|
3013
|
-
enumerable: true
|
|
3014
|
-
});
|
|
3015
|
-
return tmpDialect;
|
|
3016
|
-
};
|
|
3017
|
-
module.exports = FoxHoundDialectMySQL;
|
|
3018
|
-
}, {}]
|
|
3019
|
-
}, {}, [1])(1);
|
|
3020
|
-
});
|