meadow 2.0.41 → 2.0.43
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 +19 -17
- package/docs/_cover.md +1 -1
- package/docs/_topbar.md +1 -1
- package/docs/_version.json +2 -2
- package/docs/providers/README.md +9 -9
- package/docs/providers/alasql.md +3 -3
- package/docs/providers/meadow-endpoints.md +6 -6
- package/docs/providers/mongodb.md +5 -5
- package/docs/providers/mssql.md +3 -3
- package/docs/providers/mysql.md +3 -3
- package/docs/providers/postgresql.md +5 -5
- package/docs/providers/rocksdb.md +4 -4
- package/docs/providers/sqlite.md +4 -4
- package/docs/query/README.md +1 -1
- package/docs/query-dsl.md +1 -1
- package/docs/quick-start.md +1 -1
- package/docs/retold-catalog.json +302 -213
- package/docs/retold-keyword-index.json +18147 -13014
- package/package.json +17 -10
- package/scripts/bookstore-seed.js +136 -1
- package/scripts/meadow-test-cleanup.sh +1 -0
- package/scripts/oracle-test-db.sh +128 -0
- package/source/Meadow.js +1 -0
- package/source/providers/Meadow-Provider-ALASQL.js +1 -1
- package/source/providers/Meadow-Provider-Oracle.js +463 -0
- package/test/Meadow-Provider-Oracle_tests.js +877 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for the Meadow "Oracle" Provider
|
|
3
|
+
*
|
|
4
|
+
* These tests expect an Oracle database (see scripts/oracle-test-db.sh —
|
|
5
|
+
* gvenzl/oracle-free on port 21521). If meadow-connection-oracle is not
|
|
6
|
+
* installed, or no Oracle is reachable, the whole suite self-skips so a bare
|
|
7
|
+
* `npm test` (or test-all-providers without Oracle) doesn't hard-fail.
|
|
8
|
+
*
|
|
9
|
+
* @license MIT
|
|
10
|
+
*
|
|
11
|
+
* @author Steven Velozo <steven@velozo.com>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
var Chai = require("chai");
|
|
15
|
+
var Expect = Chai.expect;
|
|
16
|
+
|
|
17
|
+
// Tolerate the connection module (and its oracledb dependency) being absent —
|
|
18
|
+
// the suite self-skips in that case rather than breaking the whole test run.
|
|
19
|
+
var libMeadowConnectionOracle = null;
|
|
20
|
+
try
|
|
21
|
+
{
|
|
22
|
+
libMeadowConnectionOracle = require('meadow-connection-oracle');
|
|
23
|
+
}
|
|
24
|
+
catch (pRequireError)
|
|
25
|
+
{
|
|
26
|
+
libMeadowConnectionOracle = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var tmpFableSettings = (
|
|
30
|
+
{
|
|
31
|
+
"Product": "MeadowOracleTestBookstore",
|
|
32
|
+
"ProductVersion": "1.0.0",
|
|
33
|
+
|
|
34
|
+
"UUID":
|
|
35
|
+
{
|
|
36
|
+
"DataCenter": 0,
|
|
37
|
+
"Worker": 0
|
|
38
|
+
},
|
|
39
|
+
"LogStreams":
|
|
40
|
+
[
|
|
41
|
+
{
|
|
42
|
+
"streamtype": "console"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
|
|
46
|
+
"Oracle":
|
|
47
|
+
{
|
|
48
|
+
"Server": "127.0.0.1",
|
|
49
|
+
"Port": 21521,
|
|
50
|
+
"User": "bookstore",
|
|
51
|
+
"Password": "Retold1234567890!",
|
|
52
|
+
"connectionType": "ServiceName",
|
|
53
|
+
"serviceName": "FREEPDB1",
|
|
54
|
+
"ConnectionPoolLimit": 5,
|
|
55
|
+
// Fail fast into a self-skip when no Oracle is reachable.
|
|
56
|
+
"ConnectRetryOptions": { "MaxAttempts": 1 },
|
|
57
|
+
"ConnectionTimeoutMs": 8000
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
var libFable = new (require('fable'))(tmpFableSettings);
|
|
62
|
+
|
|
63
|
+
if (libMeadowConnectionOracle)
|
|
64
|
+
{
|
|
65
|
+
libFable.serviceManager.addServiceType('MeadowOracleProvider', libMeadowConnectionOracle);
|
|
66
|
+
libFable.serviceManager.instantiateServiceProvider('MeadowOracleProvider');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var _AnimalJsonSchema = (
|
|
70
|
+
{
|
|
71
|
+
title: "Animal",
|
|
72
|
+
description: "A creature that lives in a meadow.",
|
|
73
|
+
type: "object",
|
|
74
|
+
properties: {
|
|
75
|
+
IDAnimal: {
|
|
76
|
+
description: "The unique identifier for an animal",
|
|
77
|
+
type: "integer"
|
|
78
|
+
},
|
|
79
|
+
Name: {
|
|
80
|
+
description: "The animal's name",
|
|
81
|
+
type: "string"
|
|
82
|
+
},
|
|
83
|
+
Type: {
|
|
84
|
+
description: "The type of the animal",
|
|
85
|
+
type: "string"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
required: ["IDAnimal", "Name", "CreatingIDUser"]
|
|
89
|
+
});
|
|
90
|
+
var _AnimalSchema = (
|
|
91
|
+
[
|
|
92
|
+
{ Column: "IDAnimal", Type: "AutoIdentity" },
|
|
93
|
+
{ Column: "GUIDAnimal", Type: "AutoGUID" },
|
|
94
|
+
{ Column: "CreateDate", Type: "CreateDate" },
|
|
95
|
+
{ Column: "CreatingIDUser", Type: "CreateIDUser" },
|
|
96
|
+
{ Column: "UpdateDate", Type: "UpdateDate" },
|
|
97
|
+
{ Column: "UpdatingIDUser", Type: "UpdateIDUser" },
|
|
98
|
+
{ Column: "Deleted", Type: "Deleted" },
|
|
99
|
+
{ Column: "DeletingIDUser", Type: "DeleteIDUser" },
|
|
100
|
+
{ Column: "DeleteDate", Type: "DeleteDate" },
|
|
101
|
+
{ Column: "Name", Type: "String" },
|
|
102
|
+
{ Column: "Type", Type: "String" },
|
|
103
|
+
{ Column: "Metadata", Type:"JSON" },
|
|
104
|
+
{ Column: "ExtraData", Type:"JSONProxy", StorageColumn:"ExtraDataJSON" }
|
|
105
|
+
]);
|
|
106
|
+
var _AnimalDefault = (
|
|
107
|
+
{
|
|
108
|
+
IDAnimal: null,
|
|
109
|
+
GUIDAnimal: '',
|
|
110
|
+
|
|
111
|
+
CreateDate: false,
|
|
112
|
+
CreatingIDUser: 0,
|
|
113
|
+
UpdateDate: false,
|
|
114
|
+
UpdatingIDUser: 0,
|
|
115
|
+
Deleted: 0,
|
|
116
|
+
DeleteDate: false,
|
|
117
|
+
DeletingIDUser: 0,
|
|
118
|
+
|
|
119
|
+
Name: 'Unknown',
|
|
120
|
+
Type: 'Unclassified',
|
|
121
|
+
|
|
122
|
+
Metadata: {},
|
|
123
|
+
ExtraData: {}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
suite
|
|
127
|
+
(
|
|
128
|
+
'Meadow-Provider-Oracle',
|
|
129
|
+
function ()
|
|
130
|
+
{
|
|
131
|
+
var _SpooledUp = false;
|
|
132
|
+
|
|
133
|
+
// Oracle has no DROP TABLE IF EXISTS — swallow ORA-00942.
|
|
134
|
+
var _DropTableStatement = "BEGIN EXECUTE IMMEDIATE 'DROP TABLE FableTest CASCADE CONSTRAINTS'; EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;";
|
|
135
|
+
|
|
136
|
+
var _CreateTableStatement = 'CREATE TABLE FableTest ('
|
|
137
|
+
+ ' IDAnimal NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,'
|
|
138
|
+
+ " GUIDAnimal VARCHAR2(36) DEFAULT '00000000-0000-0000-0000-000000000000' NOT NULL,"
|
|
139
|
+
+ ' CreateDate TIMESTAMP,'
|
|
140
|
+
+ ' CreatingIDUser NUMBER DEFAULT 0 NOT NULL,'
|
|
141
|
+
+ ' UpdateDate TIMESTAMP,'
|
|
142
|
+
+ ' UpdatingIDUser NUMBER DEFAULT 0 NOT NULL,'
|
|
143
|
+
+ ' Deleted NUMBER(1) DEFAULT 0 NOT NULL,'
|
|
144
|
+
+ ' DeleteDate TIMESTAMP,'
|
|
145
|
+
+ ' DeletingIDUser NUMBER DEFAULT 0 NOT NULL,'
|
|
146
|
+
+ " Name VARCHAR2(128) DEFAULT ' ' NOT NULL,"
|
|
147
|
+
+ " Type VARCHAR2(128) DEFAULT ' ' NOT NULL,"
|
|
148
|
+
+ ' Metadata CLOB,'
|
|
149
|
+
+ ' ExtraDataJSON CLOB'
|
|
150
|
+
+ ' )';
|
|
151
|
+
|
|
152
|
+
var getAnimalInsert = function (pName, pType)
|
|
153
|
+
{
|
|
154
|
+
return "INSERT INTO FableTest (GUIDAnimal, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser, Deleted, DeleteDate, DeletingIDUser, Name, Type, Metadata, ExtraDataJSON)"
|
|
155
|
+
+ " VALUES ('00000000-0000-0000-0000-000000000000', SYS_EXTRACT_UTC(SYSTIMESTAMP), 1, SYS_EXTRACT_UTC(SYSTIMESTAMP), 1, 0, NULL, 0, '"
|
|
156
|
+
+ pName + "', '" + pType + "', '{}', '{}')";
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Acquire a pooled connection, run a statement with autoCommit, and
|
|
160
|
+
// always release the connection (oracledb has no pool.query()).
|
|
161
|
+
var execOnPool = function (pSQL, fCallback)
|
|
162
|
+
{
|
|
163
|
+
var tmpProvider = libFable.MeadowOracleProvider;
|
|
164
|
+
tmpProvider.getConnection(function (pConnectionError, pConnection)
|
|
165
|
+
{
|
|
166
|
+
if (pConnectionError) { return fCallback(pConnectionError); }
|
|
167
|
+
pConnection.execute(pSQL, [], { autoCommit: true })
|
|
168
|
+
.then(function () { pConnection.close().then(() => fCallback()).catch(() => fCallback()); })
|
|
169
|
+
.catch(function (pError) { pConnection.close().then(() => fCallback(pError)).catch(() => fCallback(pError)); });
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
var newMeadow = function ()
|
|
174
|
+
{
|
|
175
|
+
return require('../source/Meadow.js')
|
|
176
|
+
.new(libFable, 'FableTest')
|
|
177
|
+
.setProvider('Oracle')
|
|
178
|
+
.setSchema(_AnimalSchema)
|
|
179
|
+
.setJsonSchema(_AnimalJsonSchema)
|
|
180
|
+
.setDefaultIdentifier('IDAnimal')
|
|
181
|
+
.setDefault(_AnimalDefault)
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
suiteSetup
|
|
185
|
+
(
|
|
186
|
+
function (fDone)
|
|
187
|
+
{
|
|
188
|
+
var tmpSelf = this;
|
|
189
|
+
|
|
190
|
+
// No connection module installed → skip the whole suite.
|
|
191
|
+
if (!libMeadowConnectionOracle)
|
|
192
|
+
{
|
|
193
|
+
return tmpSelf.skip();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (_SpooledUp)
|
|
197
|
+
{
|
|
198
|
+
return fDone();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
libFable.MeadowOracleProvider.connectAsync(
|
|
202
|
+
(pConnectError) =>
|
|
203
|
+
{
|
|
204
|
+
if (pConnectError)
|
|
205
|
+
{
|
|
206
|
+
// No reachable Oracle → skip the whole suite.
|
|
207
|
+
libFable.log.warn(`Oracle not reachable, skipping Meadow-Provider-Oracle suite: ${pConnectError}`);
|
|
208
|
+
return tmpSelf.skip();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
libFable.log.info('Connection opened!');
|
|
212
|
+
libFable.Utility.waterfall(
|
|
213
|
+
[
|
|
214
|
+
function (fStageComplete)
|
|
215
|
+
{
|
|
216
|
+
execOnPool(_DropTableStatement, () => fStageComplete());
|
|
217
|
+
},
|
|
218
|
+
function (fStageComplete)
|
|
219
|
+
{
|
|
220
|
+
execOnPool(_CreateTableStatement, fStageComplete);
|
|
221
|
+
},
|
|
222
|
+
function (fStageComplete)
|
|
223
|
+
{
|
|
224
|
+
execOnPool(getAnimalInsert('Foo Foo', 'Bunny'), fStageComplete);
|
|
225
|
+
},
|
|
226
|
+
function (fStageComplete)
|
|
227
|
+
{
|
|
228
|
+
execOnPool(getAnimalInsert('Red Riding Hood', 'Girl'), fStageComplete);
|
|
229
|
+
},
|
|
230
|
+
function (fStageComplete)
|
|
231
|
+
{
|
|
232
|
+
execOnPool(getAnimalInsert('Red', 'Dog'), fStageComplete);
|
|
233
|
+
},
|
|
234
|
+
function (fStageComplete)
|
|
235
|
+
{
|
|
236
|
+
execOnPool(getAnimalInsert('Spot', 'Dog'), fStageComplete);
|
|
237
|
+
},
|
|
238
|
+
function (fStageComplete)
|
|
239
|
+
{
|
|
240
|
+
execOnPool(getAnimalInsert('Gertrude', 'Frog'), fStageComplete);
|
|
241
|
+
}
|
|
242
|
+
],
|
|
243
|
+
function (pError)
|
|
244
|
+
{
|
|
245
|
+
if (pError)
|
|
246
|
+
{
|
|
247
|
+
libFable.log.error(`Error preparing Oracle test data: ${pError}`);
|
|
248
|
+
return fDone(pError);
|
|
249
|
+
}
|
|
250
|
+
_SpooledUp = true;
|
|
251
|
+
fDone();
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
suiteTeardown((fDone) =>
|
|
260
|
+
{
|
|
261
|
+
if (libFable.MeadowOracleProvider && libFable.MeadowOracleProvider.pool)
|
|
262
|
+
{
|
|
263
|
+
try
|
|
264
|
+
{
|
|
265
|
+
libFable.MeadowOracleProvider.pool.close(0).then(() => fDone()).catch(() => fDone());
|
|
266
|
+
}
|
|
267
|
+
catch (pError)
|
|
268
|
+
{
|
|
269
|
+
return fDone();
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else
|
|
273
|
+
{
|
|
274
|
+
fDone();
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
suite
|
|
279
|
+
(
|
|
280
|
+
'Object Sanity',
|
|
281
|
+
function ()
|
|
282
|
+
{
|
|
283
|
+
test
|
|
284
|
+
(
|
|
285
|
+
'The Oracle class should initialize itself into a happy little object.',
|
|
286
|
+
function ()
|
|
287
|
+
{
|
|
288
|
+
var testMeadow = require('../source/Meadow.js').new(libFable).setProvider('Oracle');
|
|
289
|
+
Expect(testMeadow).to.be.an('object', 'Meadow should initialize as an object directly from the require statement.');
|
|
290
|
+
}
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
suite
|
|
295
|
+
(
|
|
296
|
+
'Query Processing',
|
|
297
|
+
function ()
|
|
298
|
+
{
|
|
299
|
+
test
|
|
300
|
+
(
|
|
301
|
+
'Create a record in the database',
|
|
302
|
+
function (fDone)
|
|
303
|
+
{
|
|
304
|
+
var testMeadow = newMeadow().setIDUser(90210);
|
|
305
|
+
|
|
306
|
+
var tmpQuery = testMeadow.query.clone().setLogLevel(5)
|
|
307
|
+
.addRecord({ Name: 'Blastoise', Type: 'Pokemon' });
|
|
308
|
+
|
|
309
|
+
testMeadow.doCreate(tmpQuery,
|
|
310
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
311
|
+
{
|
|
312
|
+
Expect(pRecord.Name)
|
|
313
|
+
.to.equal('Blastoise');
|
|
314
|
+
Expect(pRecord.CreatingIDUser)
|
|
315
|
+
.to.equal(90210);
|
|
316
|
+
fDone();
|
|
317
|
+
}
|
|
318
|
+
)
|
|
319
|
+
}
|
|
320
|
+
);
|
|
321
|
+
test
|
|
322
|
+
(
|
|
323
|
+
'Create a record with JSON data',
|
|
324
|
+
function (fDone)
|
|
325
|
+
{
|
|
326
|
+
var testMeadow = newMeadow().setIDUser(90210);
|
|
327
|
+
|
|
328
|
+
var tmpQuery = testMeadow.query.clone().setLogLevel(5)
|
|
329
|
+
.addRecord({ Name: 'Moose', Type: 'Mammal', Metadata: { habitat: 'forest', weight: 500 }, ExtraData: { endangered: false, population: 'stable' } });
|
|
330
|
+
|
|
331
|
+
testMeadow.doCreate(tmpQuery,
|
|
332
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
333
|
+
{
|
|
334
|
+
Expect(pRecord.Name)
|
|
335
|
+
.to.equal('Moose');
|
|
336
|
+
Expect(pRecord.Metadata)
|
|
337
|
+
.to.be.an('object');
|
|
338
|
+
Expect(pRecord.Metadata.habitat)
|
|
339
|
+
.to.equal('forest');
|
|
340
|
+
Expect(pRecord.ExtraData)
|
|
341
|
+
.to.be.an('object');
|
|
342
|
+
Expect(pRecord.ExtraData.endangered)
|
|
343
|
+
.to.equal(false);
|
|
344
|
+
// The storage column should not be exposed on the marshaled record
|
|
345
|
+
Expect(pRecord).to.not.have.property('ExtraDataJSON');
|
|
346
|
+
fDone();
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
test
|
|
352
|
+
(
|
|
353
|
+
'Read a record from the database',
|
|
354
|
+
function (fDone)
|
|
355
|
+
{
|
|
356
|
+
var testMeadow = newMeadow();
|
|
357
|
+
|
|
358
|
+
var tmpQuery = testMeadow.query
|
|
359
|
+
.addFilter('IDAnimal', 1);
|
|
360
|
+
|
|
361
|
+
testMeadow.doRead(tmpQuery,
|
|
362
|
+
function (pError, pQuery, pRecord)
|
|
363
|
+
{
|
|
364
|
+
Expect(pRecord.IDAnimal)
|
|
365
|
+
.to.equal(1);
|
|
366
|
+
Expect(pRecord.Name)
|
|
367
|
+
.to.equal('Foo Foo');
|
|
368
|
+
fDone();
|
|
369
|
+
}
|
|
370
|
+
)
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
test
|
|
374
|
+
(
|
|
375
|
+
'Read all records from the database',
|
|
376
|
+
function (fDone)
|
|
377
|
+
{
|
|
378
|
+
var testMeadow = newMeadow();
|
|
379
|
+
|
|
380
|
+
testMeadow.doReads(testMeadow.query.addSort({Column: 'IDAnimal'}),
|
|
381
|
+
function (pError, pQuery, pRecords)
|
|
382
|
+
{
|
|
383
|
+
Expect(pRecords[0].IDAnimal)
|
|
384
|
+
.to.equal(1);
|
|
385
|
+
Expect(pRecords[0].Name)
|
|
386
|
+
.to.equal('Foo Foo');
|
|
387
|
+
Expect(pRecords[1].IDAnimal)
|
|
388
|
+
.to.equal(2);
|
|
389
|
+
Expect(pRecords[1].Name)
|
|
390
|
+
.to.equal('Red Riding Hood');
|
|
391
|
+
Expect(pRecords[1].Type)
|
|
392
|
+
.to.equal('Girl');
|
|
393
|
+
fDone();
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
test
|
|
399
|
+
(
|
|
400
|
+
'Update a record in the database',
|
|
401
|
+
function (fDone)
|
|
402
|
+
{
|
|
403
|
+
var testMeadow = newMeadow();
|
|
404
|
+
|
|
405
|
+
var tmpQuery = testMeadow.query
|
|
406
|
+
.addRecord({ IDAnimal: 2, Type: 'Human' });
|
|
407
|
+
|
|
408
|
+
testMeadow.doUpdate(tmpQuery,
|
|
409
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
410
|
+
{
|
|
411
|
+
Expect(pRecord.Type)
|
|
412
|
+
.to.equal('Human');
|
|
413
|
+
fDone();
|
|
414
|
+
}
|
|
415
|
+
)
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
test
|
|
419
|
+
(
|
|
420
|
+
'Delete a record in the database',
|
|
421
|
+
function (fDone)
|
|
422
|
+
{
|
|
423
|
+
var testMeadow = newMeadow();
|
|
424
|
+
|
|
425
|
+
var tmpQuery = testMeadow.query.addFilter('IDAnimal', 3);
|
|
426
|
+
|
|
427
|
+
testMeadow.doDelete(tmpQuery,
|
|
428
|
+
function (pError, pQuery, pRecord)
|
|
429
|
+
{
|
|
430
|
+
// It returns the number of rows deleted
|
|
431
|
+
Expect(pRecord)
|
|
432
|
+
.to.equal(1);
|
|
433
|
+
fDone();
|
|
434
|
+
}
|
|
435
|
+
)
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
test
|
|
439
|
+
(
|
|
440
|
+
'Undelete a record in the database',
|
|
441
|
+
function (fDone)
|
|
442
|
+
{
|
|
443
|
+
var testMeadow = newMeadow();
|
|
444
|
+
|
|
445
|
+
var tmpDeleteQuery = testMeadow.query.addFilter('IDAnimal', 5);
|
|
446
|
+
|
|
447
|
+
// Make sure the record is deleted!
|
|
448
|
+
testMeadow.doDelete(tmpDeleteQuery,
|
|
449
|
+
function (pDeleteError, pDeleteQuery, pDeleteRecord)
|
|
450
|
+
{
|
|
451
|
+
var tmpQuery = testMeadow.query.addFilter('IDAnimal', 5);
|
|
452
|
+
testMeadow.doUndelete(tmpQuery,
|
|
453
|
+
function (pError, pQuery, pRecord)
|
|
454
|
+
{
|
|
455
|
+
// It returns the number of rows undeleted
|
|
456
|
+
Expect(pRecord)
|
|
457
|
+
.to.equal(1);
|
|
458
|
+
fDone();
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
);
|
|
463
|
+
test
|
|
464
|
+
(
|
|
465
|
+
'Count all records from the database',
|
|
466
|
+
function (fDone)
|
|
467
|
+
{
|
|
468
|
+
var testMeadow = newMeadow();
|
|
469
|
+
|
|
470
|
+
Expect(testMeadow.query.parameters.result.executed)
|
|
471
|
+
.to.equal(false);
|
|
472
|
+
testMeadow.doCount(testMeadow.query,
|
|
473
|
+
function (pError, pQuery, pRecord)
|
|
474
|
+
{
|
|
475
|
+
// There should be 6 records
|
|
476
|
+
Expect(pRecord)
|
|
477
|
+
.to.equal(6);
|
|
478
|
+
Expect(pQuery.parameters.result.executed)
|
|
479
|
+
.to.equal(true);
|
|
480
|
+
fDone();
|
|
481
|
+
}
|
|
482
|
+
)
|
|
483
|
+
}
|
|
484
|
+
);
|
|
485
|
+
test
|
|
486
|
+
(
|
|
487
|
+
'Perform operations with a schema-based instantiation',
|
|
488
|
+
function (fDone)
|
|
489
|
+
{
|
|
490
|
+
var testMeadow = require('../source/Meadow.js').new(libFable)
|
|
491
|
+
.loadFromPackage(__dirname + '/Animal.json').setProvider('Oracle');
|
|
492
|
+
|
|
493
|
+
// Make sure the authentication stuff got loaded
|
|
494
|
+
Expect(testMeadow.schemaFull.authorizer.User)
|
|
495
|
+
.to.be.an('object');
|
|
496
|
+
Expect(testMeadow.schemaFull.authorizer.User.Create)
|
|
497
|
+
.to.equal('Allow');
|
|
498
|
+
|
|
499
|
+
var tmpQuery = testMeadow.query
|
|
500
|
+
.addRecord({ Name: 'Grommet', Type: 'Dog' });
|
|
501
|
+
|
|
502
|
+
testMeadow.doCreate(tmpQuery,
|
|
503
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
504
|
+
{
|
|
505
|
+
Expect(pRecord.Name)
|
|
506
|
+
.to.equal('Grommet');
|
|
507
|
+
fDone();
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
);
|
|
514
|
+
suite
|
|
515
|
+
(
|
|
516
|
+
'Logged Query Processing',
|
|
517
|
+
function ()
|
|
518
|
+
{
|
|
519
|
+
test
|
|
520
|
+
(
|
|
521
|
+
'Create a record in the database',
|
|
522
|
+
function (fDone)
|
|
523
|
+
{
|
|
524
|
+
var testMeadow = newMeadow();
|
|
525
|
+
|
|
526
|
+
var tmpQuery = testMeadow.query
|
|
527
|
+
.setLogLevel(5)
|
|
528
|
+
.addRecord({ Name: 'MewTwo', Type: 'Pokemon' });
|
|
529
|
+
|
|
530
|
+
testMeadow.doCreate(tmpQuery,
|
|
531
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
532
|
+
{
|
|
533
|
+
Expect(pRecord.Name)
|
|
534
|
+
.to.equal('MewTwo');
|
|
535
|
+
fDone();
|
|
536
|
+
}
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
);
|
|
540
|
+
test
|
|
541
|
+
(
|
|
542
|
+
'Create a record in the database with a predefined GUID',
|
|
543
|
+
function (fDone)
|
|
544
|
+
{
|
|
545
|
+
var testMeadow = newMeadow();
|
|
546
|
+
|
|
547
|
+
var tmpQuery = testMeadow.query
|
|
548
|
+
.setLogLevel(5)
|
|
549
|
+
.addRecord({ Name: 'MewThree', GUIDAnimal: '0x12345', Type: 'Pokemon' });
|
|
550
|
+
|
|
551
|
+
testMeadow.doCreate(tmpQuery,
|
|
552
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
553
|
+
{
|
|
554
|
+
Expect(pRecord.Name)
|
|
555
|
+
.to.equal('MewThree');
|
|
556
|
+
fDone();
|
|
557
|
+
}
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
);
|
|
561
|
+
test
|
|
562
|
+
(
|
|
563
|
+
'Create a record in the database with a previously predefined GUID -- expect failure',
|
|
564
|
+
function (fDone)
|
|
565
|
+
{
|
|
566
|
+
var testMeadow = newMeadow();
|
|
567
|
+
|
|
568
|
+
var tmpQuery = testMeadow.query
|
|
569
|
+
.setLogLevel(5)
|
|
570
|
+
.addRecord({ Name: 'MewThree', GUIDAnimal: '0x12345', Type: 'Pokemon' });
|
|
571
|
+
|
|
572
|
+
testMeadow.doCreate(tmpQuery,
|
|
573
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
574
|
+
{
|
|
575
|
+
Expect(pError)
|
|
576
|
+
.to.equal("Record with GUID 0x12345 already exists!");
|
|
577
|
+
fDone();
|
|
578
|
+
}
|
|
579
|
+
)
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
test
|
|
583
|
+
(
|
|
584
|
+
'Read a record from the database',
|
|
585
|
+
function (fDone)
|
|
586
|
+
{
|
|
587
|
+
var testMeadow = newMeadow();
|
|
588
|
+
|
|
589
|
+
var tmpQuery = testMeadow.query
|
|
590
|
+
.setLogLevel(5)
|
|
591
|
+
.addFilter('IDAnimal', 1);
|
|
592
|
+
|
|
593
|
+
testMeadow.doRead(tmpQuery,
|
|
594
|
+
function (pError, pQuery, pRecord)
|
|
595
|
+
{
|
|
596
|
+
Expect(pRecord.IDAnimal)
|
|
597
|
+
.to.equal(1);
|
|
598
|
+
Expect(pRecord.Name)
|
|
599
|
+
.to.equal('Foo Foo');
|
|
600
|
+
fDone();
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
}
|
|
604
|
+
);
|
|
605
|
+
test
|
|
606
|
+
(
|
|
607
|
+
'Read all records from the database',
|
|
608
|
+
function (fDone)
|
|
609
|
+
{
|
|
610
|
+
var testMeadow = newMeadow();
|
|
611
|
+
|
|
612
|
+
testMeadow.doReads(testMeadow.query.setLogLevel(5).addSort({Column: 'IDAnimal'}),
|
|
613
|
+
function (pError, pQuery, pRecords)
|
|
614
|
+
{
|
|
615
|
+
Expect(pRecords[0].IDAnimal)
|
|
616
|
+
.to.equal(1);
|
|
617
|
+
Expect(pRecords[0].Name)
|
|
618
|
+
.to.equal('Foo Foo');
|
|
619
|
+
Expect(pRecords[1].IDAnimal)
|
|
620
|
+
.to.equal(2);
|
|
621
|
+
Expect(pRecords[1].Name)
|
|
622
|
+
.to.equal('Red Riding Hood');
|
|
623
|
+
Expect(pRecords[1].Type)
|
|
624
|
+
.to.equal('Human');
|
|
625
|
+
fDone();
|
|
626
|
+
}
|
|
627
|
+
)
|
|
628
|
+
}
|
|
629
|
+
);
|
|
630
|
+
test
|
|
631
|
+
(
|
|
632
|
+
'Update a record in the database',
|
|
633
|
+
function (fDone)
|
|
634
|
+
{
|
|
635
|
+
var testMeadow = newMeadow();
|
|
636
|
+
|
|
637
|
+
var tmpQuery = testMeadow.query
|
|
638
|
+
.setLogLevel(5)
|
|
639
|
+
.addRecord({ IDAnimal: 2, Type: 'HumanGirl' });
|
|
640
|
+
|
|
641
|
+
testMeadow.doUpdate(tmpQuery,
|
|
642
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
643
|
+
{
|
|
644
|
+
Expect(pRecord.Type)
|
|
645
|
+
.to.equal('HumanGirl');
|
|
646
|
+
fDone();
|
|
647
|
+
}
|
|
648
|
+
)
|
|
649
|
+
}
|
|
650
|
+
);
|
|
651
|
+
test
|
|
652
|
+
(
|
|
653
|
+
'Delete a record in the database',
|
|
654
|
+
function (fDone)
|
|
655
|
+
{
|
|
656
|
+
var testMeadow = newMeadow();
|
|
657
|
+
|
|
658
|
+
var tmpQuery = testMeadow.query
|
|
659
|
+
.setLogLevel(5)
|
|
660
|
+
.addFilter('IDAnimal', 4);
|
|
661
|
+
|
|
662
|
+
testMeadow.doDelete(tmpQuery,
|
|
663
|
+
function (pError, pQuery, pRecord)
|
|
664
|
+
{
|
|
665
|
+
// It returns the number of rows deleted
|
|
666
|
+
Expect(pRecord)
|
|
667
|
+
.to.equal(1);
|
|
668
|
+
fDone();
|
|
669
|
+
}
|
|
670
|
+
)
|
|
671
|
+
}
|
|
672
|
+
);
|
|
673
|
+
test
|
|
674
|
+
(
|
|
675
|
+
'Count all records from the database',
|
|
676
|
+
function (fDone)
|
|
677
|
+
{
|
|
678
|
+
var testMeadow = newMeadow();
|
|
679
|
+
|
|
680
|
+
testMeadow.doCount(testMeadow.query.setLogLevel(5),
|
|
681
|
+
function (pError, pQuery, pRecord)
|
|
682
|
+
{
|
|
683
|
+
// There should be 8 records
|
|
684
|
+
Expect(pRecord)
|
|
685
|
+
.to.equal(8);
|
|
686
|
+
fDone();
|
|
687
|
+
}
|
|
688
|
+
)
|
|
689
|
+
}
|
|
690
|
+
);
|
|
691
|
+
test
|
|
692
|
+
(
|
|
693
|
+
'Read a record from the database that had a defined GUID',
|
|
694
|
+
function (fDone)
|
|
695
|
+
{
|
|
696
|
+
var testMeadow = newMeadow();
|
|
697
|
+
|
|
698
|
+
var tmpQuery = testMeadow.query
|
|
699
|
+
.addFilter('GUIDAnimal', '0x12345');
|
|
700
|
+
|
|
701
|
+
testMeadow.doRead(tmpQuery,
|
|
702
|
+
function (pError, pQuery, pRecord)
|
|
703
|
+
{
|
|
704
|
+
Expect(pRecord.Name)
|
|
705
|
+
.to.equal('MewThree');
|
|
706
|
+
fDone();
|
|
707
|
+
}
|
|
708
|
+
)
|
|
709
|
+
}
|
|
710
|
+
);
|
|
711
|
+
test
|
|
712
|
+
(
|
|
713
|
+
'Create a record in the database with a defined creating user',
|
|
714
|
+
function (fDone)
|
|
715
|
+
{
|
|
716
|
+
var testMeadow = newMeadow();
|
|
717
|
+
var tmpQuery = testMeadow.query
|
|
718
|
+
.setIDUser(800)
|
|
719
|
+
.addRecord({ Name: 'MewSix', GUIDAnimal: '0x123456', Type: 'Pokemon' });
|
|
720
|
+
|
|
721
|
+
testMeadow.doCreate(tmpQuery,
|
|
722
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
723
|
+
{
|
|
724
|
+
Expect(pRecord.Name)
|
|
725
|
+
.to.equal('MewSix');
|
|
726
|
+
Expect(pRecord.CreatingIDUser)
|
|
727
|
+
.to.equal(800);
|
|
728
|
+
fDone();
|
|
729
|
+
}
|
|
730
|
+
)
|
|
731
|
+
}
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
);
|
|
735
|
+
suite
|
|
736
|
+
(
|
|
737
|
+
'The Bad Kind of Query Processing',
|
|
738
|
+
function ()
|
|
739
|
+
{
|
|
740
|
+
test
|
|
741
|
+
(
|
|
742
|
+
'Create a record in the database with no record',
|
|
743
|
+
function (fDone)
|
|
744
|
+
{
|
|
745
|
+
var testMeadow = newMeadow().setDefaultIdentifier('Type');
|
|
746
|
+
|
|
747
|
+
testMeadow.doCreate(testMeadow.query,
|
|
748
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
749
|
+
{
|
|
750
|
+
Expect(pError)
|
|
751
|
+
.to.equal('No record submitted');
|
|
752
|
+
fDone();
|
|
753
|
+
}
|
|
754
|
+
)
|
|
755
|
+
}
|
|
756
|
+
);
|
|
757
|
+
test
|
|
758
|
+
(
|
|
759
|
+
'Read a record from the database with no data returned',
|
|
760
|
+
function (fDone)
|
|
761
|
+
{
|
|
762
|
+
var testMeadow = newMeadow();
|
|
763
|
+
|
|
764
|
+
var tmpQuery = testMeadow.query
|
|
765
|
+
.addFilter('IDAnimal', 5000);
|
|
766
|
+
testMeadow.doRead(tmpQuery,
|
|
767
|
+
function (pError, pQuery, pRecord)
|
|
768
|
+
{
|
|
769
|
+
Expect(pRecord)
|
|
770
|
+
.to.equal(false);
|
|
771
|
+
fDone();
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
}
|
|
775
|
+
);
|
|
776
|
+
test
|
|
777
|
+
(
|
|
778
|
+
'Read records from the database with no data returned',
|
|
779
|
+
function (fDone)
|
|
780
|
+
{
|
|
781
|
+
var testMeadow = newMeadow();
|
|
782
|
+
|
|
783
|
+
var tmpQuery = testMeadow.query
|
|
784
|
+
.addFilter('IDAnimal', 5000);
|
|
785
|
+
|
|
786
|
+
testMeadow.doReads(tmpQuery,
|
|
787
|
+
function (pError, pQuery, pRecord)
|
|
788
|
+
{
|
|
789
|
+
Expect(pRecord.length)
|
|
790
|
+
.to.equal(0);
|
|
791
|
+
fDone();
|
|
792
|
+
}
|
|
793
|
+
)
|
|
794
|
+
}
|
|
795
|
+
);
|
|
796
|
+
test
|
|
797
|
+
(
|
|
798
|
+
'Update a record in the database with a bad filter',
|
|
799
|
+
function (fDone)
|
|
800
|
+
{
|
|
801
|
+
var testMeadow = newMeadow();
|
|
802
|
+
|
|
803
|
+
var tmpQuery = testMeadow.query
|
|
804
|
+
.setLogLevel(5)
|
|
805
|
+
.addRecord({ IDAnimal: undefined, Type: 'HumanGirl' });
|
|
806
|
+
|
|
807
|
+
testMeadow.doUpdate(tmpQuery,
|
|
808
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
809
|
+
{
|
|
810
|
+
Expect(pError)
|
|
811
|
+
.to.equal('Automated update missing filters... aborting!');
|
|
812
|
+
fDone();
|
|
813
|
+
}
|
|
814
|
+
)
|
|
815
|
+
}
|
|
816
|
+
);
|
|
817
|
+
test
|
|
818
|
+
(
|
|
819
|
+
'Update a record in the database without passing a record in',
|
|
820
|
+
function (fDone)
|
|
821
|
+
{
|
|
822
|
+
var testMeadow = newMeadow();
|
|
823
|
+
|
|
824
|
+
testMeadow.doUpdate(testMeadow.query,
|
|
825
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
826
|
+
{
|
|
827
|
+
Expect(pError)
|
|
828
|
+
.to.equal('No record submitted');
|
|
829
|
+
fDone();
|
|
830
|
+
}
|
|
831
|
+
)
|
|
832
|
+
}
|
|
833
|
+
);
|
|
834
|
+
test
|
|
835
|
+
(
|
|
836
|
+
'Update a record in the database with a bad record passed in (no default identifier)',
|
|
837
|
+
function (fDone)
|
|
838
|
+
{
|
|
839
|
+
var testMeadow = newMeadow();
|
|
840
|
+
|
|
841
|
+
var tmpQuery = testMeadow.query
|
|
842
|
+
.addRecord({ Name: 'Bill' });
|
|
843
|
+
|
|
844
|
+
testMeadow.doUpdate(tmpQuery,
|
|
845
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
846
|
+
{
|
|
847
|
+
Expect(pError)
|
|
848
|
+
.to.equal('Automated update missing default identifier');
|
|
849
|
+
fDone();
|
|
850
|
+
}
|
|
851
|
+
)
|
|
852
|
+
}
|
|
853
|
+
);
|
|
854
|
+
test
|
|
855
|
+
(
|
|
856
|
+
'Update a record in the database that does not exist',
|
|
857
|
+
function (fDone)
|
|
858
|
+
{
|
|
859
|
+
var testMeadow = newMeadow();
|
|
860
|
+
|
|
861
|
+
var tmpQuery = testMeadow.query
|
|
862
|
+
.addRecord({ IDAnimal: 983924 });
|
|
863
|
+
|
|
864
|
+
testMeadow.doUpdate(tmpQuery,
|
|
865
|
+
function (pError, pQuery, pQueryRead, pRecord)
|
|
866
|
+
{
|
|
867
|
+
Expect(pError)
|
|
868
|
+
.to.equal('No record found to update!');
|
|
869
|
+
fDone();
|
|
870
|
+
}
|
|
871
|
+
)
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
);
|