foxhound 2.0.27 → 2.0.28
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/README.md +5 -3
- package/docs/README.md +4 -4
- package/docs/_brand.json +18 -0
- package/docs/_cover.md +1 -1
- package/docs/_topbar.md +1 -1
- package/docs/_version.json +3 -3
- package/docs/api/README.md +14 -14
- package/docs/dialects/README.md +5 -5
- package/docs/index.html +6 -7
- package/docs/quickstart.md +1 -1
- package/docs/retold-catalog.json +245 -161
- package/docs/retold-keyword-index.json +11916 -6383
- package/docs/schema.md +1 -1
- package/package.json +7 -7
- package/source/Foxhound-Dialects.js +1 -0
- package/source/dialects/Oracle/FoxHound-Dialect-Oracle.js +1218 -0
- package/test/Foxhound-Dialect-Oracle_tests.js +463 -0
- package/docs/css/docuserve.css +0 -327
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for FoxHound Oracle Dialect
|
|
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
|
+
|
|
12
|
+
var libFable = require('fable');
|
|
13
|
+
const _Fable = new libFable({Product:'FoxhoundTestsOracle'});
|
|
14
|
+
var libFoxHound = require('../source/FoxHound.js');
|
|
15
|
+
|
|
16
|
+
var _AnimalSchema = (
|
|
17
|
+
[
|
|
18
|
+
{ Column: "IDAnimal", Type:"AutoIdentity" },
|
|
19
|
+
{ Column: "GUIDAnimal", Type:"AutoGUID" },
|
|
20
|
+
{ Column: "CreateDate", Type:"CreateDate" },
|
|
21
|
+
{ Column: "CreatingIDUser", Type:"CreateIDUser" },
|
|
22
|
+
{ Column: "UpdateDate", Type:"UpdateDate" },
|
|
23
|
+
{ Column: "UpdatingIDUser", Type:"UpdateIDUser" },
|
|
24
|
+
{ Column: "Deleted", Type:"Deleted" },
|
|
25
|
+
{ Column: "DeletingIDUser", Type:"DeleteIDUser" },
|
|
26
|
+
{ Column: "DeleteDate", Type:"DeleteDate" },
|
|
27
|
+
{ Column: "Name", Type:"String" },
|
|
28
|
+
{ Column: "Age", Type:"Integer" }
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
var _AnimalSchemaWithoutDeleted = (
|
|
32
|
+
[
|
|
33
|
+
{ Column: "IDAnimal", Type:"AutoIdentity" },
|
|
34
|
+
{ Column: "GUIDAnimal", Type:"AutoGUID" },
|
|
35
|
+
{ Column: "CreateDate", Type:"CreateDate" },
|
|
36
|
+
{ Column: "CreatingIDUser", Type:"CreateIDUser" },
|
|
37
|
+
{ Column: "UpdateDate", Type:"UpdateDate" },
|
|
38
|
+
{ Column: "UpdatingIDUser", Type:"UpdateIDUser" }
|
|
39
|
+
]);
|
|
40
|
+
|
|
41
|
+
suite
|
|
42
|
+
(
|
|
43
|
+
'FoxHound-Dialect-Oracle',
|
|
44
|
+
function()
|
|
45
|
+
{
|
|
46
|
+
suite
|
|
47
|
+
(
|
|
48
|
+
'Object Sanity',
|
|
49
|
+
function()
|
|
50
|
+
{
|
|
51
|
+
test
|
|
52
|
+
(
|
|
53
|
+
'initialize should build a happy little object',
|
|
54
|
+
function()
|
|
55
|
+
{
|
|
56
|
+
var testFoxHound = libFoxHound.new(_Fable).setDialect('Oracle');
|
|
57
|
+
Expect(testFoxHound.dialect.name)
|
|
58
|
+
.to.equal('Oracle');
|
|
59
|
+
Expect(testFoxHound)
|
|
60
|
+
.to.be.an('object', 'FoxHound with Oracle should initialize as an object directly from the require statement.');
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
suite
|
|
67
|
+
(
|
|
68
|
+
'Create Query Generation',
|
|
69
|
+
function()
|
|
70
|
+
{
|
|
71
|
+
test
|
|
72
|
+
(
|
|
73
|
+
'Create Query without schema parameterizes every column and has no RETURNING',
|
|
74
|
+
function()
|
|
75
|
+
{
|
|
76
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
77
|
+
.setDialect('Oracle')
|
|
78
|
+
.setScope('Animal')
|
|
79
|
+
.addRecord({IDAnimal:null, Name:'Foo Foo', Age:15});
|
|
80
|
+
tmpQuery.buildCreateQuery();
|
|
81
|
+
Expect(tmpQuery.query.body)
|
|
82
|
+
.to.equal("INSERT INTO Animal ( IDAnimal, Name, Age) VALUES ( :IDAnimal_0, :Name_1, :Age_2)");
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
test
|
|
86
|
+
(
|
|
87
|
+
'Create Query with schema skips AutoIdentity and appends RETURNING INTO',
|
|
88
|
+
function()
|
|
89
|
+
{
|
|
90
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
91
|
+
.setDialect('Oracle')
|
|
92
|
+
.setScope('Animal')
|
|
93
|
+
.addRecord({IDAnimal:null, Name:'Foo Foo', Age:15});
|
|
94
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
95
|
+
tmpQuery.buildCreateQuery();
|
|
96
|
+
Expect(tmpQuery.query.body)
|
|
97
|
+
.to.equal("INSERT INTO Animal ( Name, Age) VALUES ( :Name_0, :Age_1) RETURNING IDAnimal INTO :RETURNING_ID");
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
test
|
|
101
|
+
(
|
|
102
|
+
'Bad Create Query returns false',
|
|
103
|
+
function()
|
|
104
|
+
{
|
|
105
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle');
|
|
106
|
+
tmpQuery.buildCreateQuery();
|
|
107
|
+
tmpQuery.addRecord({});
|
|
108
|
+
tmpQuery.buildCreateQuery();
|
|
109
|
+
Expect(tmpQuery.query.body)
|
|
110
|
+
.to.equal(false);
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
suite
|
|
117
|
+
(
|
|
118
|
+
'Read Query Generation',
|
|
119
|
+
function()
|
|
120
|
+
{
|
|
121
|
+
test
|
|
122
|
+
(
|
|
123
|
+
'Simple Read Query (no quoting)',
|
|
124
|
+
function()
|
|
125
|
+
{
|
|
126
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle').setScope('Animal');
|
|
127
|
+
tmpQuery.addSort({Column:'Cost',Direction:'Descending'});
|
|
128
|
+
tmpQuery.buildReadQuery();
|
|
129
|
+
Expect(tmpQuery.query.body)
|
|
130
|
+
.to.equal('SELECT Animal.* FROM Animal ORDER BY Cost DESC');
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
test
|
|
134
|
+
(
|
|
135
|
+
'Read Query with named binds and OFFSET/FETCH pagination',
|
|
136
|
+
function()
|
|
137
|
+
{
|
|
138
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
139
|
+
.setDialect('Oracle')
|
|
140
|
+
.setScope('Animal')
|
|
141
|
+
.setDataElements(['Name', 'Age'])
|
|
142
|
+
.setCap(10)
|
|
143
|
+
.setBegin(0)
|
|
144
|
+
.addFilter('Age', '15')
|
|
145
|
+
.addSort('Age');
|
|
146
|
+
tmpQuery.buildReadQuery();
|
|
147
|
+
Expect(tmpQuery.query.body)
|
|
148
|
+
.to.equal('SELECT Name, Age FROM Animal WHERE Age = :Age_w0 ORDER BY Age OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY');
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
test
|
|
152
|
+
(
|
|
153
|
+
'Complex Read Query expands IN lists into discrete binds',
|
|
154
|
+
function()
|
|
155
|
+
{
|
|
156
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
157
|
+
.setDialect('Oracle')
|
|
158
|
+
.setScope('Animal')
|
|
159
|
+
.setDataElements(['Name', 'Age', 'Cost'])
|
|
160
|
+
.setCap(100)
|
|
161
|
+
.addFilter('Age', '25')
|
|
162
|
+
.addFilter('', '', '(')
|
|
163
|
+
.addFilter('Color', 'Red')
|
|
164
|
+
.addFilter('Color', 'Green', '=', 'OR')
|
|
165
|
+
.addFilter('', '', ')')
|
|
166
|
+
.addFilter('Description', '', 'IS NOT NULL')
|
|
167
|
+
.addFilter('IDOffice', [10, 11, 15, 18, 22], 'IN');
|
|
168
|
+
tmpQuery.addSort('Age');
|
|
169
|
+
tmpQuery.buildReadQuery();
|
|
170
|
+
Expect(tmpQuery.query.body)
|
|
171
|
+
.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_0, :IDOffice_w6_1, :IDOffice_w6_2, :IDOffice_w6_3, :IDOffice_w6_4) ORDER BY Age OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY');
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
test
|
|
175
|
+
(
|
|
176
|
+
'Read Query with schema injects soft-delete filter and PK ORDER BY',
|
|
177
|
+
function()
|
|
178
|
+
{
|
|
179
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
180
|
+
.setDialect('Oracle')
|
|
181
|
+
.setScope('Animal')
|
|
182
|
+
.setDataElements(['Name', 'Age', 'Cost'])
|
|
183
|
+
.setCap(100);
|
|
184
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
185
|
+
tmpQuery.buildReadQuery();
|
|
186
|
+
Expect(tmpQuery.query.body)
|
|
187
|
+
.to.equal('SELECT Name, Age, Cost FROM Animal WHERE Deleted = :Deleted_w0 ORDER BY IDAnimal OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY');
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
test
|
|
191
|
+
(
|
|
192
|
+
'Read Query with quoteIdentifiers wraps identifiers in double quotes',
|
|
193
|
+
function()
|
|
194
|
+
{
|
|
195
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
196
|
+
.setDialect('Oracle')
|
|
197
|
+
.setScope('Animal')
|
|
198
|
+
.setDataElements(['Name', 'Age'])
|
|
199
|
+
.addSort('Age');
|
|
200
|
+
tmpQuery.parameters.quoteIdentifiers = true;
|
|
201
|
+
tmpQuery.buildReadQuery();
|
|
202
|
+
Expect(tmpQuery.query.body)
|
|
203
|
+
.to.equal('SELECT "Name", "Age" FROM "Animal" ORDER BY "Age"');
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
test
|
|
207
|
+
(
|
|
208
|
+
'Custom Read Query honors the query override template',
|
|
209
|
+
function()
|
|
210
|
+
{
|
|
211
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
212
|
+
.setDialect('Oracle')
|
|
213
|
+
.setScope('Animal')
|
|
214
|
+
.setCap(10)
|
|
215
|
+
.setBegin(0)
|
|
216
|
+
.setDataElements(['Name', 'Age', 'Cost'])
|
|
217
|
+
.setFilter({Column:'Age',Operator:'=',Value:'15',Connector:'AND',Parameter:'Age'});
|
|
218
|
+
tmpQuery.parameters.queryOverride = 'SELECT Name, Age * 5, Cost FROM <%= TableName %> <%= Where %> <%= Limit %>';
|
|
219
|
+
tmpQuery.buildReadQuery();
|
|
220
|
+
Expect(tmpQuery.query.body)
|
|
221
|
+
.to.equal('SELECT Name, Age * 5, Cost FROM Animal WHERE Age = :Age_w0 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY');
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
suite
|
|
228
|
+
(
|
|
229
|
+
'Legacy Pagination (ROWNUM double-subquery)',
|
|
230
|
+
function()
|
|
231
|
+
{
|
|
232
|
+
test
|
|
233
|
+
(
|
|
234
|
+
'legacyPagination wraps the query in a ROWNUM subquery (caller sort)',
|
|
235
|
+
function()
|
|
236
|
+
{
|
|
237
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
238
|
+
.setDialect('Oracle')
|
|
239
|
+
.setScope('Animal')
|
|
240
|
+
.setDataElements(['Name', 'Age', 'Cost'])
|
|
241
|
+
.setCap(10)
|
|
242
|
+
.setBegin(20)
|
|
243
|
+
.addSort('Age');
|
|
244
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
245
|
+
tmpQuery.parameters.legacyPagination = true;
|
|
246
|
+
tmpQuery.buildReadQuery();
|
|
247
|
+
Expect(tmpQuery.query.body)
|
|
248
|
+
.to.equal('SELECT Name, Age, Cost FROM (SELECT meadow_inner.*, ROWNUM AS "_RowNum" FROM (SELECT Name, Age, Cost FROM Animal WHERE Deleted = :Deleted_w0 ORDER BY Age) meadow_inner WHERE ROWNUM <= 30) WHERE "_RowNum" > 20');
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
test
|
|
252
|
+
(
|
|
253
|
+
'legacyPagination injects PK ORDER BY when caller omits sort',
|
|
254
|
+
function()
|
|
255
|
+
{
|
|
256
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
257
|
+
.setDialect('Oracle')
|
|
258
|
+
.setScope('Animal')
|
|
259
|
+
.setDataElements(['Name', 'Age', 'Cost'])
|
|
260
|
+
.setCap(10);
|
|
261
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
262
|
+
tmpQuery.parameters.legacyPagination = true;
|
|
263
|
+
tmpQuery.buildReadQuery();
|
|
264
|
+
Expect(tmpQuery.query.body)
|
|
265
|
+
.to.equal('SELECT Name, Age, Cost FROM (SELECT meadow_inner.*, ROWNUM AS "_RowNum" FROM (SELECT Name, Age, Cost FROM Animal WHERE Deleted = :Deleted_w0 ORDER BY IDAnimal) meadow_inner WHERE ROWNUM <= 10) WHERE "_RowNum" > 0');
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
test
|
|
269
|
+
(
|
|
270
|
+
'legacyPagination is inert without a cap',
|
|
271
|
+
function()
|
|
272
|
+
{
|
|
273
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
274
|
+
.setDialect('Oracle')
|
|
275
|
+
.setScope('Animal')
|
|
276
|
+
.setDataElements(['Name']);
|
|
277
|
+
tmpQuery.parameters.legacyPagination = true;
|
|
278
|
+
tmpQuery.buildReadQuery();
|
|
279
|
+
Expect(tmpQuery.query.body)
|
|
280
|
+
.to.equal('SELECT Name FROM Animal');
|
|
281
|
+
}
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
suite
|
|
287
|
+
(
|
|
288
|
+
'Update / Delete / Undelete Query Generation',
|
|
289
|
+
function()
|
|
290
|
+
{
|
|
291
|
+
test
|
|
292
|
+
(
|
|
293
|
+
'Update Query auto-stamps UpdateDate with SYS_EXTRACT_UTC',
|
|
294
|
+
function()
|
|
295
|
+
{
|
|
296
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
297
|
+
.setScope('Animal')
|
|
298
|
+
.addFilter('IDAnimal', 9)
|
|
299
|
+
.addRecord({
|
|
300
|
+
IDAnimal:82,
|
|
301
|
+
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
|
|
302
|
+
CreateDate:false,
|
|
303
|
+
CreatingIDUser:false,
|
|
304
|
+
UpdateDate:false,
|
|
305
|
+
UpdatingIDUser:false,
|
|
306
|
+
Name:'Froo Froo',
|
|
307
|
+
Age:18
|
|
308
|
+
});
|
|
309
|
+
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
|
|
310
|
+
tmpQuery.buildUpdateQuery();
|
|
311
|
+
Expect(tmpQuery.query.body)
|
|
312
|
+
.to.equal('UPDATE Animal SET GUIDAnimal = :GUIDAnimal_0, UpdateDate = SYS_EXTRACT_UTC(SYSTIMESTAMP), UpdatingIDUser = :UpdatingIDUser_2, Name = :Name_3, Age = :Age_4 WHERE IDAnimal = :IDAnimal_w0');
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
test
|
|
316
|
+
(
|
|
317
|
+
'Update Query with disabled stamps parameterizes UpdateDate',
|
|
318
|
+
function()
|
|
319
|
+
{
|
|
320
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
321
|
+
.setScope('Animal')
|
|
322
|
+
.addFilter('IDAnimal', 9)
|
|
323
|
+
.setDisableAutoUserStamp(true)
|
|
324
|
+
.setDisableAutoDateStamp(true)
|
|
325
|
+
.addRecord({
|
|
326
|
+
IDAnimal:82,
|
|
327
|
+
GUIDAnimal:'1111-2222-3333-4444-5555-6666-7777',
|
|
328
|
+
CreateDate:false,
|
|
329
|
+
CreatingIDUser:false,
|
|
330
|
+
UpdateDate:false,
|
|
331
|
+
UpdatingIDUser:false,
|
|
332
|
+
Name:'Froo Froo',
|
|
333
|
+
Age:18
|
|
334
|
+
});
|
|
335
|
+
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
|
|
336
|
+
tmpQuery.buildUpdateQuery();
|
|
337
|
+
Expect(tmpQuery.query.body)
|
|
338
|
+
.to.equal('UPDATE Animal SET GUIDAnimal = :GUIDAnimal_0, UpdateDate = :MANUAL_UpdateDate, Name = :Name_2, Age = :Age_3 WHERE IDAnimal = :IDAnimal_w0');
|
|
339
|
+
}
|
|
340
|
+
);
|
|
341
|
+
test
|
|
342
|
+
(
|
|
343
|
+
'Delete Query converts to soft-delete UPDATE when a Deleted column exists',
|
|
344
|
+
function()
|
|
345
|
+
{
|
|
346
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
347
|
+
.setScope('Animal')
|
|
348
|
+
.addFilter('IDAnimal', 10);
|
|
349
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
350
|
+
tmpQuery.buildDeleteQuery();
|
|
351
|
+
Expect(tmpQuery.query.body)
|
|
352
|
+
.to.equal('UPDATE Animal SET UpdateDate = SYS_EXTRACT_UTC(SYSTIMESTAMP), Deleted = 1, DeletingIDUser = :DeletingIDUser_2, DeleteDate = SYS_EXTRACT_UTC(SYSTIMESTAMP) WHERE IDAnimal = :IDAnimal_w0 AND Deleted = :Deleted_w1');
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
test
|
|
356
|
+
(
|
|
357
|
+
'Delete Query is a hard DELETE when there is no Deleted column',
|
|
358
|
+
function()
|
|
359
|
+
{
|
|
360
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
361
|
+
.setScope('Animal')
|
|
362
|
+
.addFilter('IDAnimal', 9)
|
|
363
|
+
.addRecord({IDAnimal:82, GUIDAnimal:'1111-2222'});
|
|
364
|
+
tmpQuery.query.schema = _AnimalSchemaWithoutDeleted;
|
|
365
|
+
tmpQuery.buildDeleteQuery();
|
|
366
|
+
Expect(tmpQuery.query.body)
|
|
367
|
+
.to.equal('DELETE FROM Animal WHERE IDAnimal = :IDAnimal_w0');
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
test
|
|
371
|
+
(
|
|
372
|
+
'Delete Query is a hard DELETE when delete tracking is disabled',
|
|
373
|
+
function()
|
|
374
|
+
{
|
|
375
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
376
|
+
.setScope('Animal')
|
|
377
|
+
.setDisableDeleteTracking(true)
|
|
378
|
+
.addFilter('IDAnimal', 9)
|
|
379
|
+
.addRecord({IDAnimal:82, GUIDAnimal:'1111-2222'});
|
|
380
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
381
|
+
tmpQuery.buildDeleteQuery();
|
|
382
|
+
Expect(tmpQuery.query.body)
|
|
383
|
+
.to.equal('DELETE FROM Animal WHERE IDAnimal = :IDAnimal_w0');
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
test
|
|
387
|
+
(
|
|
388
|
+
'Undelete Query clears the Deleted bit',
|
|
389
|
+
function()
|
|
390
|
+
{
|
|
391
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
392
|
+
.setScope('Animal')
|
|
393
|
+
.addFilter('IDAnimal', 10);
|
|
394
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
395
|
+
tmpQuery.buildUndeleteQuery();
|
|
396
|
+
Expect(tmpQuery.query.body)
|
|
397
|
+
.to.equal('UPDATE Animal SET UpdateDate = SYS_EXTRACT_UTC(SYSTIMESTAMP), UpdatingIDUser = :UpdatingIDUser_1, Deleted = 0 WHERE IDAnimal = :IDAnimal_w0');
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
suite
|
|
404
|
+
(
|
|
405
|
+
'Count Query Generation',
|
|
406
|
+
function()
|
|
407
|
+
{
|
|
408
|
+
test
|
|
409
|
+
(
|
|
410
|
+
'Count Query injects soft-delete filter and aliases as RowCount',
|
|
411
|
+
function()
|
|
412
|
+
{
|
|
413
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle').setScope('Animal');
|
|
414
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
415
|
+
tmpQuery.buildCountQuery();
|
|
416
|
+
Expect(tmpQuery.query.body)
|
|
417
|
+
.to.equal('SELECT COUNT(*) AS RowCount FROM Animal WHERE Deleted = :Deleted_w0');
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
test
|
|
421
|
+
(
|
|
422
|
+
'Count Query honors DISTINCT on the selected field',
|
|
423
|
+
function()
|
|
424
|
+
{
|
|
425
|
+
var tmpQuery = libFoxHound.new(_Fable).setDialect('Oracle')
|
|
426
|
+
.setScope('Animal')
|
|
427
|
+
.setDataElements(['Name'])
|
|
428
|
+
.setDistinct(true);
|
|
429
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
430
|
+
tmpQuery.buildCountQuery();
|
|
431
|
+
Expect(tmpQuery.query.body)
|
|
432
|
+
.to.equal('SELECT COUNT(DISTINCT Name) AS RowCount FROM Animal WHERE Deleted = :Deleted_w0');
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
suite
|
|
439
|
+
(
|
|
440
|
+
'Oracle Bind Type Tracking',
|
|
441
|
+
function()
|
|
442
|
+
{
|
|
443
|
+
test
|
|
444
|
+
(
|
|
445
|
+
'parameterTypes maps schema types to oracledb type strings',
|
|
446
|
+
function()
|
|
447
|
+
{
|
|
448
|
+
var tmpQuery = libFoxHound.new(_Fable)
|
|
449
|
+
.setDialect('Oracle')
|
|
450
|
+
.setScope('Animal')
|
|
451
|
+
.addFilter('Age', 15)
|
|
452
|
+
.addFilter('Name', 'Foo');
|
|
453
|
+
tmpQuery.query.schema = _AnimalSchema;
|
|
454
|
+
tmpQuery.buildReadQuery();
|
|
455
|
+
Expect(tmpQuery.query.parameterTypes.Age_w0).to.equal('NUMBER');
|
|
456
|
+
Expect(tmpQuery.query.parameterTypes.Name_w1).to.equal('STRING');
|
|
457
|
+
Expect(tmpQuery.query.parameterTypes.Deleted_w2).to.equal('NUMBER');
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
);
|