foxhound 2.0.2 → 2.0.4

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.
@@ -0,0 +1,953 @@
1
+ /**
2
+ * Unit tests for FoxHound
3
+ *
4
+ * @license MIT
5
+ *
6
+ * @author Steven Velozo <steven@velozo.com>
7
+ */
8
+
9
+ var Chai = require('chai');
10
+ var Expect = Chai.expect;
11
+ var Assert = Chai.assert;
12
+
13
+ var libFable = require('fable');
14
+ const _Fable = new libFable({Product:'FoxhoundTestsMSSQL'});
15
+ var libFoxHound = require('../source/FoxHound.js');
16
+
17
+ var _AnimalSchema = (
18
+ [
19
+ { Column: "IDAnimal", Type:"AutoIdentity" },
20
+ { Column: "GUIDAnimal", Type:"AutoGUID" },
21
+ { Column: "CreateDate", Type:"CreateDate" },
22
+ { Column: "CreatingIDUser", Type:"CreateIDUser" },
23
+ { Column: "UpdateDate", Type:"UpdateDate" },
24
+ { Column: "UpdatingIDUser", Type:"UpdateIDUser" },
25
+ { Column: "Deleted", Type:"Deleted" },
26
+ { Column: "DeletingIDUser", Type:"DeleteIDUser" },
27
+ { Column: "DeleteDate", Type:"DeleteDate" }
28
+ ]);
29
+
30
+ var _AnimalSchemaWithoutDeleted = (
31
+ [
32
+ { Column: "IDAnimal", Type:"AutoIdentity" },
33
+ { Column: "GUIDAnimal", Type:"AutoGUID" },
34
+ { Column: "CreateDate", Type:"CreateDate" },
35
+ { Column: "CreatingIDUser", Type:"CreateIDUser" },
36
+ { Column: "UpdateDate", Type:"UpdateDate" },
37
+ { Column: "UpdatingIDUser", Type:"UpdateIDUser" }
38
+ ]);
39
+
40
+ suite
41
+ (
42
+ 'FoxHound-Dialect-MSSQL',
43
+ function()
44
+ {
45
+ setup
46
+ (
47
+ function()
48
+ {
49
+ }
50
+ );
51
+
52
+ suite
53
+ (
54
+ 'Object Sanity',
55
+ function()
56
+ {
57
+ test
58
+ (
59
+ 'initialize should build a happy little object',
60
+ function()
61
+ {
62
+ var testFoxHound = libFoxHound.new(_Fable).setDialect('MSSQL');
63
+ Expect(testFoxHound.dialect.name)
64
+ .to.equal('MSSQL');
65
+ Expect(testFoxHound)
66
+ .to.be.an('object', 'FoxHound with MSSQL should initialize as an object directly from the require statement.');
67
+ }
68
+ );
69
+ }
70
+ );
71
+
72
+ suite
73
+ (
74
+ 'Basic Query Generation',
75
+ function()
76
+ {
77
+ test
78
+ (
79
+ 'Create Query',
80
+ function()
81
+ {
82
+ var tmpQuery = libFoxHound.new(_Fable)
83
+ .setLogLevel(5)
84
+ .setDialect('MSSQL')
85
+ .setScope('Animal')
86
+ .addRecord({IDAnimal:null, Name:'Foo Foo', Age:15});
87
+ // Build the query
88
+ tmpQuery.buildCreateQuery();
89
+ // This is the query generated by the MSSQL dialect
90
+ _Fable.log.trace('Create Query', tmpQuery.query);
91
+ Expect(tmpQuery.query.body)
92
+ .to.equal("INSERT INTO `Animal` ( IDAnimal, Name, Age) VALUES ( :IDAnimal_0, :Name_1, :Age_2);");
93
+ }
94
+ );
95
+ test
96
+ (
97
+ 'Bad Create Query',
98
+ function()
99
+ {
100
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL');
101
+ // Build the query
102
+ tmpQuery.buildCreateQuery();
103
+ tmpQuery.addRecord({});
104
+ tmpQuery.buildCreateQuery();
105
+ // This is the query generated by the MSSQL dialect
106
+ _Fable.log.trace('Create Query', tmpQuery.query);
107
+ Expect(tmpQuery.query.body)
108
+ .to.equal(false);
109
+ }
110
+ );
111
+ test
112
+ (
113
+ 'Read Query',
114
+ function()
115
+ {
116
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
117
+ tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
118
+ // Build the query
119
+ tmpQuery.buildReadQuery();
120
+ // This is the query generated by the MSSQL dialect
121
+ _Fable.log.trace('Simple Select Query', tmpQuery.query);
122
+ Expect(tmpQuery.query.body)
123
+ .to.equal('SELECT `Animal`.* FROM `Animal` ORDER BY Cost DESC;');
124
+ }
125
+ );
126
+ test
127
+ (
128
+ 'Read Query with Distinct',
129
+ function()
130
+ {
131
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL').setScope('Animal');
132
+ tmpQuery.addSort({Column:'Cost',Direction:'Descending'})
133
+ .setDistinct(true);
134
+ // Build the query
135
+ tmpQuery.buildReadQuery();
136
+ // This is the query generated by the MSSQL dialect
137
+ _Fable.log.trace('Simple Select Query', tmpQuery.query);
138
+ Expect(tmpQuery.query.body)
139
+ .to.equal('SELECT DISTINCT `Animal`.* FROM `Animal` ORDER BY Cost DESC;');
140
+ }
141
+ );
142
+ test
143
+ (
144
+ 'Complex Read Query',
145
+ function()
146
+ {
147
+ var tmpQuery = libFoxHound.new(_Fable)
148
+ .setDialect('MSSQL')
149
+ .setScope('Animal')
150
+ .setCap(10)
151
+ .setBegin(0)
152
+ .setDataElements(['Name', 'Age', 'Cost'])
153
+ .setSort([{Column:'Age',Direction:'Ascending'}])
154
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
155
+ tmpQuery.addSort('Cost');
156
+ // Build the query
157
+ tmpQuery.buildReadQuery();
158
+ // This is the query generated by the MSSQL dialect
159
+ _Fable.log.trace('Select Query', tmpQuery.query);
160
+ Expect(tmpQuery.query.body)
161
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` WHERE Age = :Age_w0 ORDER BY Age, Cost LIMIT 0, 10;');
162
+ }
163
+ );
164
+ test
165
+ (
166
+ 'Complex Read Query with qualified and unqualified "SELECT *" cases',
167
+ function()
168
+ {
169
+ var tmpQuery = libFoxHound.new(_Fable)
170
+ .setDialect('MSSQL')
171
+ .setScope('Animal')
172
+ .setCap(10)
173
+ .setBegin(0)
174
+ .setDataElements(['*', 'Name', 'Age', 'Cost', 'Animal.*'])
175
+ .setSort([{Column:'Age',Direction:'Ascending'}])
176
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
177
+ tmpQuery.addSort('Cost');
178
+ // Build the query
179
+ tmpQuery.buildReadQuery();
180
+ // This is the query generated by the MSSQL dialect
181
+ _Fable.log.trace('Select Query', tmpQuery.query);
182
+ Expect(tmpQuery.query.body)
183
+ .to.equal('SELECT *, `Name`, `Age`, `Cost`, `Animal`.* FROM `Animal` WHERE Age = :Age_w0 ORDER BY Age, Cost LIMIT 0, 10;');
184
+ }
185
+ );
186
+ test
187
+ (
188
+ 'Complex Read Query 2',
189
+ function()
190
+ {
191
+ var tmpQuery = libFoxHound.new(_Fable)
192
+ .setDialect('MSSQL')
193
+ .setScope('Animal')
194
+ .setDataElements(['Name', 'Age', 'Cost'])
195
+ .setCap(100)
196
+ .addFilter('Age', '25')
197
+ .addFilter('', '', '(')
198
+ .addFilter('Color', 'Red')
199
+ .addFilter('Color', 'Green', '=', 'OR')
200
+ .addFilter('', '', ')')
201
+ .addFilter('Description', '', 'IS NOT NULL')
202
+ .addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
203
+ tmpQuery.setLogLevel(3).addSort('Age');
204
+ // Build the query
205
+ tmpQuery.buildReadQuery();
206
+ // This is the query generated by the MSSQL dialect
207
+ _Fable.log.trace('Select Query', tmpQuery.query);
208
+ Expect(tmpQuery.query.body)
209
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` WHERE Age = :Age_w0 AND ( Color = :Color_w2 OR Color = :Color_w3 ) AND Description IS NOT NULL AND IDOffice IN ( :IDOffice_w6 ) ORDER BY Age LIMIT 100;');
210
+ }
211
+ );
212
+ test
213
+ (
214
+ 'Custom Read Query',
215
+ function()
216
+ {
217
+ var tmpQuery = libFoxHound.new(_Fable)
218
+ .setDialect('MSSQL')
219
+ .setScope('Animal')
220
+ .setCap(10)
221
+ .setBegin(0)
222
+ .setDataElements(['Name', 'Age', 'Cost'])
223
+ .setSort([{Column:'Age',Direction:'Ascending'},{Column:'Cost',Direction:'Descending'}])
224
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
225
+ tmpQuery.parameters.queryOverride = 'SELECT Name, Age * 5, Cost FROM <%= TableName %> <%= Where %> <%= Limit %>;';
226
+ // Build the query
227
+ tmpQuery.buildReadQuery();
228
+ // This is the query generated by the MSSQL dialect
229
+ _Fable.log.trace('Custom Select Query', tmpQuery.query);
230
+ Expect(tmpQuery.query.body)
231
+ .to.equal('SELECT Name, Age * 5, Cost FROM `Animal` WHERE Age = :Age_w0 LIMIT 0, 10;');
232
+ }
233
+ );
234
+ test
235
+ (
236
+ 'Custom Read Query with Custom Parameters',
237
+ function()
238
+ {
239
+ var tmpQuery = libFoxHound.new(_Fable)
240
+ .setDialect('MSSQL')
241
+ .setScope('Animal')
242
+ .setCap(10)
243
+ .setBegin(0)
244
+ .setDataElements(['Name', 'Age', 'Cost'])
245
+ .setSort([{Column:'Age',Direction:'Ascending'},{Column:'Cost',Direction:'Descending'}])
246
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
247
+ tmpQuery.parameters.CustomFields = 'Name, Age * 5, Cost';
248
+ tmpQuery.parameters.queryOverride = 'SELECT <%= _Params.CustomFields %> FROM <%= TableName %> <%= Where %> <%= Limit %>;';
249
+ // Build the query
250
+ tmpQuery.buildReadQuery();
251
+ // This is the query generated by the MSSQL dialect
252
+ _Fable.log.trace('Custom Select Query', tmpQuery.query);
253
+ Expect(tmpQuery.query.body)
254
+ .to.equal('SELECT Name, Age * 5, Cost FROM `Animal` WHERE Age = :Age_w0 LIMIT 0, 10;');
255
+ }
256
+ );
257
+ test
258
+ (
259
+ 'Bad Custom Read Query',
260
+ function()
261
+ {
262
+ var tmpQuery = libFoxHound.new(_Fable)
263
+ .setDialect('MSSQL')
264
+ .setScope('Animal')
265
+ .setCap(10)
266
+ .setBegin(0)
267
+ .setDataElements(['Name', 'Age', 'Cost'])
268
+ .setSort([{Column:'Age',Direction:'Ascending'}])
269
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
270
+ tmpQuery.parameters.queryOverride = 'SELECT Name, Age * 5, Cost FROM <%= TableName <%= Where %> <%= Limit ;';
271
+ // Build the query
272
+ tmpQuery.buildReadQuery();
273
+ // This is the query generated by the MSSQL dialect
274
+ _Fable.log.trace('Custom Select Query', tmpQuery.query);
275
+ Expect(tmpQuery.query.body)
276
+ .to.equal(false);
277
+ }
278
+ );
279
+ test
280
+ (
281
+ 'Bad Custom Count Query',
282
+ function()
283
+ {
284
+ var tmpQuery = libFoxHound.new(_Fable)
285
+ .setDialect('MSSQL')
286
+ .setScope('Animal')
287
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
288
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName <%= TableName %> <%= Where;';
289
+ // Build the query
290
+ tmpQuery.buildCountQuery();
291
+ // This is the query generated by the MSSQL dialect
292
+ _Fable.log.trace('Custom Count Query', tmpQuery.query);
293
+ Expect(tmpQuery.query.body)
294
+ .to.equal(false);
295
+ }
296
+ );
297
+ test
298
+ (
299
+ 'Custom Count Query',
300
+ function()
301
+ {
302
+ var tmpQuery = libFoxHound.new(_Fable)
303
+ .setDialect('MSSQL')
304
+ .setScope('Animal')
305
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
306
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS RowCount FROM <%= TableName %> <%= Where %>;';
307
+ // Build the query
308
+ tmpQuery.buildCountQuery();
309
+ // This is the query generated by the MSSQL dialect
310
+ _Fable.log.trace('Custom Count Query', tmpQuery.query);
311
+ Expect(tmpQuery.query.body)
312
+ .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal` WHERE Age = :Age_w0;');
313
+ }
314
+ );
315
+ test
316
+ (
317
+ 'Custom Count Query with Custom Parameters',
318
+ function()
319
+ {
320
+ var tmpQuery = libFoxHound.new(_Fable)
321
+ .setDialect('MSSQL')
322
+ .setScope('Animal')
323
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
324
+ tmpQuery.parameters.CountAlias = 'RowCount';
325
+ tmpQuery.parameters.queryOverride = 'SELECT COUNT(*) AS <%= _Params.CountAlias %> FROM <%= TableName %> <%= Where %>;';
326
+ // Build the query
327
+ tmpQuery.buildCountQuery();
328
+ // This is the query generated by the MSSQL dialect
329
+ _Fable.log.trace('Custom Count Query', tmpQuery.query);
330
+ Expect(tmpQuery.query.body)
331
+ .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal` WHERE Age = :Age_w0;');
332
+ }
333
+ );
334
+ test
335
+ (
336
+ 'Update Query',
337
+ function()
338
+ {
339
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
340
+ .setLogLevel(5)
341
+ .setScope('Animal')
342
+ .addFilter('IDAnimal', 9)
343
+ .addRecord({Age:15,Color:'Brown'});
344
+
345
+ // Build the query
346
+ tmpQuery.buildUpdateQuery();
347
+ // This is the query generated by the MSSQL dialect
348
+ _Fable.log.trace('Update Query', tmpQuery.query);
349
+ Expect(tmpQuery.query.body)
350
+ .to.equal('UPDATE `Animal` SET Age = :Age_0, Color = :Color_1 WHERE IDAnimal = :IDAnimal_w0;');
351
+ }
352
+ );
353
+ test
354
+ (
355
+ 'Bad Update Query',
356
+ function()
357
+ {
358
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL');
359
+
360
+ // Build the query
361
+ tmpQuery.buildUpdateQuery();
362
+ tmpQuery.addRecord({});
363
+ tmpQuery.buildUpdateQuery();
364
+ // This is the query generated by the MSSQL dialect
365
+ _Fable.log.trace('Update Query', tmpQuery.query);
366
+ Expect(tmpQuery.query.body)
367
+ .to.equal(false);
368
+ }
369
+ );
370
+ test
371
+ (
372
+ 'Delete Query',
373
+ function()
374
+ {
375
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
376
+ .setScope('Animal')
377
+ .addFilter('IDAnimal', 10);
378
+
379
+ // Build the query
380
+ tmpQuery.buildDeleteQuery();
381
+ // This is the query generated by the MSSQL dialect
382
+ _Fable.log.trace('Delete Query', tmpQuery.query);
383
+ Expect(tmpQuery.query.body)
384
+ .to.equal('DELETE FROM `Animal` WHERE IDAnimal = :IDAnimal_w0;');
385
+ }
386
+ );
387
+ test
388
+ (
389
+ 'Count Query',
390
+ function()
391
+ {
392
+ var tmpQuery = libFoxHound.new(_Fable)
393
+ .setDialect('MSSQL')
394
+ .setScope('Animal');
395
+
396
+ // Build the query
397
+ tmpQuery.buildCountQuery();
398
+ // This is the query generated by the MSSQL dialect
399
+ _Fable.log.trace('Count Query', tmpQuery.query);
400
+ Expect(tmpQuery.query.body)
401
+ .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal`;');
402
+ }
403
+ );
404
+ test
405
+ (
406
+ 'Count Distinct Query',
407
+ function()
408
+ {
409
+ var tmpQuery = libFoxHound.new(_Fable)
410
+ .setDialect('MSSQL')
411
+ .setScope('Animal');
412
+ tmpQuery.setDistinct(true);
413
+ tmpQuery.query.schema = _AnimalSchema;
414
+
415
+ // Build the query
416
+ tmpQuery.buildCountQuery();
417
+ // This is the query generated by the MSSQL dialect
418
+ _Fable.log.trace('Count Distinct Query', tmpQuery.query);
419
+ Expect(tmpQuery.query.body)
420
+ .to.equal('SELECT COUNT(DISTINCT `Animal`.`IDAnimal`) AS RowCount FROM `Animal` WHERE `Animal`.Deleted = :Deleted_w0;');
421
+ }
422
+ );
423
+ test
424
+ (
425
+ 'Count Distinct Query without Schema',
426
+ function()
427
+ {
428
+ var tmpQuery = libFoxHound.new(_Fable)
429
+ .setDialect('MSSQL')
430
+ .setScope('Animal');
431
+ tmpQuery.setDistinct(true);
432
+
433
+ // Build the query
434
+ tmpQuery.buildCountQuery();
435
+ // This is the query generated by the MSSQL dialect
436
+ _Fable.log.trace('Count Distinct Query', tmpQuery.query);
437
+ Expect(tmpQuery.query.body)
438
+ .to.equal('SELECT COUNT(*) AS RowCount FROM `Animal`;');
439
+ }
440
+ );
441
+ test
442
+ (
443
+ 'Count Distinct Query with Custom Fields',
444
+ function()
445
+ {
446
+ var tmpQuery = libFoxHound.new(_Fable)
447
+ .setDialect('MSSQL')
448
+ .setScope('Animal')
449
+ .setDataElements(['Name', 'Age', 'Cost']);
450
+ tmpQuery.setDistinct(true);
451
+
452
+ // Build the query
453
+ tmpQuery.buildCountQuery();
454
+ // This is the query generated by the MSSQL dialect
455
+ _Fable.log.trace('Count Distinct Query', tmpQuery.query);
456
+ Expect(tmpQuery.query.body)
457
+ .to.equal('SELECT COUNT(DISTINCT `Name`, `Age`, `Cost`) AS RowCount FROM `Animal`;');
458
+ }
459
+ );
460
+ }
461
+ );
462
+
463
+ suite
464
+ (
465
+ 'Complex Query Generation - Schemas',
466
+ function()
467
+ {
468
+ test
469
+ (
470
+ 'Create Query',
471
+ function()
472
+ {
473
+ var tmpQuery = libFoxHound.new(_Fable)
474
+ .setLogLevel(5)
475
+ .setDialect('MSSQL')
476
+ .setScope('Animal')
477
+ .addRecord(
478
+ {
479
+ IDAnimal:false,
480
+ GUIDAnimal:false,
481
+ CreateDate:false,
482
+ CreatingIDUser:false,
483
+ UpdateDate:false,
484
+ UpdatingIDUser:false,
485
+ Deleted:false,
486
+ DeletingIDUser:false,
487
+ DeleteDate:false,
488
+ Name:'Froo Froo',
489
+ Age:18
490
+ });
491
+ tmpQuery.query.schema = _AnimalSchema;
492
+ // Build the query
493
+ tmpQuery.buildCreateQuery();
494
+ // This is the query generated by the MSSQL dialect
495
+ _Fable.log.trace('Create Query', tmpQuery.query);
496
+ Expect(tmpQuery.query.body)
497
+ .to.equal("INSERT INTO `Animal` ( IDAnimal, GUIDAnimal, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser, Deleted, Name, Age) VALUES ( NULL, :GUIDAnimal_1, NOW(3), :CreatingIDUser_3, NOW(3), :UpdatingIDUser_5, :Deleted_6, :Name_7, :Age_8);");
498
+ }
499
+ );
500
+ test
501
+ (
502
+ 'Create Query -- with GUID specified',
503
+ function()
504
+ {
505
+ var tmpQuery = libFoxHound.new(_Fable)
506
+ .setLogLevel(5)
507
+ .setDialect('MSSQL')
508
+ .setScope('Animal')
509
+ .addRecord(
510
+ {
511
+ IDAnimal:false,
512
+ GUIDAnimal:'0xabcdef',
513
+ CreateDate:false,
514
+ CreatingIDUser:false,
515
+ UpdateDate:false,
516
+ UpdatingIDUser:false,
517
+ Deleted:false,
518
+ DeletingIDUser:false,
519
+ DeleteDate:false,
520
+ Name:'Froo Froo',
521
+ Age:18
522
+ });
523
+ tmpQuery.query.schema = _AnimalSchema;
524
+ // Build the query
525
+ tmpQuery.buildCreateQuery();
526
+ // This is the query generated by the MSSQL dialect
527
+ _Fable.log.trace('Create Query', tmpQuery.query);
528
+ Expect(tmpQuery.query.body)
529
+ .to.equal("INSERT INTO `Animal` ( IDAnimal, GUIDAnimal, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser, Deleted, Name, Age) VALUES ( NULL, :GUIDAnimal_1, NOW(3), :CreatingIDUser_3, NOW(3), :UpdatingIDUser_5, :Deleted_6, :Name_7, :Age_8);");
530
+ }
531
+ );
532
+ test
533
+ (
534
+ 'Create Query - with AutoIdentity disabled',
535
+ function()
536
+ {
537
+ var tmpQuery = libFoxHound.new(_Fable)
538
+ .setLogLevel(5)
539
+ .setDialect('MSSQL')
540
+ .setScope('Animal')
541
+ .setDisableAutoIdentity(true)
542
+ .setDisableDeleteTracking(true)
543
+ .setDisableAutoDateStamp(true)
544
+ .setDisableAutoUserStamp(true)
545
+ .addRecord(
546
+ {
547
+ IDAnimal:false,
548
+ GUIDAnimal:false,
549
+ CreateDate:false,
550
+ CreatingIDUser:false,
551
+ UpdateDate:false,
552
+ UpdatingIDUser:false,
553
+ Deleted:false,
554
+ DeletingIDUser:false,
555
+ DeleteDate:false,
556
+ Name:'Froo Froo',
557
+ Age:18
558
+ });
559
+ tmpQuery.query.schema = _AnimalSchema;
560
+ // Build the query
561
+ tmpQuery.buildCreateQuery();
562
+ // This is the query generated by the MSSQL dialect
563
+ _Fable.log.trace('Create Query (AutoIdentity disabled)', tmpQuery.query);
564
+ Expect(tmpQuery.query.body)
565
+ .to.equal("INSERT INTO `Animal` ( IDAnimal, GUIDAnimal, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser, Deleted, DeletingIDUser, DeleteDate, Name, Age) VALUES ( :IDAnimal_0, :GUIDAnimal_1, :CreateDate_2, :CreatingIDUser_3, :UpdateDate_4, :UpdatingIDUser_5, :Deleted_6, :DeletingIDUser_7, :DeleteDate_8, :Name_9, :Age_10);");
566
+ }
567
+ );
568
+ test
569
+ (
570
+ 'Complex Read Query 2, verify checking Deleted bit with no filters',
571
+ function()
572
+ {
573
+ var tmpQuery = libFoxHound.new(_Fable)
574
+ .setDialect('MSSQL')
575
+ .setScope('Animal')
576
+ .setDataElements(['Name', 'Age', 'Cost'])
577
+ .setCap(100);
578
+
579
+ //Use a schema that already defines a deleted bit
580
+ tmpQuery.query.schema = _AnimalSchema;
581
+ // Build the query
582
+ tmpQuery.buildReadQuery();
583
+ // This is the query generated by the MSSQL dialect
584
+ _Fable.log.trace('Select Query', tmpQuery.query);
585
+ Expect(tmpQuery.query.body)
586
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` WHERE `Animal`.Deleted = :Deleted_w0 LIMIT 100;');
587
+ }
588
+ );
589
+ test
590
+ (
591
+ 'Complex Read Query 2, verify checking Deleted bit with no filters, with Distinct',
592
+ function()
593
+ {
594
+ var tmpQuery = libFoxHound.new(_Fable)
595
+ .setDialect('MSSQL')
596
+ .setScope('Animal')
597
+ .setDataElements(['Name', 'Age', 'Cost'])
598
+ .setCap(100)
599
+ .setDistinct(true);
600
+
601
+ //Use a schema that already defines a deleted bit
602
+ tmpQuery.query.schema = _AnimalSchema;
603
+ // Build the query
604
+ tmpQuery.buildReadQuery();
605
+ // This is the query generated by the MSSQL dialect
606
+ _Fable.log.trace('Select Query', tmpQuery.query);
607
+ Expect(tmpQuery.query.body)
608
+ .to.equal('SELECT DISTINCT `Name`, `Age`, `Cost` FROM `Animal` WHERE `Animal`.Deleted = :Deleted_w0 LIMIT 100;');
609
+ }
610
+ );
611
+ test
612
+ (
613
+ 'Complex Read Query 2, manually checking Deleted bit with Schema that has one',
614
+ function()
615
+ {
616
+ var tmpQuery = libFoxHound.new(_Fable)
617
+ .setDialect('MSSQL')
618
+ .setScope('Animal')
619
+ .setDataElements(['Name', 'Age', 'Cost'])
620
+ .setCap(100)
621
+ .addFilter('Age', '25')
622
+ .addFilter('', '', '(')
623
+ .addFilter('Color', 'Red')
624
+ .addFilter('Color', 'Green', '=', 'OR')
625
+ .addFilter('', '', ')')
626
+ .addFilter('Description', '', 'IS NOT NULL')
627
+ .addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN')
628
+ .addFilter('Deleted', '1');
629
+
630
+ //Use a schema that already defines a deleted bit
631
+ tmpQuery.query.schema = _AnimalSchema;
632
+ // Build the query
633
+ tmpQuery.buildReadQuery();
634
+ // This is the query generated by the MSSQL dialect
635
+ _Fable.log.trace('Select Query', tmpQuery.query);
636
+ Expect(tmpQuery.query.body)
637
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` WHERE Age = :Age_w0 AND ( Color = :Color_w2 OR Color = :Color_w3 ) AND Description IS NOT NULL AND IDOffice IN ( :IDOffice_w6 ) AND Deleted = :Deleted_w7 LIMIT 100;');
638
+ }
639
+ );
640
+ test
641
+ (
642
+ 'Complex Read Query 2, delete tracking disabled',
643
+ function()
644
+ {
645
+ var tmpQuery = libFoxHound.new(_Fable)
646
+ .setDialect('MSSQL')
647
+ .setScope('Animal')
648
+ .setDisableDeleteTracking(true)
649
+ .setDataElements(['Name', 'Age', 'Cost'])
650
+ .setCap(100);
651
+
652
+ //Use a schema that already defines a deleted bit
653
+ tmpQuery.query.schema = _AnimalSchema;
654
+ // Build the query
655
+ tmpQuery.buildReadQuery();
656
+ // This is the query generated by the MSSQL dialect
657
+ _Fable.log.trace('Select Query', tmpQuery.query);
658
+ Expect(tmpQuery.query.body)
659
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` LIMIT 100;');
660
+ }
661
+ );
662
+ test
663
+ (
664
+ 'Delete Query with Filters',
665
+ function()
666
+ {
667
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
668
+ .setScope('Animal')
669
+ .addFilter('IDAnimal', 10);
670
+ //Perform delete with no record specified, but has a Deleted bit in the schema
671
+
672
+ //Use a schema that already defines a deleted bit
673
+ tmpQuery.query.schema = _AnimalSchema;
674
+
675
+ // Build the query
676
+ tmpQuery.buildDeleteQuery();
677
+ // This is the query generated by the MSSQL dialect
678
+ _Fable.log.trace('Delete Query', tmpQuery.query);
679
+ Expect(tmpQuery.query.body)
680
+ .to.equal('UPDATE `Animal` SET UpdateDate = NOW(3), Deleted = 1, DeletingIDUser = :DeletingIDUser_2, DeleteDate = NOW(3) WHERE IDAnimal = :IDAnimal_w0 AND `Animal`.Deleted = :Deleted_w1;');
681
+ }
682
+ );
683
+ test
684
+ (
685
+ 'Update Query -- without Deleted',
686
+ function()
687
+ {
688
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
689
+ .setLogLevel(5)
690
+ .setScope('Animal')
691
+ .addFilter('IDAnimal', 9)
692
+ .addRecord({
693
+ IDAnimal:82,
694
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
695
+ CreateDate:false,
696
+ CreatingIDUser:false,
697
+ UpdateDate:false,
698
+ UpdatingIDUser:false,
699
+ Name:'Froo Froo',
700
+ Age:18
701
+ });
702
+ tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
703
+ // Build the query
704
+ tmpQuery.buildUpdateQuery();
705
+ // This is the query generated by the MSSQL dialect
706
+ _Fable.log.trace('Update Query', tmpQuery.query);
707
+ Expect(tmpQuery.query.body)
708
+ .to.equal('UPDATE `Animal` SET GUIDAnimal = :GUIDAnimal_0, UpdateDate = NOW(3), UpdatingIDUser = :UpdatingIDUser_2, Name = :Name_3, Age = :Age_4 WHERE IDAnimal = :IDAnimal_w0;');
709
+ }
710
+ );
711
+ test
712
+ (
713
+ 'Update Query -- without Deleted, UpdateDate and UpdatingIDUser',
714
+ function()
715
+ {
716
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
717
+ .setLogLevel(5)
718
+ .setScope('Animal')
719
+ .addFilter('IDAnimal', 9)
720
+ .setDisableAutoUserStamp(true)
721
+ .setDisableAutoDateStamp(true)
722
+ .addRecord({
723
+ IDAnimal:82,
724
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
725
+ CreateDate:false,
726
+ CreatingIDUser:false,
727
+ UpdateDate:false,
728
+ UpdatingIDUser:false,
729
+ Name:'Froo Froo',
730
+ Age:18
731
+ });
732
+ tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
733
+ // Build the query
734
+ tmpQuery.buildUpdateQuery();
735
+ // This is the query generated by the MSSQL dialect
736
+ _Fable.log.trace('Update Query', tmpQuery.query);
737
+ Expect(tmpQuery.query.body)
738
+ .to.equal('UPDATE `Animal` SET GUIDAnimal = :GUIDAnimal_0, Name = :Name_1, Age = :Age_2 WHERE IDAnimal = :IDAnimal_w0;');
739
+ }
740
+ );
741
+ test
742
+ (
743
+ 'Delete Query -- without Deleted',
744
+ function()
745
+ {
746
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
747
+ .setLogLevel(5)
748
+ .setScope('Animal')
749
+ .addFilter('IDAnimal', 9)
750
+ .addRecord({
751
+ IDAnimal:82,
752
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
753
+ });
754
+ tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
755
+ // Build the query
756
+ tmpQuery.buildDeleteQuery();
757
+ // This is the query generated by the MSSQL dialect
758
+ _Fable.log.trace('Delete Query', tmpQuery.query);
759
+ Expect(tmpQuery.query.body)
760
+ .to.equal('DELETE FROM `Animal` WHERE IDAnimal = :IDAnimal_w0;');
761
+ }
762
+ );
763
+ test
764
+ (
765
+ 'Update Query',
766
+ function()
767
+ {
768
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
769
+ .setLogLevel(5)
770
+ .setScope('Animal')
771
+ .addFilter('IDAnimal', 9)
772
+ .addFilter('Deleted', 0) //cover case where this can be overridden instead of automatically added
773
+ .addRecord({
774
+ IDAnimal:82,
775
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
776
+ CreateDate:false,
777
+ CreatingIDUser:false,
778
+ UpdateDate:false,
779
+ UpdatingIDUser:false,
780
+ Deleted:false,
781
+ DeletingIDUser:false,
782
+ DeleteDate:false,
783
+ Name:'Froo Froo',
784
+ Age:18
785
+ });
786
+ tmpQuery.query.schema = _AnimalSchema;
787
+ // Build the query
788
+ tmpQuery.buildUpdateQuery();
789
+ // This is the query generated by the MSSQL dialect
790
+ _Fable.log.trace('Update Query', tmpQuery.query);
791
+ Expect(tmpQuery.query.body)
792
+ .to.equal('UPDATE `Animal` SET GUIDAnimal = :GUIDAnimal_0, UpdateDate = NOW(3), UpdatingIDUser = :UpdatingIDUser_2, Deleted = :Deleted_3, Name = :Name_4, Age = :Age_5 WHERE IDAnimal = :IDAnimal_w0 AND Deleted = :Deleted_w1;');
793
+ }
794
+ );
795
+ test
796
+ (
797
+ 'Delete Query',
798
+ function()
799
+ {
800
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
801
+ .setLogLevel(5)
802
+ .setScope('Animal')
803
+ .addFilter('IDAnimal', 9)
804
+ .addRecord({
805
+ IDAnimal:82,
806
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
807
+ });
808
+ tmpQuery.query.schema = _AnimalSchema;
809
+ // Build the query 
810
+ tmpQuery.buildDeleteQuery();
811
+ // This is the query generated by the MSSQL dialect
812
+ _Fable.log.trace('Delete Query', tmpQuery.query);
813
+ Expect(tmpQuery.query.body)
814
+ .to.equal('UPDATE `Animal` SET UpdateDate = NOW(3), Deleted = 1, DeletingIDUser = :DeletingIDUser_2, DeleteDate = NOW(3) WHERE IDAnimal = :IDAnimal_w0 AND `Animal`.Deleted = :Deleted_w1;');
815
+ }
816
+ );
817
+ test
818
+ (
819
+ 'Delete Query with Delete Tracking Disabled',
820
+ function()
821
+ {
822
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
823
+ .setLogLevel(5)
824
+ .setScope('Animal')
825
+ .setDisableDeleteTracking(true)
826
+ .addFilter('IDAnimal', 9)
827
+ .addRecord({
828
+ IDAnimal:82,
829
+ GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777'
830
+ });
831
+ tmpQuery.query.schema = _AnimalSchema;
832
+ // Build the query
833
+ tmpQuery.buildDeleteQuery();
834
+ // This is the query generated by the MSSQL dialect
835
+ _Fable.log.trace('Delete Query', tmpQuery.query);
836
+ Expect(tmpQuery.query.body)
837
+ .to.equal('DELETE FROM `Animal` WHERE IDAnimal = :IDAnimal_w0;');
838
+ }
839
+ );
840
+ test
841
+ (
842
+ 'Undelete Query with Deleted Bit',
843
+ function()
844
+ {
845
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
846
+ .setScope('Animal')
847
+ .addFilter('IDAnimal', 10);
848
+
849
+ //Use a schema that already defines a deleted bit
850
+ tmpQuery.query.schema = _AnimalSchema;
851
+
852
+ // Build the query
853
+ tmpQuery.buildUndeleteQuery();
854
+ // This is the query generated by the MSSQL dialect
855
+ _Fable.log.trace('Undelete Query', tmpQuery.query);
856
+ Expect(tmpQuery.query.body)
857
+ .to.equal('UPDATE `Animal` SET UpdateDate = NOW(3), UpdatingIDUser = :UpdatingIDUser_1, Deleted = 0 WHERE IDAnimal = :IDAnimal_w0;');
858
+ }
859
+ );
860
+ test
861
+ (
862
+ 'Undelete Query without Deleted Bit',
863
+ function()
864
+ {
865
+ var tmpQuery = libFoxHound.new(_Fable).setDialect('MSSQL')
866
+ .setScope('Animal')
867
+ .addFilter('IDAnimal', 10);
868
+
869
+ // Build the query
870
+ tmpQuery.buildUndeleteQuery();
871
+ // This is the query generated by the MSSQL dialect
872
+ _Fable.log.trace('Undelete Query', tmpQuery.query);
873
+ Expect(tmpQuery.query.body)
874
+ .to.equal('SELECT NULL;');
875
+ }
876
+ );
877
+ }
878
+ );
879
+
880
+ suite
881
+ (
882
+ 'Join Query Generation',
883
+ function()
884
+ {
885
+ test
886
+ (
887
+ 'Join Read Query',
888
+ function()
889
+ {
890
+ var tmpQuery = libFoxHound.new(_Fable)
891
+ .setDialect('MSSQL')
892
+ .setScope('Animal')
893
+ .setCap(10)
894
+ .setBegin(0)
895
+ .setDataElements(['Name', 'Age', 'Cost'])
896
+ .setSort([{Column:'Age',Direction:'Ascending'}])
897
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'})
898
+ .setJoin({Table: 'Test', From:'Test.IDAnimal', To: 'Animal.IDAnimal'});
899
+
900
+ // Build the query
901
+ tmpQuery.buildReadQuery();
902
+ // This is the query generated by the MSSQL dialect
903
+ _Fable.log.trace('Select Query', tmpQuery.query);
904
+ Expect(tmpQuery.query.body)
905
+ .to.equal('SELECT `Name`, `Age`, `Cost` FROM `Animal` INNER JOIN Test ON Test.IDAnimal = Animal.IDAnimal WHERE Age = :Age_w0 ORDER BY Age LIMIT 0, 10;');
906
+ }
907
+ );
908
+ test
909
+ (
910
+ 'Join Read Query with Distinct',
911
+ function()
912
+ {
913
+ var tmpQuery = libFoxHound.new(_Fable)
914
+ .setDialect('MSSQL')
915
+ .setScope('Animal')
916
+ .setCap(10)
917
+ .setBegin(0)
918
+ .setDataElements(['Name', 'Age', 'Cost'])
919
+ .setSort([{Column:'Age',Direction:'Ascending'}])
920
+ .setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'})
921
+ .setJoin({Table: 'Test', From:'Test.IDAnimal', To: 'Animal.IDAnimal'})
922
+ .setDistinct(true);
923
+
924
+ // Build the query
925
+ tmpQuery.buildReadQuery();
926
+ // This is the query generated by the MSSQL dialect
927
+ _Fable.log.trace('Select Query', tmpQuery.query);
928
+ Expect(tmpQuery.query.body)
929
+ .to.equal('SELECT DISTINCT `Name`, `Age`, `Cost` FROM `Animal` INNER JOIN Test ON Test.IDAnimal = Animal.IDAnimal WHERE Age = :Age_w0 ORDER BY Age LIMIT 0, 10;');
930
+ }
931
+ );
932
+ test
933
+ (
934
+ 'Bad Join Read Query',
935
+ function()
936
+ {
937
+ var tmpQuery = libFoxHound.new(_Fable)
938
+ .setDialect('MSSQL')
939
+ .setScope('Animal')
940
+ .setJoin({Table: 'Test', From:'Bad.IDAnimal', To: 'Animal.IDAnimal'});
941
+
942
+ // Build the query
943
+ tmpQuery.buildReadQuery();
944
+ // This is the query generated by the MSSQL dialect
945
+ _Fable.log.trace('Select Query', tmpQuery.query);
946
+ Expect(tmpQuery.query.body)
947
+ .to.equal('SELECT `Animal`.* FROM `Animal`;'); //bad join is ignored, warn log is generated
948
+ }
949
+ );
950
+ }
951
+ );
952
+ }
953
+ );