@balena/abstract-sql-compiler 11.0.0-build-11-x-b2280608fff69d9959999c79db6245c4ad561bbc-1 → 11.0.0-build-11-x-7511b8ebe5a9461f20add0ed97d0670ed3b5a479-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -2
- package/.github/workflows/flowzone.yml +0 -21
- package/.husky/pre-commit +0 -2
- package/.versionbot/CHANGELOG.yml +0 -10729
- package/CHANGELOG.md +0 -3515
- package/repo.yml +0 -12
- package/src/abstract-sql-compiler.ts +0 -1138
- package/src/abstract-sql-optimizer.ts +0 -1632
- package/src/abstract-sql-rules-to-sql.ts +0 -1730
- package/src/abstract-sql-schema-optimizer.ts +0 -172
- package/src/referenced-fields.ts +0 -600
- package/test/abstract-sql/aggregate-json.ts +0 -49
- package/test/abstract-sql/aggregate.ts +0 -161
- package/test/abstract-sql/and-or-boolean-optimisations.ts +0 -115
- package/test/abstract-sql/case-when-else.ts +0 -48
- package/test/abstract-sql/cast.ts +0 -25
- package/test/abstract-sql/coalesce.ts +0 -24
- package/test/abstract-sql/comparisons.ts +0 -360
- package/test/abstract-sql/dates.ts +0 -512
- package/test/abstract-sql/duration.ts +0 -56
- package/test/abstract-sql/empty-query-optimisations.ts +0 -54
- package/test/abstract-sql/functions-wrapper.ts +0 -70
- package/test/abstract-sql/get-referenced-fields.ts +0 -674
- package/test/abstract-sql/get-rule-referenced-fields.ts +0 -345
- package/test/abstract-sql/insert-query.ts +0 -22
- package/test/abstract-sql/is-distinct.ts +0 -102
- package/test/abstract-sql/joins.ts +0 -84
- package/test/abstract-sql/json.ts +0 -58
- package/test/abstract-sql/math.ts +0 -467
- package/test/abstract-sql/nested-in-optimisations.ts +0 -200
- package/test/abstract-sql/not-not-optimisations.ts +0 -15
- package/test/abstract-sql/schema-checks.ts +0 -168
- package/test/abstract-sql/schema-informative-reference.ts +0 -420
- package/test/abstract-sql/schema-rule-optimization.ts +0 -120
- package/test/abstract-sql/schema-rule-to-check.ts +0 -393
- package/test/abstract-sql/schema-views.ts +0 -73
- package/test/abstract-sql/test.ts +0 -192
- package/test/abstract-sql/text.ts +0 -168
- package/test/model.sbvr +0 -60
- package/test/odata/expand.ts +0 -674
- package/test/odata/fields.ts +0 -59
- package/test/odata/filterby.ts +0 -1517
- package/test/odata/orderby.ts +0 -96
- package/test/odata/paging.ts +0 -48
- package/test/odata/resource-parsing.ts +0 -568
- package/test/odata/select.ts +0 -119
- package/test/odata/stress.ts +0 -93
- package/test/odata/test.ts +0 -297
- package/test/sbvr/pilots.ts +0 -1097
- package/test/sbvr/reference-type.ts +0 -211
- package/test/sbvr/test.ts +0 -101
- package/tsconfig.build.json +0 -6
- package/tsconfig.json +0 -25
package/test/odata/filterby.ts
DELETED
@@ -1,1517 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* decaffeinate suggestions:
|
3
|
-
* DS205: Consider reworking code to avoid use of IIFEs
|
4
|
-
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
5
|
-
*/
|
6
|
-
import { expect } from 'chai';
|
7
|
-
import type { ExpectationSuccessFn } from './test.js';
|
8
|
-
import test, { clientModel } from './test.js';
|
9
|
-
import _ from 'lodash';
|
10
|
-
import { odataNameToSqlName } from '@balena/odata-to-abstract-sql';
|
11
|
-
import {
|
12
|
-
pilotFields,
|
13
|
-
teamFields,
|
14
|
-
aliasPilotCanFlyPlaneFields,
|
15
|
-
} from './fields.js';
|
16
|
-
import type {
|
17
|
-
Binding,
|
18
|
-
DurationNode,
|
19
|
-
SqlResult,
|
20
|
-
} from '../../out/abstract-sql-compiler.js';
|
21
|
-
|
22
|
-
const pilotFieldsStr = pilotFields.join(', ');
|
23
|
-
const aliasPilotCanFlyPlaneFieldsStr = aliasPilotCanFlyPlaneFields.join(', ');
|
24
|
-
const teamFieldsStr = teamFields.join(', ');
|
25
|
-
|
26
|
-
type ParsedOperand = {
|
27
|
-
odata: string | number | boolean;
|
28
|
-
bindings: Binding[];
|
29
|
-
sql: string;
|
30
|
-
};
|
31
|
-
type Operand =
|
32
|
-
| string
|
33
|
-
| number
|
34
|
-
| boolean
|
35
|
-
| Date
|
36
|
-
| DurationNode[1]
|
37
|
-
| ParsedOperand;
|
38
|
-
|
39
|
-
let parseOperandFactory = function (defaultResource = 'pilot') {
|
40
|
-
let bindNo = 0;
|
41
|
-
const operandToOData = function (operand: Operand) {
|
42
|
-
if (operand != null && typeof operand === 'object') {
|
43
|
-
if ('odata' in operand) {
|
44
|
-
return operand.odata;
|
45
|
-
}
|
46
|
-
if (_.isDate(operand)) {
|
47
|
-
return "datetime'" + encodeURIComponent(operand.toISOString()) + "'";
|
48
|
-
}
|
49
|
-
|
50
|
-
const duration: Array<string | number> = [];
|
51
|
-
let t = false;
|
52
|
-
if (operand.negative) {
|
53
|
-
duration.push('-');
|
54
|
-
}
|
55
|
-
duration.push('P');
|
56
|
-
if (operand.day != null) {
|
57
|
-
duration.push(operand.day, 'D');
|
58
|
-
}
|
59
|
-
if (operand.hour != null) {
|
60
|
-
t = true;
|
61
|
-
duration.push('T', operand.hour, 'H');
|
62
|
-
}
|
63
|
-
if (operand.minute != null) {
|
64
|
-
if (!t) {
|
65
|
-
t = true;
|
66
|
-
duration.push('T');
|
67
|
-
}
|
68
|
-
duration.push(operand.minute, 'M');
|
69
|
-
}
|
70
|
-
if (operand.second != null) {
|
71
|
-
if (!t) {
|
72
|
-
t = true;
|
73
|
-
duration.push('T');
|
74
|
-
}
|
75
|
-
duration.push(operand.second, 'S');
|
76
|
-
}
|
77
|
-
if (duration.length < 3) {
|
78
|
-
throw new Error('Duration must contain at least 1 component');
|
79
|
-
}
|
80
|
-
return `duration'${duration.join('')}'`;
|
81
|
-
}
|
82
|
-
return operand;
|
83
|
-
};
|
84
|
-
|
85
|
-
const operandToBindings = function (operand: Operand): Binding[] {
|
86
|
-
if (typeof operand === 'object' && 'bindings' in operand) {
|
87
|
-
return operand.bindings;
|
88
|
-
}
|
89
|
-
if (
|
90
|
-
typeof operand === 'boolean' ||
|
91
|
-
typeof operand === 'number' ||
|
92
|
-
_.isDate(operand) ||
|
93
|
-
(typeof operand === 'string' && operand.startsWith("'"))
|
94
|
-
) {
|
95
|
-
return [['Bind', bindNo++]];
|
96
|
-
}
|
97
|
-
return [];
|
98
|
-
};
|
99
|
-
|
100
|
-
const operandToSQL = function (
|
101
|
-
operand: Operand,
|
102
|
-
resource = defaultResource,
|
103
|
-
): string {
|
104
|
-
if (typeof operand === 'object' && 'sql' in operand) {
|
105
|
-
return operand.sql;
|
106
|
-
}
|
107
|
-
if (
|
108
|
-
typeof operand === 'boolean' ||
|
109
|
-
typeof operand === 'number' ||
|
110
|
-
_.isDate(operand)
|
111
|
-
) {
|
112
|
-
return '?';
|
113
|
-
}
|
114
|
-
if (typeof operand === 'string') {
|
115
|
-
let mapping;
|
116
|
-
if (operand === 'null') {
|
117
|
-
return 'NULL';
|
118
|
-
}
|
119
|
-
if (operand.startsWith("'")) {
|
120
|
-
return '?';
|
121
|
-
}
|
122
|
-
const fieldParts = operand.split('/');
|
123
|
-
if (fieldParts.length > 1) {
|
124
|
-
let alias = resource;
|
125
|
-
let previousResource = resource;
|
126
|
-
for (const resourceName of fieldParts.slice(0, -1)) {
|
127
|
-
const sqlName = odataNameToSqlName(resourceName);
|
128
|
-
const sqlNameParts = sqlName.split('-');
|
129
|
-
mapping = _.get(
|
130
|
-
clientModel.relationships[previousResource],
|
131
|
-
sqlNameParts.join('.'),
|
132
|
-
).$;
|
133
|
-
const refTable = mapping[1][0];
|
134
|
-
if (sqlNameParts.length > 1 && !_.includes(refTable, '-')) {
|
135
|
-
alias = `${alias}.${sqlNameParts[0]}-${refTable}`;
|
136
|
-
} else {
|
137
|
-
alias = `${alias}.${refTable}`;
|
138
|
-
}
|
139
|
-
previousResource = refTable;
|
140
|
-
}
|
141
|
-
mapping = [alias, _.last(fieldParts)];
|
142
|
-
} else {
|
143
|
-
mapping = [resource, odataNameToSqlName(operand)];
|
144
|
-
}
|
145
|
-
return '"' + mapping.join('"."') + '"';
|
146
|
-
}
|
147
|
-
if (operand != null && typeof operand === 'object') {
|
148
|
-
const sign = operand.negative ? '-' : '';
|
149
|
-
const day = operand.day ?? 0;
|
150
|
-
const hour = operand.hour ?? 0;
|
151
|
-
const minute = operand.minute ?? 0;
|
152
|
-
const second = operand.second ?? 0;
|
153
|
-
return `INTERVAL '${sign}${day} ${sign}${hour}:${minute}:${second}'`;
|
154
|
-
}
|
155
|
-
throw new Error(`Unknown operand type: ${operand}`);
|
156
|
-
};
|
157
|
-
|
158
|
-
return (operand: Operand): ParsedOperand => ({
|
159
|
-
sql: operandToSQL(operand),
|
160
|
-
bindings: operandToBindings(operand),
|
161
|
-
odata: operandToOData(operand),
|
162
|
-
});
|
163
|
-
};
|
164
|
-
|
165
|
-
let parseOperand: ReturnType<typeof parseOperandFactory> | null = null;
|
166
|
-
const run = (function () {
|
167
|
-
let running = false;
|
168
|
-
return function (fn: () => void) {
|
169
|
-
if (!running) {
|
170
|
-
running = true;
|
171
|
-
parseOperand = parseOperandFactory();
|
172
|
-
fn();
|
173
|
-
parseOperand = null;
|
174
|
-
running = false;
|
175
|
-
} else {
|
176
|
-
fn();
|
177
|
-
}
|
178
|
-
};
|
179
|
-
})();
|
180
|
-
|
181
|
-
const sqlOps = {
|
182
|
-
eq: ' =',
|
183
|
-
ne: ' !=',
|
184
|
-
gt: ' >',
|
185
|
-
ge: ' >=',
|
186
|
-
lt: ' <',
|
187
|
-
le: ' <=',
|
188
|
-
and: '\nAND',
|
189
|
-
or: '\nOR',
|
190
|
-
add: ' +',
|
191
|
-
sub: ' -',
|
192
|
-
mul: ' *',
|
193
|
-
div: ' /',
|
194
|
-
};
|
195
|
-
const sqlOpBrackets = { or: true };
|
196
|
-
|
197
|
-
const methodMaps = {
|
198
|
-
TOUPPER: 'UPPER',
|
199
|
-
TOLOWER: 'LOWER',
|
200
|
-
};
|
201
|
-
|
202
|
-
const createExpression = function (lhs: Operand, op?: Operand, rhs?: Operand) {
|
203
|
-
let sql;
|
204
|
-
if (lhs === 'not') {
|
205
|
-
op = parseOperand!(op!);
|
206
|
-
return {
|
207
|
-
odata: 'not(' + op.odata + ')',
|
208
|
-
sql: 'NOT (\n\t' + op.sql + '\n)',
|
209
|
-
bindings: op.bindings,
|
210
|
-
};
|
211
|
-
}
|
212
|
-
if (rhs == null) {
|
213
|
-
lhs = parseOperand!(lhs);
|
214
|
-
return {
|
215
|
-
odata: '(' + lhs.odata + ')',
|
216
|
-
sql: lhs.sql,
|
217
|
-
bindings: lhs.bindings,
|
218
|
-
};
|
219
|
-
}
|
220
|
-
lhs = parseOperand!(lhs);
|
221
|
-
rhs = parseOperand!(rhs);
|
222
|
-
const bindings = lhs.bindings.concat(rhs.bindings);
|
223
|
-
if (op === 'eq' || op === 'ne') {
|
224
|
-
if ([lhs.sql, rhs.sql].includes('NULL')) {
|
225
|
-
const nullCheck = op === 'eq' ? ' IS NULL' : ' IS NOT NULL';
|
226
|
-
if (lhs.sql === 'NULL') {
|
227
|
-
sql = rhs.sql + nullCheck;
|
228
|
-
} else {
|
229
|
-
sql = lhs.sql + nullCheck;
|
230
|
-
}
|
231
|
-
} else {
|
232
|
-
const isAtomic = /^([-." a-zA-Z]+|\?|\$[0-9]+)$/;
|
233
|
-
const lhsSql = isAtomic.test(lhs.sql) ? lhs.sql : `(${lhs.sql})`;
|
234
|
-
const rhsSql = isAtomic.test(rhs.sql) ? rhs.sql : `(${rhs.sql})`;
|
235
|
-
const nullCheck = ' IS NOT NULL';
|
236
|
-
const lhsNullCheck = lhs.sql === '?' ? '' : `${lhsSql}${nullCheck} AND `;
|
237
|
-
const rhsNullCheck = rhs.sql === '?' ? '' : `${rhsSql}${nullCheck} AND `;
|
238
|
-
const bothNullCheck =
|
239
|
-
lhsNullCheck.length > 0 && rhsNullCheck.length > 0
|
240
|
-
? ` OR ${lhsSql} IS NULL AND ${rhsSql} IS NULL`
|
241
|
-
: '';
|
242
|
-
|
243
|
-
if (lhsNullCheck.length > 0 || rhsNullCheck.length > 0) {
|
244
|
-
if (op === 'ne') {
|
245
|
-
const mainCheck = `${lhsSql}${sqlOps.eq} ${rhsSql}`;
|
246
|
-
sql = `NOT(${lhsNullCheck}${rhsNullCheck}${mainCheck}${bothNullCheck})`;
|
247
|
-
} else {
|
248
|
-
const mainCheck = `${lhsSql}${sqlOps[op]} ${rhsSql}`;
|
249
|
-
sql = `${lhsNullCheck}${rhsNullCheck}${mainCheck}${bothNullCheck}`;
|
250
|
-
}
|
251
|
-
} else {
|
252
|
-
const mainCheck = `${lhs.sql}${sqlOps[op]} ${rhs.sql}`;
|
253
|
-
sql = `${lhsNullCheck}${rhsNullCheck}${mainCheck}${bothNullCheck}`;
|
254
|
-
}
|
255
|
-
}
|
256
|
-
} else {
|
257
|
-
sql = `${lhs.sql}${sqlOps[op as keyof typeof sqlOps]} ${rhs.sql}`;
|
258
|
-
}
|
259
|
-
|
260
|
-
if (sqlOpBrackets[op as keyof typeof sqlOpBrackets]) {
|
261
|
-
sql = '(' + sql + ')';
|
262
|
-
}
|
263
|
-
return {
|
264
|
-
odata: `${lhs.odata} ${op} ${rhs.odata}`,
|
265
|
-
sql,
|
266
|
-
bindings,
|
267
|
-
};
|
268
|
-
};
|
269
|
-
const createMethodCall = function (method: string, ...args: Operand[]) {
|
270
|
-
const parsedArgs = args.map((arg) => parseOperand!(arg));
|
271
|
-
const odata =
|
272
|
-
method + '(' + parsedArgs.map((arg) => arg.odata).join(',') + ')';
|
273
|
-
method = method.toUpperCase();
|
274
|
-
switch (method) {
|
275
|
-
case 'CONTAINS':
|
276
|
-
case 'SUBSTRINGOF':
|
277
|
-
if (method === 'SUBSTRINGOF') {
|
278
|
-
parsedArgs.reverse();
|
279
|
-
}
|
280
|
-
return {
|
281
|
-
sql: `${parsedArgs[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${parsedArgs[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%') || '%')`,
|
282
|
-
bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
|
283
|
-
odata,
|
284
|
-
};
|
285
|
-
case 'STARTSWITH':
|
286
|
-
return {
|
287
|
-
sql: `STARTS_WITH(${parsedArgs[0].sql}, ${parsedArgs[1].sql})`,
|
288
|
-
bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
|
289
|
-
odata,
|
290
|
-
};
|
291
|
-
case 'ENDSWITH':
|
292
|
-
return {
|
293
|
-
sql: `${parsedArgs[0].sql} LIKE ('%' || REPLACE(REPLACE(REPLACE(${parsedArgs[1].sql}, '\\', '\\\\'), '_', '\\_'), '%', '\\%'))`,
|
294
|
-
bindings: [...parsedArgs[0].bindings, ...parsedArgs[1].bindings],
|
295
|
-
odata,
|
296
|
-
};
|
297
|
-
case 'CONCAT':
|
298
|
-
return {
|
299
|
-
sql: '(' + parsedArgs.map((arg) => arg.sql).join(' || ') + ')',
|
300
|
-
bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
|
301
|
-
odata,
|
302
|
-
};
|
303
|
-
case 'INDEXOF':
|
304
|
-
return {
|
305
|
-
sql: 'STRPOS(' + parsedArgs.map((arg) => arg.sql).join(', ') + ') - 1',
|
306
|
-
bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
|
307
|
-
odata,
|
308
|
-
};
|
309
|
-
case 'NOW':
|
310
|
-
return {
|
311
|
-
sql: 'CURRENT_TIMESTAMP',
|
312
|
-
bindings: [],
|
313
|
-
odata,
|
314
|
-
};
|
315
|
-
case 'YEAR':
|
316
|
-
case 'MONTH':
|
317
|
-
case 'DAY':
|
318
|
-
case 'HOUR':
|
319
|
-
case 'MINUTE':
|
320
|
-
return {
|
321
|
-
sql: `EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC'))`,
|
322
|
-
bindings: parsedArgs[0].bindings,
|
323
|
-
odata,
|
324
|
-
};
|
325
|
-
case 'SECOND':
|
326
|
-
return {
|
327
|
-
sql: `FLOOR(EXTRACT('${method}' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC')))`,
|
328
|
-
bindings: parsedArgs[0].bindings,
|
329
|
-
odata,
|
330
|
-
};
|
331
|
-
case 'FRACTIONALSECONDS':
|
332
|
-
return {
|
333
|
-
sql: `EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC')) - FLOOR(EXTRACT('SECOND' FROM DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC')))`,
|
334
|
-
bindings: parsedArgs[0].bindings,
|
335
|
-
odata,
|
336
|
-
};
|
337
|
-
case 'TIME':
|
338
|
-
return {
|
339
|
-
sql: `CAST(DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC') AS ${method})`,
|
340
|
-
bindings: parsedArgs[0].bindings,
|
341
|
-
odata,
|
342
|
-
};
|
343
|
-
case 'TOTALSECONDS':
|
344
|
-
return {
|
345
|
-
sql: `EXTRACT(EPOCH FROM ${parsedArgs[0].sql})`,
|
346
|
-
bindings: parsedArgs[0].bindings,
|
347
|
-
odata,
|
348
|
-
};
|
349
|
-
case 'DATE':
|
350
|
-
return {
|
351
|
-
sql: `DATE(DATE_TRUNC('milliseconds', ${parsedArgs[0].sql}, 'UTC'))`,
|
352
|
-
bindings: parsedArgs[0].bindings,
|
353
|
-
odata,
|
354
|
-
};
|
355
|
-
default: {
|
356
|
-
if (Object.prototype.hasOwnProperty.call(methodMaps, method)) {
|
357
|
-
method = methodMaps[method as keyof typeof methodMaps];
|
358
|
-
}
|
359
|
-
switch (method) {
|
360
|
-
case 'SUBSTRING':
|
361
|
-
parsedArgs[1].sql += ' + 1';
|
362
|
-
break;
|
363
|
-
}
|
364
|
-
const sql =
|
365
|
-
method + '(' + parsedArgs.map((arg) => arg.sql).join(', ') + ')';
|
366
|
-
return {
|
367
|
-
sql,
|
368
|
-
bindings: _.flatten(parsedArgs.map((arg) => arg.bindings)),
|
369
|
-
odata,
|
370
|
-
};
|
371
|
-
}
|
372
|
-
}
|
373
|
-
};
|
374
|
-
|
375
|
-
const operandTest = (
|
376
|
-
lhs: Operand,
|
377
|
-
op?: Operand,
|
378
|
-
rhs?: Operand,
|
379
|
-
override?: Partial<ParsedOperand>,
|
380
|
-
) => {
|
381
|
-
run(function () {
|
382
|
-
let from;
|
383
|
-
let { odata, sql, bindings } = createExpression(lhs, op, rhs);
|
384
|
-
bindings = override?.bindings ?? bindings;
|
385
|
-
sql = override?.sql ?? sql;
|
386
|
-
if (_.includes(odata, '/')) {
|
387
|
-
from = `\
|
388
|
-
"pilot"
|
389
|
-
LEFT JOIN "pilot" AS "pilot.trained-pilot" ON "pilot"."id" = "pilot.trained-pilot"."was trained by-pilot"`;
|
390
|
-
} else {
|
391
|
-
from = '"pilot"';
|
392
|
-
}
|
393
|
-
|
394
|
-
test(`/pilot?$filter=${odata}`, 'GET', bindings, (result, sqlEquals) => {
|
395
|
-
it('should select from pilot where "' + odata + '"', () => {
|
396
|
-
sqlEquals(
|
397
|
-
result,
|
398
|
-
`\
|
399
|
-
SELECT ${pilotFieldsStr}
|
400
|
-
FROM ${from}
|
401
|
-
WHERE ${sql}`,
|
402
|
-
);
|
403
|
-
});
|
404
|
-
});
|
405
|
-
test(
|
406
|
-
`/pilot/$count?$filter=${odata}`,
|
407
|
-
'GET',
|
408
|
-
bindings,
|
409
|
-
(result, sqlEquals) => {
|
410
|
-
it('should select count(*) from pilot where "' + odata + '"', () => {
|
411
|
-
sqlEquals(
|
412
|
-
result,
|
413
|
-
`\
|
414
|
-
SELECT COUNT(*) AS "$count"
|
415
|
-
FROM ${from}
|
416
|
-
WHERE ${sql}`,
|
417
|
-
);
|
418
|
-
});
|
419
|
-
},
|
420
|
-
);
|
421
|
-
});
|
422
|
-
};
|
423
|
-
|
424
|
-
const methodTest = (...args: [method: string, ...Operand[]]) => {
|
425
|
-
run(function () {
|
426
|
-
const { odata, sql, bindings } = createMethodCall(...args);
|
427
|
-
test(`/pilot?$filter=${odata}`, 'GET', bindings, (result, sqlEquals) => {
|
428
|
-
it('should select from pilot where "' + odata + '"', () => {
|
429
|
-
sqlEquals(
|
430
|
-
result,
|
431
|
-
`\
|
432
|
-
SELECT ${pilotFieldsStr}
|
433
|
-
FROM "pilot"
|
434
|
-
WHERE ` + sql,
|
435
|
-
);
|
436
|
-
});
|
437
|
-
});
|
438
|
-
test(
|
439
|
-
`/pilot/$count?$filter=${odata}`,
|
440
|
-
'GET',
|
441
|
-
bindings,
|
442
|
-
(result, sqlEquals) => {
|
443
|
-
it('should select count(*) from pilot where "' + odata + '"', () => {
|
444
|
-
sqlEquals(
|
445
|
-
result,
|
446
|
-
`\
|
447
|
-
SELECT COUNT(*) AS "$count"
|
448
|
-
FROM "pilot"
|
449
|
-
WHERE ` + sql,
|
450
|
-
);
|
451
|
-
});
|
452
|
-
},
|
453
|
-
);
|
454
|
-
});
|
455
|
-
};
|
456
|
-
|
457
|
-
// Test each combination of operands and operations
|
458
|
-
(function () {
|
459
|
-
const operations = ['eq', 'ne', 'gt', 'ge', 'lt', 'le'];
|
460
|
-
const nonNullableOperands = [
|
461
|
-
2,
|
462
|
-
-2,
|
463
|
-
2.5,
|
464
|
-
-2.5,
|
465
|
-
"'bar'",
|
466
|
-
new Date(),
|
467
|
-
true,
|
468
|
-
false,
|
469
|
-
];
|
470
|
-
const nullableOperands = [
|
471
|
-
'name',
|
472
|
-
'trained__pilot/name',
|
473
|
-
{ negative: true, day: 3, hour: 4, minute: 5, second: 6.7 },
|
474
|
-
// null is quoted as otherwise we hit issues with coffeescript defaulting values
|
475
|
-
// 'null',
|
476
|
-
];
|
477
|
-
operations.forEach((op) => {
|
478
|
-
describe(op, () => {
|
479
|
-
nonNullableOperands.forEach((lhs) => {
|
480
|
-
[...nonNullableOperands, ...nullableOperands].forEach((rhs) => {
|
481
|
-
run(() => {
|
482
|
-
operandTest(lhs, op, rhs);
|
483
|
-
});
|
484
|
-
});
|
485
|
-
run(() => {
|
486
|
-
switch (op) {
|
487
|
-
case 'eq':
|
488
|
-
case 'ne':
|
489
|
-
// eq/ne of non-nullable to null are automatically optimized away
|
490
|
-
operandTest(lhs, op, 'null', {
|
491
|
-
bindings: [],
|
492
|
-
sql: op === 'eq' ? 'false' : 'true',
|
493
|
-
});
|
494
|
-
break;
|
495
|
-
|
496
|
-
default:
|
497
|
-
operandTest(lhs, op, 'null');
|
498
|
-
break;
|
499
|
-
}
|
500
|
-
});
|
501
|
-
});
|
502
|
-
nullableOperands.forEach((lhs) => {
|
503
|
-
[...nonNullableOperands, ...nullableOperands].forEach((rhs) => {
|
504
|
-
run(() => {
|
505
|
-
operandTest(lhs, op, rhs);
|
506
|
-
});
|
507
|
-
});
|
508
|
-
run(() => {
|
509
|
-
operandTest(lhs, op, 'null');
|
510
|
-
});
|
511
|
-
});
|
512
|
-
});
|
513
|
-
});
|
514
|
-
})();
|
515
|
-
|
516
|
-
run(function () {
|
517
|
-
const left = createExpression('age', 'gt', 2);
|
518
|
-
const right = createExpression('age', 'lt', 10);
|
519
|
-
operandTest(left, 'and', right);
|
520
|
-
operandTest(left, 'or', right);
|
521
|
-
operandTest('is_experienced');
|
522
|
-
operandTest('not', 'is_experienced');
|
523
|
-
operandTest('not', left);
|
524
|
-
});
|
525
|
-
|
526
|
-
(function () {
|
527
|
-
const mathOps = ['add', 'sub', 'mul', 'div'];
|
528
|
-
mathOps.map((mathOp) => {
|
529
|
-
run(() => {
|
530
|
-
const mathOpExpr = createExpression('age', mathOp, 2);
|
531
|
-
operandTest(mathOpExpr, 'gt', 10);
|
532
|
-
});
|
533
|
-
});
|
534
|
-
})();
|
535
|
-
|
536
|
-
run(function () {
|
537
|
-
const odata = "name eq @name&@name='Pete'";
|
538
|
-
test(
|
539
|
-
`/pilot?$filter=${odata}`,
|
540
|
-
'GET',
|
541
|
-
[['Bind', '@name']],
|
542
|
-
(result, sqlEquals) => {
|
543
|
-
it('should select from pilot where "' + odata + '"', () => {
|
544
|
-
sqlEquals(
|
545
|
-
result,
|
546
|
-
`\
|
547
|
-
SELECT ${pilotFieldsStr}
|
548
|
-
FROM "pilot"
|
549
|
-
WHERE "pilot"."name" IS NOT NULL AND "pilot"."name" = ?`,
|
550
|
-
);
|
551
|
-
});
|
552
|
-
},
|
553
|
-
);
|
554
|
-
});
|
555
|
-
|
556
|
-
run(function () {
|
557
|
-
const odata = "name eq @x or favourite_colour eq @x&@x='Amber'";
|
558
|
-
test(
|
559
|
-
`/pilot?$filter=${odata}`,
|
560
|
-
'GET',
|
561
|
-
[['Bind', '@x']],
|
562
|
-
(result, sqlEquals) => {
|
563
|
-
it('should select from pilot where "' + odata + '"', () => {
|
564
|
-
sqlEquals(
|
565
|
-
result,
|
566
|
-
`\
|
567
|
-
SELECT ${pilotFieldsStr}
|
568
|
-
FROM "pilot"
|
569
|
-
WHERE ("pilot"."name" IS NOT NULL AND "pilot"."name" = $1
|
570
|
-
OR "pilot"."favourite colour" IS NOT NULL AND "pilot"."favourite colour" = $1)`,
|
571
|
-
);
|
572
|
-
});
|
573
|
-
},
|
574
|
-
);
|
575
|
-
});
|
576
|
-
|
577
|
-
run(function () {
|
578
|
-
const { odata, bindings, sql } = createExpression(
|
579
|
-
'can_fly__plane/id',
|
580
|
-
'eq',
|
581
|
-
10,
|
582
|
-
);
|
583
|
-
test(`/pilot?$filter=${odata}`, 'GET', bindings, (result, sqlEquals) => {
|
584
|
-
it('should select from pilot where "' + odata + '"', () => {
|
585
|
-
sqlEquals(
|
586
|
-
result,
|
587
|
-
`\
|
588
|
-
SELECT ${pilotFieldsStr}
|
589
|
-
FROM "pilot"
|
590
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
591
|
-
WHERE ${sql}`,
|
592
|
-
);
|
593
|
-
});
|
594
|
-
});
|
595
|
-
});
|
596
|
-
|
597
|
-
run(function () {
|
598
|
-
const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
|
599
|
-
const { odata, bindings } = createExpression('can_fly__plane/id', 'eq', 10);
|
600
|
-
test(
|
601
|
-
'/pilot(' + keyOdata + ')/can_fly__plane?$filter=' + odata,
|
602
|
-
'GET',
|
603
|
-
bindings.concat(keyBindings),
|
604
|
-
(result, sqlEquals) => {
|
605
|
-
it(
|
606
|
-
'should select from pilot__can_fly__plane where "' + odata + '"',
|
607
|
-
() => {
|
608
|
-
sqlEquals(
|
609
|
-
result,
|
610
|
-
`\
|
611
|
-
SELECT ${aliasPilotCanFlyPlaneFieldsStr}
|
612
|
-
FROM "pilot",
|
613
|
-
"pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
614
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.can fly-plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.can fly-plane"."id"
|
615
|
-
WHERE "pilot.pilot-can fly-plane.can fly-plane"."id" IS NOT NULL AND "pilot.pilot-can fly-plane.can fly-plane"."id" = ?
|
616
|
-
AND "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
617
|
-
AND "pilot"."id" IS NOT NULL AND "pilot"."id" = ?`,
|
618
|
-
);
|
619
|
-
},
|
620
|
-
);
|
621
|
-
},
|
622
|
-
);
|
623
|
-
});
|
624
|
-
|
625
|
-
run(function () {
|
626
|
-
const { odata, bindings, sql } = createExpression(
|
627
|
-
'can_fly__plane/plane/id',
|
628
|
-
'eq',
|
629
|
-
10,
|
630
|
-
);
|
631
|
-
const name = 'Peter';
|
632
|
-
const bodyBindings = [['Bind', ['pilot', 'name']], ...bindings] as const;
|
633
|
-
const insertTest: ExpectationSuccessFn = (result, sqlEquals) => {
|
634
|
-
sqlEquals(
|
635
|
-
result,
|
636
|
-
`\
|
637
|
-
INSERT INTO "pilot" ("name")
|
638
|
-
SELECT "$insert"."name"
|
639
|
-
FROM (
|
640
|
-
SELECT CAST(NULL AS TIMESTAMPTZ) AS "created at", CAST(NULL AS TIMESTAMPTZ) AS "modified at", CAST(NULL AS INTEGER) AS "id", CAST(NULL AS INTEGER) AS "person", CAST(NULL AS BOOLEAN) AS "is experienced", CAST(? AS VARCHAR(255)) AS "name", CAST(NULL AS INTEGER) AS "age", CAST(NULL AS INTEGER) AS "favourite colour", CAST(NULL AS INTEGER) AS "is on-team", CAST(NULL AS INTEGER) AS "licence", CAST(NULL AS TIMESTAMPTZ) AS "hire date", CAST(NULL AS INTEGER) AS "was trained by-pilot"
|
641
|
-
) AS "$insert"
|
642
|
-
WHERE EXISTS (
|
643
|
-
SELECT 1
|
644
|
-
FROM (
|
645
|
-
SELECT "$insert".*
|
646
|
-
) AS "pilot"
|
647
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
648
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
649
|
-
WHERE ${sql}
|
650
|
-
)`,
|
651
|
-
);
|
652
|
-
};
|
653
|
-
const updateWhere = `\
|
654
|
-
WHERE "pilot"."id" IN ((
|
655
|
-
SELECT "pilot"."id" AS "$modifyid"
|
656
|
-
FROM "pilot"
|
657
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
658
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
659
|
-
WHERE ${sql}
|
660
|
-
))`;
|
661
|
-
|
662
|
-
test(`/pilot?$filter=${odata}`, 'GET', bindings, (result, sqlEquals) => {
|
663
|
-
it(`should select from pilot where '${odata}'`, () => {
|
664
|
-
sqlEquals(
|
665
|
-
result,
|
666
|
-
`\
|
667
|
-
SELECT ${pilotFieldsStr}
|
668
|
-
FROM "pilot"
|
669
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
670
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
671
|
-
WHERE ${sql}`,
|
672
|
-
);
|
673
|
-
});
|
674
|
-
});
|
675
|
-
|
676
|
-
test(
|
677
|
-
`/pilot?$filter=${odata}`,
|
678
|
-
'PATCH',
|
679
|
-
bodyBindings,
|
680
|
-
{ name },
|
681
|
-
(result, sqlEquals) => {
|
682
|
-
it(`should update pilot where '${odata}'`, () => {
|
683
|
-
sqlEquals(
|
684
|
-
result,
|
685
|
-
`\
|
686
|
-
UPDATE "pilot"
|
687
|
-
SET "name" = ?
|
688
|
-
${updateWhere}`,
|
689
|
-
);
|
690
|
-
});
|
691
|
-
},
|
692
|
-
);
|
693
|
-
|
694
|
-
test(
|
695
|
-
`/pilot?$filter=${odata}`,
|
696
|
-
'POST',
|
697
|
-
bodyBindings,
|
698
|
-
{ name },
|
699
|
-
(result, sqlEquals) => {
|
700
|
-
it(`should insert pilot where '${odata}'`, () => {
|
701
|
-
insertTest(result, sqlEquals);
|
702
|
-
});
|
703
|
-
},
|
704
|
-
);
|
705
|
-
|
706
|
-
test(
|
707
|
-
`/pilot?$filter=${odata}`,
|
708
|
-
'PUT',
|
709
|
-
bodyBindings,
|
710
|
-
{ name },
|
711
|
-
(result, sqlEquals) => {
|
712
|
-
describe('should upsert the pilot with id 1', function () {
|
713
|
-
it('should be an upsert', () => {
|
714
|
-
expect(result).to.be.an('array');
|
715
|
-
});
|
716
|
-
it('that inserts', () => {
|
717
|
-
insertTest((result as SqlResult[])[0], sqlEquals);
|
718
|
-
});
|
719
|
-
it('and updates', () => {
|
720
|
-
sqlEquals(
|
721
|
-
(result as SqlResult[])[1],
|
722
|
-
`\
|
723
|
-
UPDATE "pilot"
|
724
|
-
SET "created at" = DEFAULT,
|
725
|
-
"modified at" = DEFAULT,
|
726
|
-
"id" = DEFAULT,
|
727
|
-
"person" = DEFAULT,
|
728
|
-
"is experienced" = DEFAULT,
|
729
|
-
"name" = ?,
|
730
|
-
"age" = DEFAULT,
|
731
|
-
"favourite colour" = DEFAULT,
|
732
|
-
"is on-team" = DEFAULT,
|
733
|
-
"licence" = DEFAULT,
|
734
|
-
"hire date" = DEFAULT,
|
735
|
-
"was trained by-pilot" = DEFAULT
|
736
|
-
${updateWhere}`,
|
737
|
-
);
|
738
|
-
});
|
739
|
-
});
|
740
|
-
},
|
741
|
-
);
|
742
|
-
|
743
|
-
test(`/pilot?$filter=${odata}`, 'DELETE', bindings, (result, sqlEquals) => {
|
744
|
-
it('should delete from pilot where "' + odata + '"', () => {
|
745
|
-
sqlEquals(
|
746
|
-
result,
|
747
|
-
`\
|
748
|
-
DELETE FROM "pilot"
|
749
|
-
WHERE "pilot"."id" IN ((
|
750
|
-
SELECT "pilot"."id" AS "$modifyid"
|
751
|
-
FROM "pilot"
|
752
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
753
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
754
|
-
WHERE ${sql}
|
755
|
-
))`,
|
756
|
-
);
|
757
|
-
});
|
758
|
-
});
|
759
|
-
});
|
760
|
-
|
761
|
-
run(function () {
|
762
|
-
const name = 'Peter';
|
763
|
-
const {
|
764
|
-
odata,
|
765
|
-
sql,
|
766
|
-
bindings: exprBindings,
|
767
|
-
} = createExpression('name', 'eq', `'${name}'`);
|
768
|
-
test(
|
769
|
-
`/pilot?$filter=${odata}`,
|
770
|
-
'POST',
|
771
|
-
[['Bind', ['pilot', 'name']], ...exprBindings],
|
772
|
-
{ name },
|
773
|
-
(result, sqlEquals) => {
|
774
|
-
it(`should insert into pilot where '${odata}'`, () => {
|
775
|
-
sqlEquals(
|
776
|
-
result,
|
777
|
-
`\
|
778
|
-
INSERT INTO "pilot" ("name")
|
779
|
-
SELECT "$insert"."name"
|
780
|
-
FROM (
|
781
|
-
SELECT CAST(NULL AS TIMESTAMPTZ) AS "created at", CAST(NULL AS TIMESTAMPTZ) AS "modified at", CAST(NULL AS INTEGER) AS "id", CAST(NULL AS INTEGER) AS "person", CAST(NULL AS BOOLEAN) AS "is experienced", CAST(? AS VARCHAR(255)) AS "name", CAST(NULL AS INTEGER) AS "age", CAST(NULL AS INTEGER) AS "favourite colour", CAST(NULL AS INTEGER) AS "is on-team", CAST(NULL AS INTEGER) AS "licence", CAST(NULL AS TIMESTAMPTZ) AS "hire date", CAST(NULL AS INTEGER) AS "was trained by-pilot"
|
782
|
-
) AS "$insert"
|
783
|
-
WHERE EXISTS (
|
784
|
-
SELECT 1
|
785
|
-
FROM (
|
786
|
-
SELECT "$insert".*
|
787
|
-
) AS "pilot"
|
788
|
-
WHERE ${sql}
|
789
|
-
)`,
|
790
|
-
);
|
791
|
-
});
|
792
|
-
},
|
793
|
-
);
|
794
|
-
});
|
795
|
-
|
796
|
-
run(function () {
|
797
|
-
const name = 'Peter';
|
798
|
-
const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
|
799
|
-
const {
|
800
|
-
odata,
|
801
|
-
sql,
|
802
|
-
bindings: exprBindings,
|
803
|
-
} = createExpression('name', 'eq', `'${name}'`);
|
804
|
-
const bodyBindings = [['Bind', ['pilot', 'name']]] as const;
|
805
|
-
const insertBindings = [
|
806
|
-
['Bind', ['pilot', 'id']],
|
807
|
-
...bodyBindings,
|
808
|
-
...exprBindings,
|
809
|
-
...keyBindings,
|
810
|
-
] as const;
|
811
|
-
const updateBindings = [
|
812
|
-
...bodyBindings,
|
813
|
-
...keyBindings,
|
814
|
-
...exprBindings,
|
815
|
-
] as const;
|
816
|
-
test(
|
817
|
-
'/pilot(' + keyOdata + ')?$filter=' + odata,
|
818
|
-
'PATCH',
|
819
|
-
updateBindings,
|
820
|
-
{ name },
|
821
|
-
(result, sqlEquals) => {
|
822
|
-
it('should update the pilot with id 1', () => {
|
823
|
-
sqlEquals(
|
824
|
-
result,
|
825
|
-
`\
|
826
|
-
UPDATE "pilot"
|
827
|
-
SET "name" = ?
|
828
|
-
WHERE "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
829
|
-
AND "pilot"."id" IN ((
|
830
|
-
SELECT "pilot"."id" AS "$modifyid"
|
831
|
-
FROM "pilot"
|
832
|
-
WHERE ${sql}
|
833
|
-
))`,
|
834
|
-
);
|
835
|
-
});
|
836
|
-
},
|
837
|
-
);
|
838
|
-
|
839
|
-
test(
|
840
|
-
'/pilot(' + keyOdata + ')?$filter=' + odata,
|
841
|
-
'PUT',
|
842
|
-
[insertBindings, [['Bind', ['pilot', 'id']], ...updateBindings]],
|
843
|
-
{ name },
|
844
|
-
(result, sqlEquals) => {
|
845
|
-
describe('should upsert the pilot with id 1', function () {
|
846
|
-
it('should be an upsert', () => {
|
847
|
-
expect(result).to.be.an('array');
|
848
|
-
});
|
849
|
-
it('that inserts', () => {
|
850
|
-
sqlEquals(
|
851
|
-
(result as SqlResult[])[0],
|
852
|
-
`\
|
853
|
-
INSERT INTO "pilot" ("id", "name")
|
854
|
-
SELECT "$insert"."id", "$insert"."name"
|
855
|
-
FROM (
|
856
|
-
SELECT CAST(NULL AS TIMESTAMPTZ) AS "created at", CAST(NULL AS TIMESTAMPTZ) AS "modified at", CAST(? AS INTEGER) AS "id", CAST(NULL AS INTEGER) AS "person", CAST(NULL AS BOOLEAN) AS "is experienced", CAST(? AS VARCHAR(255)) AS "name", CAST(NULL AS INTEGER) AS "age", CAST(NULL AS INTEGER) AS "favourite colour", CAST(NULL AS INTEGER) AS "is on-team", CAST(NULL AS INTEGER) AS "licence", CAST(NULL AS TIMESTAMPTZ) AS "hire date", CAST(NULL AS INTEGER) AS "was trained by-pilot"
|
857
|
-
) AS "$insert"
|
858
|
-
WHERE EXISTS (
|
859
|
-
SELECT 1
|
860
|
-
FROM (
|
861
|
-
SELECT "$insert".*
|
862
|
-
) AS "pilot"
|
863
|
-
WHERE ${sql}
|
864
|
-
AND "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
865
|
-
)`,
|
866
|
-
);
|
867
|
-
});
|
868
|
-
it('and updates', () => {
|
869
|
-
sqlEquals(
|
870
|
-
(result as SqlResult[])[1],
|
871
|
-
`\
|
872
|
-
UPDATE "pilot"
|
873
|
-
SET "created at" = DEFAULT,
|
874
|
-
"modified at" = DEFAULT,
|
875
|
-
"id" = ?,
|
876
|
-
"person" = DEFAULT,
|
877
|
-
"is experienced" = DEFAULT,
|
878
|
-
"name" = ?,
|
879
|
-
"age" = DEFAULT,
|
880
|
-
"favourite colour" = DEFAULT,
|
881
|
-
"is on-team" = DEFAULT,
|
882
|
-
"licence" = DEFAULT,
|
883
|
-
"hire date" = DEFAULT,
|
884
|
-
"was trained by-pilot" = DEFAULT
|
885
|
-
WHERE "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
886
|
-
AND "pilot"."id" IN ((
|
887
|
-
SELECT "pilot"."id" AS "$modifyid"
|
888
|
-
FROM "pilot"
|
889
|
-
WHERE ${sql}
|
890
|
-
))`,
|
891
|
-
);
|
892
|
-
});
|
893
|
-
});
|
894
|
-
},
|
895
|
-
);
|
896
|
-
});
|
897
|
-
|
898
|
-
run(function () {
|
899
|
-
const { odata: keyOdata, bindings: keyBindings } = parseOperand!(1);
|
900
|
-
const { odata, bindings, sql } = createExpression(
|
901
|
-
createExpression(1, 'eq', 1),
|
902
|
-
'or',
|
903
|
-
createExpression(1, 'eq', 1),
|
904
|
-
);
|
905
|
-
test(
|
906
|
-
'/pilot(' + keyOdata + ')/can_fly__plane?$filter=' + odata,
|
907
|
-
'GET',
|
908
|
-
bindings.concat(keyBindings),
|
909
|
-
(result, sqlEquals) => {
|
910
|
-
it(
|
911
|
-
'should select from pilot__can_fly__plane where "' + odata + '"',
|
912
|
-
() => {
|
913
|
-
sqlEquals(
|
914
|
-
result,
|
915
|
-
`\
|
916
|
-
SELECT ${aliasPilotCanFlyPlaneFieldsStr}
|
917
|
-
FROM "pilot",
|
918
|
-
"pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
919
|
-
WHERE ${sql}
|
920
|
-
AND "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
921
|
-
AND "pilot"."id" IS NOT NULL AND "pilot"."id" = ?`,
|
922
|
-
);
|
923
|
-
},
|
924
|
-
);
|
925
|
-
},
|
926
|
-
);
|
927
|
-
});
|
928
|
-
|
929
|
-
methodTest('contains', 'name', "'et'");
|
930
|
-
methodTest('endswith', 'name', "'ete'");
|
931
|
-
methodTest('startswith', 'name', "'P'");
|
932
|
-
run(() => {
|
933
|
-
operandTest(createMethodCall('length', 'name'), 'eq', 4);
|
934
|
-
});
|
935
|
-
|
936
|
-
run(() => {
|
937
|
-
operandTest(createMethodCall('indexof', 'name', "'Pe'"), 'eq', 0, {
|
938
|
-
sql: '(STRPOS("pilot"."name", $1) - 1) IS NOT NULL AND (STRPOS("pilot"."name", $1) - 1) = $2',
|
939
|
-
});
|
940
|
-
});
|
941
|
-
run(() => {
|
942
|
-
operandTest(createMethodCall('substring', 'name', 1), 'eq', "'ete'", {
|
943
|
-
sql: '(SUBSTRING("pilot"."name", $1 + 1)) IS NOT NULL AND (SUBSTRING("pilot"."name", $1 + 1)) = $2',
|
944
|
-
});
|
945
|
-
});
|
946
|
-
run(() => {
|
947
|
-
operandTest(createMethodCall('substring', 'name', 1, 2), 'eq', "'et'", {
|
948
|
-
sql: '(SUBSTRING("pilot"."name", $1 + 1, $2)) IS NOT NULL AND (SUBSTRING("pilot"."name", $1 + 1, $2)) = $3',
|
949
|
-
});
|
950
|
-
});
|
951
|
-
run(() => {
|
952
|
-
operandTest(createMethodCall('tolower', 'name'), 'eq', "'pete'");
|
953
|
-
});
|
954
|
-
run(() => {
|
955
|
-
operandTest(
|
956
|
-
createMethodCall('tolower', 'trained__pilot/name'),
|
957
|
-
'eq',
|
958
|
-
"'pete'",
|
959
|
-
);
|
960
|
-
});
|
961
|
-
run(() => {
|
962
|
-
operandTest(createMethodCall('toupper', 'name'), 'eq', "'PETE'");
|
963
|
-
});
|
964
|
-
run(function () {
|
965
|
-
const concat = createMethodCall('concat', 'name', "'%20'");
|
966
|
-
operandTest(createMethodCall('trim', concat), 'eq', "'Pete'", {
|
967
|
-
sql: '(TRIM(("pilot"."name" || $1))) IS NOT NULL AND (TRIM(("pilot"."name" || $1))) = $2',
|
968
|
-
});
|
969
|
-
});
|
970
|
-
run(function () {
|
971
|
-
const concat = createMethodCall('concat', 'name', "'%20'");
|
972
|
-
operandTest(concat, 'eq', "'Pete%20'", {
|
973
|
-
sql: '(("pilot"."name" || $1)) IS NOT NULL AND (("pilot"."name" || $1)) = $2',
|
974
|
-
});
|
975
|
-
});
|
976
|
-
run(() => {
|
977
|
-
operandTest(createMethodCall('year', 'hire_date'), 'eq', 2011);
|
978
|
-
});
|
979
|
-
run(() => {
|
980
|
-
operandTest(createMethodCall('month', 'hire_date'), 'eq', 10);
|
981
|
-
});
|
982
|
-
run(() => {
|
983
|
-
operandTest(createMethodCall('day', 'hire_date'), 'eq', 3);
|
984
|
-
});
|
985
|
-
run(() => {
|
986
|
-
operandTest(createMethodCall('hour', 'hire_date'), 'eq', 12);
|
987
|
-
});
|
988
|
-
run(() => {
|
989
|
-
operandTest(createMethodCall('minute', 'hire_date'), 'eq', 10);
|
990
|
-
});
|
991
|
-
run(() => {
|
992
|
-
operandTest(createMethodCall('second', 'hire_date'), 'eq', 25);
|
993
|
-
});
|
994
|
-
run(() => {
|
995
|
-
operandTest(createMethodCall('fractionalseconds', 'hire_date'), 'eq', 0.222);
|
996
|
-
});
|
997
|
-
run(() => {
|
998
|
-
operandTest(createMethodCall('date', 'hire_date'), 'eq', "'2011-10-03'");
|
999
|
-
});
|
1000
|
-
run(() => {
|
1001
|
-
operandTest(createMethodCall('time', 'hire_date'), 'eq', "'12:10:25.222'");
|
1002
|
-
});
|
1003
|
-
run(() => {
|
1004
|
-
operandTest(createMethodCall('now'), 'eq', new Date('2012-12-03T07:16:23Z'));
|
1005
|
-
});
|
1006
|
-
run(() => {
|
1007
|
-
operandTest(
|
1008
|
-
createMethodCall('totalseconds', {
|
1009
|
-
negative: true,
|
1010
|
-
day: 3,
|
1011
|
-
hour: 4,
|
1012
|
-
minute: 5,
|
1013
|
-
second: 6.7,
|
1014
|
-
}),
|
1015
|
-
'eq',
|
1016
|
-
-273906.7,
|
1017
|
-
);
|
1018
|
-
});
|
1019
|
-
run(() => {
|
1020
|
-
operandTest(createMethodCall('round', 'age'), 'eq', 25);
|
1021
|
-
});
|
1022
|
-
run(() => {
|
1023
|
-
operandTest(createMethodCall('floor', 'age'), 'eq', 25);
|
1024
|
-
});
|
1025
|
-
run(() => {
|
1026
|
-
operandTest(createMethodCall('ceiling', 'age'), 'eq', 25);
|
1027
|
-
});
|
1028
|
-
|
1029
|
-
methodTest('substringof', "'Pete'", 'name');
|
1030
|
-
run(() => {
|
1031
|
-
operandTest(
|
1032
|
-
createMethodCall('replace', 'name', "'ete'", "'at'"),
|
1033
|
-
'eq',
|
1034
|
-
"'Pat'",
|
1035
|
-
{
|
1036
|
-
sql: '(REPLACE("pilot"."name", $1, $2)) IS NOT NULL AND (REPLACE("pilot"."name", $1, $2)) = $3',
|
1037
|
-
},
|
1038
|
-
);
|
1039
|
-
});
|
1040
|
-
|
1041
|
-
test(
|
1042
|
-
"/pilot?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde')",
|
1043
|
-
'GET',
|
1044
|
-
[['Bind', 0]],
|
1045
|
-
(result, sqlEquals) => {
|
1046
|
-
it('should select from pilot where ...', () => {
|
1047
|
-
sqlEquals(
|
1048
|
-
result,
|
1049
|
-
`\
|
1050
|
-
SELECT ${pilotFieldsStr}
|
1051
|
-
FROM "pilot"
|
1052
|
-
WHERE EXISTS (
|
1053
|
-
SELECT 1
|
1054
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1055
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1056
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1057
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1058
|
-
)`,
|
1059
|
-
);
|
1060
|
-
});
|
1061
|
-
},
|
1062
|
-
);
|
1063
|
-
|
1064
|
-
test(
|
1065
|
-
"/pilot/$count?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde')",
|
1066
|
-
'GET',
|
1067
|
-
[['Bind', 0]],
|
1068
|
-
(result, sqlEquals) => {
|
1069
|
-
it('should select count(*) from pilot where ...', () => {
|
1070
|
-
sqlEquals(
|
1071
|
-
result,
|
1072
|
-
`\
|
1073
|
-
SELECT COUNT(*) AS "$count"
|
1074
|
-
FROM "pilot"
|
1075
|
-
WHERE EXISTS (
|
1076
|
-
SELECT 1
|
1077
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1078
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1079
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1080
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1081
|
-
)`,
|
1082
|
-
);
|
1083
|
-
});
|
1084
|
-
},
|
1085
|
-
);
|
1086
|
-
|
1087
|
-
test(
|
1088
|
-
"/pilot?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde') or (id eq 5 or id eq 10) or (name eq 'Peter' or name eq 'Harry')",
|
1089
|
-
'GET',
|
1090
|
-
[
|
1091
|
-
['Bind', 0],
|
1092
|
-
['Bind', 1],
|
1093
|
-
['Bind', 2],
|
1094
|
-
['Bind', 3],
|
1095
|
-
['Bind', 4],
|
1096
|
-
],
|
1097
|
-
(result, sqlEquals) => {
|
1098
|
-
it('should select count(*) from pilot where id in (5,10)', () => {
|
1099
|
-
sqlEquals(
|
1100
|
-
result,
|
1101
|
-
`\
|
1102
|
-
SELECT ${pilotFieldsStr}
|
1103
|
-
FROM "pilot"
|
1104
|
-
WHERE (EXISTS (
|
1105
|
-
SELECT 1
|
1106
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1107
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1108
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1109
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1110
|
-
)
|
1111
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1112
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1113
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?
|
1114
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?)`,
|
1115
|
-
);
|
1116
|
-
});
|
1117
|
-
},
|
1118
|
-
);
|
1119
|
-
|
1120
|
-
test(
|
1121
|
-
"/pilot?$filter=not(can_fly__plane/any(d:d/plane/name eq 'Concorde') or (id eq 5 or id eq 10) or (name eq 'Peter' or name eq 'Harry'))",
|
1122
|
-
'GET',
|
1123
|
-
[
|
1124
|
-
['Bind', 0],
|
1125
|
-
['Bind', 1],
|
1126
|
-
['Bind', 2],
|
1127
|
-
['Bind', 3],
|
1128
|
-
['Bind', 4],
|
1129
|
-
],
|
1130
|
-
(result, sqlEquals) => {
|
1131
|
-
it('should select count(*) from pilot where id in (5,10)', () => {
|
1132
|
-
sqlEquals(
|
1133
|
-
result,
|
1134
|
-
`\
|
1135
|
-
SELECT ${pilotFieldsStr}
|
1136
|
-
FROM "pilot"
|
1137
|
-
WHERE NOT (
|
1138
|
-
(EXISTS (
|
1139
|
-
SELECT 1
|
1140
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1141
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1142
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1143
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1144
|
-
)
|
1145
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1146
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1147
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?
|
1148
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?)
|
1149
|
-
)`,
|
1150
|
-
);
|
1151
|
-
});
|
1152
|
-
},
|
1153
|
-
);
|
1154
|
-
|
1155
|
-
test(
|
1156
|
-
"/pilot?$filter=can_fly__plane/all(d:d/plane/name eq 'Concorde')",
|
1157
|
-
'GET',
|
1158
|
-
[['Bind', 0]],
|
1159
|
-
(result, sqlEquals) => {
|
1160
|
-
it('should select from pilot where ...', () => {
|
1161
|
-
sqlEquals(
|
1162
|
-
result,
|
1163
|
-
`\
|
1164
|
-
SELECT ${pilotFieldsStr}
|
1165
|
-
FROM "pilot"
|
1166
|
-
WHERE NOT EXISTS (
|
1167
|
-
SELECT 1
|
1168
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1169
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1170
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1171
|
-
AND NOT (
|
1172
|
-
"pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1173
|
-
)
|
1174
|
-
)`,
|
1175
|
-
);
|
1176
|
-
});
|
1177
|
-
},
|
1178
|
-
);
|
1179
|
-
|
1180
|
-
test(
|
1181
|
-
"/pilot/$count?$filter=can_fly__plane/all(d:d/plane/name eq 'Concorde')",
|
1182
|
-
'GET',
|
1183
|
-
[['Bind', 0]],
|
1184
|
-
(result, sqlEquals) => {
|
1185
|
-
it('should select count(*) from pilot where ...', () => {
|
1186
|
-
sqlEquals(
|
1187
|
-
result,
|
1188
|
-
`\
|
1189
|
-
SELECT COUNT(*) AS "$count"
|
1190
|
-
FROM "pilot"
|
1191
|
-
WHERE NOT EXISTS (
|
1192
|
-
SELECT 1
|
1193
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1194
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1195
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1196
|
-
AND NOT (
|
1197
|
-
"pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1198
|
-
)
|
1199
|
-
)`,
|
1200
|
-
);
|
1201
|
-
});
|
1202
|
-
},
|
1203
|
-
);
|
1204
|
-
|
1205
|
-
test(
|
1206
|
-
"/pilot?$filter=can_fly__plane/plane/any(d:d/name eq 'Concorde')",
|
1207
|
-
'GET',
|
1208
|
-
[['Bind', 0]],
|
1209
|
-
(result, sqlEquals) => {
|
1210
|
-
it('should select from pilot where ...', () => {
|
1211
|
-
sqlEquals(
|
1212
|
-
result,
|
1213
|
-
`\
|
1214
|
-
SELECT ${pilotFieldsStr}
|
1215
|
-
FROM "pilot"
|
1216
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1217
|
-
WHERE EXISTS (
|
1218
|
-
SELECT 1
|
1219
|
-
FROM "plane" AS "pilot.pilot-can fly-plane.plane"
|
1220
|
-
WHERE "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1221
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1222
|
-
)`,
|
1223
|
-
);
|
1224
|
-
});
|
1225
|
-
},
|
1226
|
-
);
|
1227
|
-
|
1228
|
-
test(
|
1229
|
-
"/pilot/$count?$filter=can_fly__plane/plane/any(d:d/name eq 'Concorde')",
|
1230
|
-
'GET',
|
1231
|
-
[['Bind', 0]],
|
1232
|
-
(result, sqlEquals) => {
|
1233
|
-
it('should select count(*) from pilot where ...', () => {
|
1234
|
-
sqlEquals(
|
1235
|
-
result,
|
1236
|
-
`\
|
1237
|
-
SELECT COUNT(*) AS "$count"
|
1238
|
-
FROM "pilot"
|
1239
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1240
|
-
WHERE EXISTS (
|
1241
|
-
SELECT 1
|
1242
|
-
FROM "plane" AS "pilot.pilot-can fly-plane.plane"
|
1243
|
-
WHERE "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1244
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1245
|
-
)`,
|
1246
|
-
);
|
1247
|
-
});
|
1248
|
-
},
|
1249
|
-
);
|
1250
|
-
|
1251
|
-
test(
|
1252
|
-
"/pilot?$filter=can_fly__plane/plane/all(d:d/name eq 'Concorde')",
|
1253
|
-
'GET',
|
1254
|
-
[['Bind', 0]],
|
1255
|
-
(result, sqlEquals) => {
|
1256
|
-
it('should select from pilot where ...', () => {
|
1257
|
-
sqlEquals(
|
1258
|
-
result,
|
1259
|
-
`\
|
1260
|
-
SELECT ${pilotFieldsStr}
|
1261
|
-
FROM "pilot"
|
1262
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1263
|
-
WHERE NOT EXISTS (
|
1264
|
-
SELECT 1
|
1265
|
-
FROM "plane" AS "pilot.pilot-can fly-plane.plane"
|
1266
|
-
WHERE "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1267
|
-
AND NOT (
|
1268
|
-
"pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1269
|
-
)
|
1270
|
-
)`,
|
1271
|
-
);
|
1272
|
-
});
|
1273
|
-
},
|
1274
|
-
);
|
1275
|
-
|
1276
|
-
test(
|
1277
|
-
"/pilot/$count?$filter=can_fly__plane/plane/all(d:d/name eq 'Concorde')",
|
1278
|
-
'GET',
|
1279
|
-
[['Bind', 0]],
|
1280
|
-
(result, sqlEquals) => {
|
1281
|
-
it('should select count(*) from pilot where ...', () => {
|
1282
|
-
sqlEquals(
|
1283
|
-
result,
|
1284
|
-
`\
|
1285
|
-
SELECT COUNT(*) AS "$count"
|
1286
|
-
FROM "pilot"
|
1287
|
-
LEFT JOIN "pilot-can fly-plane" AS "pilot.pilot-can fly-plane" ON "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1288
|
-
WHERE NOT EXISTS (
|
1289
|
-
SELECT 1
|
1290
|
-
FROM "plane" AS "pilot.pilot-can fly-plane.plane"
|
1291
|
-
WHERE "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1292
|
-
AND NOT (
|
1293
|
-
"pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1294
|
-
)
|
1295
|
-
)`,
|
1296
|
-
);
|
1297
|
-
});
|
1298
|
-
},
|
1299
|
-
);
|
1300
|
-
|
1301
|
-
test(
|
1302
|
-
"/pilot?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde') or (id eq 5 or name eq 'Peter') or (id eq 10 or name eq 'Harry')",
|
1303
|
-
'GET',
|
1304
|
-
[
|
1305
|
-
['Bind', 0],
|
1306
|
-
['Bind', 1],
|
1307
|
-
['Bind', 2],
|
1308
|
-
['Bind', 3],
|
1309
|
-
['Bind', 4],
|
1310
|
-
],
|
1311
|
-
(result, sqlEquals) => {
|
1312
|
-
it('should select count(*) from pilot where id in (5,10)', () => {
|
1313
|
-
sqlEquals(
|
1314
|
-
result,
|
1315
|
-
`\
|
1316
|
-
SELECT ${pilotFieldsStr}
|
1317
|
-
FROM "pilot"
|
1318
|
-
WHERE (EXISTS (
|
1319
|
-
SELECT 1
|
1320
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1321
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1322
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1323
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1324
|
-
)
|
1325
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1326
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?
|
1327
|
-
OR "pilot"."id" IS NOT NULL AND "pilot"."id" = ?
|
1328
|
-
OR "pilot"."name" IS NOT NULL AND "pilot"."name" = ?)`,
|
1329
|
-
);
|
1330
|
-
});
|
1331
|
-
},
|
1332
|
-
);
|
1333
|
-
|
1334
|
-
test(
|
1335
|
-
"/pilot?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde') and (id ne 5 and id ne 10) and (name ne 'Peter' and name ne 'Harry')",
|
1336
|
-
'GET',
|
1337
|
-
[
|
1338
|
-
['Bind', 0],
|
1339
|
-
['Bind', 1],
|
1340
|
-
['Bind', 2],
|
1341
|
-
['Bind', 3],
|
1342
|
-
['Bind', 4],
|
1343
|
-
],
|
1344
|
-
(result, sqlEquals) => {
|
1345
|
-
it('should select count(*) from pilot where id in (5,10)', () => {
|
1346
|
-
sqlEquals(
|
1347
|
-
result,
|
1348
|
-
`\
|
1349
|
-
SELECT ${pilotFieldsStr}
|
1350
|
-
FROM "pilot"
|
1351
|
-
WHERE EXISTS (
|
1352
|
-
SELECT 1
|
1353
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1354
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1355
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1356
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1357
|
-
)
|
1358
|
-
AND NOT("pilot"."id" IS NOT NULL AND "pilot"."id" = ?)
|
1359
|
-
AND NOT("pilot"."id" IS NOT NULL AND "pilot"."id" = ?)
|
1360
|
-
AND NOT("pilot"."name" IS NOT NULL AND "pilot"."name" = ?)
|
1361
|
-
AND NOT("pilot"."name" IS NOT NULL AND "pilot"."name" = ?)`,
|
1362
|
-
);
|
1363
|
-
});
|
1364
|
-
},
|
1365
|
-
);
|
1366
|
-
|
1367
|
-
test(
|
1368
|
-
"/pilot?$filter=can_fly__plane/any(d:d/plane/name eq 'Concorde') and (id ne 5 and name ne 'Peter') and (id ne 10 and name ne 'Harry')",
|
1369
|
-
'GET',
|
1370
|
-
[
|
1371
|
-
['Bind', 0],
|
1372
|
-
['Bind', 1],
|
1373
|
-
['Bind', 2],
|
1374
|
-
['Bind', 3],
|
1375
|
-
['Bind', 4],
|
1376
|
-
],
|
1377
|
-
(result, sqlEquals) => {
|
1378
|
-
it('should select count(*) from pilot where id in (5,10)', () => {
|
1379
|
-
sqlEquals(
|
1380
|
-
result,
|
1381
|
-
`\
|
1382
|
-
SELECT ${pilotFieldsStr}
|
1383
|
-
FROM "pilot"
|
1384
|
-
WHERE EXISTS (
|
1385
|
-
SELECT 1
|
1386
|
-
FROM "pilot-can fly-plane" AS "pilot.pilot-can fly-plane"
|
1387
|
-
LEFT JOIN "plane" AS "pilot.pilot-can fly-plane.plane" ON "pilot.pilot-can fly-plane"."can fly-plane" = "pilot.pilot-can fly-plane.plane"."id"
|
1388
|
-
WHERE "pilot"."id" = "pilot.pilot-can fly-plane"."pilot"
|
1389
|
-
AND "pilot.pilot-can fly-plane.plane"."name" IS NOT NULL AND "pilot.pilot-can fly-plane.plane"."name" = ?
|
1390
|
-
)
|
1391
|
-
AND NOT("pilot"."id" IS NOT NULL AND "pilot"."id" = ?)
|
1392
|
-
AND NOT("pilot"."name" IS NOT NULL AND "pilot"."name" = ?)
|
1393
|
-
AND NOT("pilot"."id" IS NOT NULL AND "pilot"."id" = ?)
|
1394
|
-
AND NOT("pilot"."name" IS NOT NULL AND "pilot"."name" = ?)`,
|
1395
|
-
);
|
1396
|
-
});
|
1397
|
-
},
|
1398
|
-
);
|
1399
|
-
|
1400
|
-
// Switch parseOperandFactory permanently to using 'team' as the resource,
|
1401
|
-
// as we are switch to using that as our base resource from here on.
|
1402
|
-
parseOperandFactory = _.partialRight(parseOperandFactory, 'team');
|
1403
|
-
run(function () {
|
1404
|
-
const favouriteColour = 'purple';
|
1405
|
-
const { odata, sql, bindings } = createExpression(
|
1406
|
-
'favourite_colour',
|
1407
|
-
'eq',
|
1408
|
-
`'${favouriteColour}'`,
|
1409
|
-
);
|
1410
|
-
test(
|
1411
|
-
'/team?$filter=' + odata,
|
1412
|
-
'POST',
|
1413
|
-
[['Bind', ['team', 'favourite_colour']], ...bindings],
|
1414
|
-
{ favourite_colour: favouriteColour },
|
1415
|
-
(result, sqlEquals) => {
|
1416
|
-
it('should insert into team where "' + odata + '"', () => {
|
1417
|
-
sqlEquals(
|
1418
|
-
result,
|
1419
|
-
`\
|
1420
|
-
INSERT INTO "team" ("favourite colour")
|
1421
|
-
SELECT "$insert"."favourite colour"
|
1422
|
-
FROM (
|
1423
|
-
SELECT CAST(NULL AS TIMESTAMPTZ) AS "created at", CAST(NULL AS TIMESTAMPTZ) AS "modified at", CAST(? AS INTEGER) AS "favourite colour"
|
1424
|
-
) AS "$insert"
|
1425
|
-
WHERE EXISTS (
|
1426
|
-
SELECT 1
|
1427
|
-
FROM (
|
1428
|
-
SELECT "$insert".*
|
1429
|
-
) AS "team"
|
1430
|
-
WHERE ${sql}
|
1431
|
-
)`,
|
1432
|
-
);
|
1433
|
-
});
|
1434
|
-
},
|
1435
|
-
);
|
1436
|
-
});
|
1437
|
-
|
1438
|
-
run(function () {
|
1439
|
-
const { odata, sql, bindings } = createExpression(
|
1440
|
-
'includes__pilot/can_fly__plane/plane/name',
|
1441
|
-
'eq',
|
1442
|
-
"'Concorde'",
|
1443
|
-
);
|
1444
|
-
test('/team?$filter=' + odata, 'GET', bindings, (result, sqlEquals) => {
|
1445
|
-
it('should select from team where "' + odata + '"', () => {
|
1446
|
-
sqlEquals(
|
1447
|
-
result,
|
1448
|
-
`\
|
1449
|
-
SELECT ${teamFieldsStr}
|
1450
|
-
FROM "team"
|
1451
|
-
LEFT JOIN "pilot" AS "team.includes-pilot" ON "team"."favourite colour" = "team.includes-pilot"."is on-team"
|
1452
|
-
LEFT JOIN "pilot-can fly-plane" AS "team.includes-pilot.pilot-can fly-plane" ON "team.includes-pilot"."id" = "team.includes-pilot.pilot-can fly-plane"."pilot"
|
1453
|
-
LEFT JOIN "plane" AS "team.includes-pilot.pilot-can fly-plane.plane" ON "team.includes-pilot.pilot-can fly-plane"."can fly-plane" = "team.includes-pilot.pilot-can fly-plane.plane"."id"
|
1454
|
-
WHERE ${sql}`,
|
1455
|
-
);
|
1456
|
-
});
|
1457
|
-
});
|
1458
|
-
});
|
1459
|
-
|
1460
|
-
run(function () {
|
1461
|
-
const odata = "now() sub created_at lt duration'P1D'";
|
1462
|
-
test(`/pilot?$filter=${odata}`, 'GET', [], (result, sqlEquals) => {
|
1463
|
-
it('should select from pilot where "' + odata + '"', () => {
|
1464
|
-
sqlEquals(
|
1465
|
-
result,
|
1466
|
-
`\
|
1467
|
-
SELECT ${pilotFieldsStr}
|
1468
|
-
FROM "pilot"
|
1469
|
-
WHERE CURRENT_TIMESTAMP - DATE_TRUNC('milliseconds', "pilot"."created at", 'UTC') < INTERVAL '1 0:0:0.0'`,
|
1470
|
-
);
|
1471
|
-
});
|
1472
|
-
});
|
1473
|
-
});
|
1474
|
-
|
1475
|
-
run(function () {
|
1476
|
-
const odata = 'now() add now()';
|
1477
|
-
test.fail(`/pilot?$filter=${odata}`, 'GET', [], (err) => {
|
1478
|
-
it(
|
1479
|
-
'should fail to add current_timestamp to current_timestamp where "' +
|
1480
|
-
odata +
|
1481
|
-
'"',
|
1482
|
-
() => {
|
1483
|
-
expect(err).to.be.instanceOf(Error);
|
1484
|
-
},
|
1485
|
-
);
|
1486
|
-
});
|
1487
|
-
});
|
1488
|
-
|
1489
|
-
run(function () {
|
1490
|
-
const odata = "created_at add duration'P1D' gt now()";
|
1491
|
-
test(`/pilot?$filter=${odata}`, 'GET', [], (result, sqlEquals) => {
|
1492
|
-
it('should select from pilot where "' + odata + '"', () => {
|
1493
|
-
sqlEquals(
|
1494
|
-
result,
|
1495
|
-
`\
|
1496
|
-
SELECT ${pilotFieldsStr}
|
1497
|
-
FROM "pilot"
|
1498
|
-
WHERE DATE_TRUNC('milliseconds', "pilot"."created at", 'UTC') + INTERVAL '1 0:0:0.0' > CURRENT_TIMESTAMP`,
|
1499
|
-
);
|
1500
|
-
});
|
1501
|
-
});
|
1502
|
-
});
|
1503
|
-
|
1504
|
-
run(function () {
|
1505
|
-
const odata = "totalseconds(duration'P1D') gt 1";
|
1506
|
-
test(`/pilot?$filter=${odata}`, 'GET', [['Bind', 0]], (result, sqlEquals) => {
|
1507
|
-
it('should select from pilot where "' + odata + '"', () => {
|
1508
|
-
sqlEquals(
|
1509
|
-
result,
|
1510
|
-
`\
|
1511
|
-
SELECT ${pilotFieldsStr}
|
1512
|
-
FROM "pilot"
|
1513
|
-
WHERE EXTRACT(EPOCH FROM INTERVAL '1 0:0:0.0') > $1`,
|
1514
|
-
);
|
1515
|
-
});
|
1516
|
-
});
|
1517
|
-
});
|