@balena/abstract-sql-compiler 11.0.0-build-11-x-45529f014aa1c181f338c0f7348767f2990a9084-1 → 11.0.0

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.
Files changed (53) hide show
  1. package/package.json +5 -2
  2. package/.github/workflows/flowzone.yml +0 -21
  3. package/.husky/pre-commit +0 -2
  4. package/.versionbot/CHANGELOG.yml +0 -10729
  5. package/CHANGELOG.md +0 -3515
  6. package/repo.yml +0 -12
  7. package/src/abstract-sql-compiler.ts +0 -1138
  8. package/src/abstract-sql-optimizer.ts +0 -1632
  9. package/src/abstract-sql-rules-to-sql.ts +0 -1730
  10. package/src/abstract-sql-schema-optimizer.ts +0 -172
  11. package/src/referenced-fields.ts +0 -600
  12. package/test/abstract-sql/aggregate-json.ts +0 -49
  13. package/test/abstract-sql/aggregate.ts +0 -161
  14. package/test/abstract-sql/and-or-boolean-optimisations.ts +0 -115
  15. package/test/abstract-sql/case-when-else.ts +0 -48
  16. package/test/abstract-sql/cast.ts +0 -25
  17. package/test/abstract-sql/coalesce.ts +0 -24
  18. package/test/abstract-sql/comparisons.ts +0 -360
  19. package/test/abstract-sql/dates.ts +0 -512
  20. package/test/abstract-sql/duration.ts +0 -56
  21. package/test/abstract-sql/empty-query-optimisations.ts +0 -54
  22. package/test/abstract-sql/functions-wrapper.ts +0 -70
  23. package/test/abstract-sql/get-referenced-fields.ts +0 -674
  24. package/test/abstract-sql/get-rule-referenced-fields.ts +0 -345
  25. package/test/abstract-sql/insert-query.ts +0 -22
  26. package/test/abstract-sql/is-distinct.ts +0 -102
  27. package/test/abstract-sql/joins.ts +0 -84
  28. package/test/abstract-sql/json.ts +0 -58
  29. package/test/abstract-sql/math.ts +0 -467
  30. package/test/abstract-sql/nested-in-optimisations.ts +0 -200
  31. package/test/abstract-sql/not-not-optimisations.ts +0 -15
  32. package/test/abstract-sql/schema-checks.ts +0 -168
  33. package/test/abstract-sql/schema-informative-reference.ts +0 -420
  34. package/test/abstract-sql/schema-rule-optimization.ts +0 -120
  35. package/test/abstract-sql/schema-rule-to-check.ts +0 -393
  36. package/test/abstract-sql/schema-views.ts +0 -73
  37. package/test/abstract-sql/test.ts +0 -192
  38. package/test/abstract-sql/text.ts +0 -168
  39. package/test/model.sbvr +0 -60
  40. package/test/odata/expand.ts +0 -674
  41. package/test/odata/fields.ts +0 -59
  42. package/test/odata/filterby.ts +0 -1517
  43. package/test/odata/orderby.ts +0 -96
  44. package/test/odata/paging.ts +0 -48
  45. package/test/odata/resource-parsing.ts +0 -568
  46. package/test/odata/select.ts +0 -119
  47. package/test/odata/stress.ts +0 -93
  48. package/test/odata/test.ts +0 -297
  49. package/test/sbvr/pilots.ts +0 -1097
  50. package/test/sbvr/reference-type.ts +0 -211
  51. package/test/sbvr/test.ts +0 -101
  52. package/tsconfig.build.json +0 -6
  53. package/tsconfig.json +0 -25
@@ -1,393 +0,0 @@
1
- import * as AbstractSQLCompiler from '../../out/abstract-sql-compiler.js';
2
- import { expect } from 'chai';
3
-
4
- const generateSchema = (
5
- abstractSqlModel: AbstractSQLCompiler.AbstractSqlModel,
6
- ) =>
7
- AbstractSQLCompiler.postgres.compileSchema(
8
- AbstractSQLCompiler.postgres.optimizeSchema(abstractSqlModel),
9
- );
10
-
11
- it('should convert a basic rule to a check using NOT EXISTS', () => {
12
- expect(
13
- generateSchema({
14
- synonyms: {},
15
- relationships: {},
16
- tables: {
17
- test: {
18
- name: 'test',
19
- resourceName: 'test',
20
- idField: 'id',
21
- fields: [
22
- {
23
- fieldName: 'id',
24
- dataType: 'Integer',
25
- index: 'PRIMARY KEY',
26
- },
27
- ],
28
- indexes: [],
29
- primitive: false,
30
- },
31
- },
32
- rules: [
33
- [
34
- 'Rule',
35
- [
36
- 'Body',
37
- [
38
- 'Not',
39
- [
40
- 'Exists',
41
- [
42
- 'SelectQuery',
43
- ['Select', []],
44
- ['From', ['Alias', ['Table', 'test'], 'test.0']],
45
- [
46
- 'Where',
47
- [
48
- 'Not',
49
- [
50
- 'And',
51
- [
52
- 'LessThan',
53
- ['Integer', 0],
54
- ['ReferencedField', 'test.0', 'id'],
55
- ],
56
- ['Exists', ['ReferencedField', 'test.0', 'id']],
57
- ],
58
- ],
59
- ],
60
- ],
61
- ],
62
- ],
63
- ],
64
- [
65
- 'StructuredEnglish',
66
- 'It is necessary that each test has an id that is greater than 0.',
67
- ],
68
- ],
69
- ],
70
- lfInfo: { rules: {} },
71
- }),
72
- )
73
- .to.have.property('createSchema')
74
- .that.deep.equals([
75
- `\
76
- CREATE TABLE IF NOT EXISTS "test" (
77
- "id" INTEGER NULL PRIMARY KEY
78
- , -- It is necessary that each test has an id that is greater than 0.
79
- CONSTRAINT "test$hkEwz3pzAqalNu6crijhhdWJ0ffUvqRGK8rMkQbViPg=" CHECK (0 < "id"
80
- AND "id" IS NOT NULL)
81
- );`,
82
- ]);
83
- });
84
-
85
- it('should convert a basic rule to a check using COUNT(*) = 0', () => {
86
- expect(
87
- generateSchema({
88
- synonyms: {},
89
- relationships: {},
90
- tables: {
91
- test: {
92
- name: 'test',
93
- resourceName: 'test',
94
- idField: 'id',
95
- fields: [
96
- {
97
- fieldName: 'id',
98
- dataType: 'Integer',
99
- index: 'PRIMARY KEY',
100
- },
101
- ],
102
- indexes: [],
103
- primitive: false,
104
- },
105
- },
106
- rules: [
107
- [
108
- 'Rule',
109
- [
110
- 'Body',
111
- [
112
- 'Equals',
113
- [
114
- 'SelectQuery',
115
- ['Select', [['Count', '*']]],
116
- ['From', ['Alias', ['Table', 'test'], 'test.0']],
117
- [
118
- 'Where',
119
- [
120
- 'Not',
121
- [
122
- 'And',
123
- [
124
- 'LessThan',
125
- ['Integer', 0],
126
- ['ReferencedField', 'test.0', 'id'],
127
- ],
128
- ['Exists', ['ReferencedField', 'test.0', 'id']],
129
- ],
130
- ],
131
- ],
132
- ],
133
- ['Number', 0],
134
- ],
135
- ],
136
- [
137
- 'StructuredEnglish',
138
- 'It is necessary that each test has an id that is greater than 0.',
139
- ],
140
- ],
141
- ],
142
- lfInfo: { rules: {} },
143
- }),
144
- )
145
- .to.have.property('createSchema')
146
- .that.deep.equals([
147
- `\
148
- CREATE TABLE IF NOT EXISTS "test" (
149
- "id" INTEGER NULL PRIMARY KEY
150
- , -- It is necessary that each test has an id that is greater than 0.
151
- CONSTRAINT "test$qEORqfvLM2D8/gu0ZEVfvrnt19+uBo55ipVGKTdmu0k=" CHECK (0 < "id"
152
- AND "id" IS NOT NULL)
153
- );`,
154
- ]);
155
- });
156
-
157
- it('should correctly shorten a converted check rule with a long name', () => {
158
- expect(
159
- generateSchema({
160
- synonyms: {},
161
- relationships: {},
162
- tables: {
163
- test_table_with_very_very_long_name: {
164
- name: 'test_table_with_very_very_long_name',
165
- resourceName: 'test_table_with_very_very_long_name',
166
- idField: 'id',
167
- fields: [
168
- {
169
- fieldName: 'id',
170
- dataType: 'Integer',
171
- index: 'PRIMARY KEY',
172
- },
173
- ],
174
- indexes: [],
175
- primitive: false,
176
- },
177
- },
178
- rules: [
179
- [
180
- 'Rule',
181
- [
182
- 'Body',
183
- [
184
- 'Not',
185
- [
186
- 'Exists',
187
- [
188
- 'SelectQuery',
189
- ['Select', []],
190
- [
191
- 'From',
192
- [
193
- 'Alias',
194
- ['Table', 'test_table_with_very_very_long_name'],
195
- 'test_table_with_very_very_long_name.0',
196
- ],
197
- ],
198
- [
199
- 'Where',
200
- [
201
- 'Not',
202
- [
203
- 'And',
204
- [
205
- 'LessThan',
206
- ['Integer', 0],
207
- [
208
- 'ReferencedField',
209
- 'test_table_with_very_very_long_name.0',
210
- 'id',
211
- ],
212
- ],
213
- [
214
- 'Exists',
215
- [
216
- 'ReferencedField',
217
- 'test_table_with_very_very_long_name.0',
218
- 'id',
219
- ],
220
- ],
221
- ],
222
- ],
223
- ],
224
- ],
225
- ],
226
- ],
227
- ],
228
- [
229
- 'StructuredEnglish',
230
- 'It is necessary that each test_table_with_very_very_long_name has an id that is greater than 0.',
231
- ],
232
- ],
233
- ],
234
- lfInfo: { rules: {} },
235
- }),
236
- )
237
- .to.have.property('createSchema')
238
- .that.deep.equals([
239
- `\
240
- CREATE TABLE IF NOT EXISTS "test_table_with_very_very_long_name" (
241
- "id" INTEGER NULL PRIMARY KEY
242
- , -- It is necessary that each test_table_with_very_very_long_name has an id that is greater than 0.
243
- CONSTRAINT "test_table_with_very_very_long$9z+XEkP4EI1mhDQ8SiLulo2NLmenGY1C" CHECK (0 < "id"
244
- AND "id" IS NOT NULL)
245
- );`,
246
- ]);
247
- });
248
-
249
- it('should work with differing table/resource names using NOT EXISTS', () => {
250
- expect(
251
- generateSchema({
252
- synonyms: {},
253
- relationships: {},
254
- tables: {
255
- some_other_resource_name: {
256
- name: 'test',
257
- resourceName: 'some_other_resource_name',
258
- idField: 'id',
259
- fields: [
260
- {
261
- fieldName: 'id',
262
- dataType: 'Integer',
263
- index: 'PRIMARY KEY',
264
- },
265
- ],
266
- indexes: [],
267
- primitive: false,
268
- },
269
- },
270
- rules: [
271
- [
272
- 'Rule',
273
- [
274
- 'Body',
275
- [
276
- 'Not',
277
- [
278
- 'Exists',
279
- [
280
- 'SelectQuery',
281
- ['Select', []],
282
- ['From', ['Alias', ['Table', 'test'], 'test.0']],
283
- [
284
- 'Where',
285
- [
286
- 'Not',
287
- [
288
- 'And',
289
- [
290
- 'LessThan',
291
- ['Integer', 0],
292
- ['ReferencedField', 'test.0', 'id'],
293
- ],
294
- ['Exists', ['ReferencedField', 'test.0', 'id']],
295
- ],
296
- ],
297
- ],
298
- ],
299
- ],
300
- ],
301
- ],
302
- [
303
- 'StructuredEnglish',
304
- 'It is necessary that each test has an id that is greater than 0.',
305
- ],
306
- ],
307
- ],
308
- lfInfo: { rules: {} },
309
- }),
310
- )
311
- .to.have.property('createSchema')
312
- .that.deep.equals([
313
- `\
314
- CREATE TABLE IF NOT EXISTS "test" (
315
- "id" INTEGER NULL PRIMARY KEY
316
- , -- It is necessary that each test has an id that is greater than 0.
317
- CONSTRAINT "test$hkEwz3pzAqalNu6crijhhdWJ0ffUvqRGK8rMkQbViPg=" CHECK (0 < "id"
318
- AND "id" IS NOT NULL)
319
- );`,
320
- ]);
321
- });
322
-
323
- it('should work with differing table/resource names using COUNT(*) = 0', () => {
324
- expect(
325
- generateSchema({
326
- synonyms: {},
327
- relationships: {},
328
- tables: {
329
- some_other_resource_name: {
330
- name: 'test',
331
- resourceName: 'some_other_resource_name',
332
- idField: 'id',
333
- fields: [
334
- {
335
- fieldName: 'id',
336
- dataType: 'Integer',
337
- index: 'PRIMARY KEY',
338
- },
339
- ],
340
- indexes: [],
341
- primitive: false,
342
- },
343
- },
344
- rules: [
345
- [
346
- 'Rule',
347
- [
348
- 'Body',
349
- [
350
- 'Equals',
351
- [
352
- 'SelectQuery',
353
- ['Select', [['Count', '*']]],
354
- ['From', ['Alias', ['Table', 'test'], 'test.0']],
355
- [
356
- 'Where',
357
- [
358
- 'Not',
359
- [
360
- 'And',
361
- [
362
- 'LessThan',
363
- ['Integer', 0],
364
- ['ReferencedField', 'test.0', 'id'],
365
- ],
366
- ['Exists', ['ReferencedField', 'test.0', 'id']],
367
- ],
368
- ],
369
- ],
370
- ],
371
- ['Number', 0],
372
- ],
373
- ],
374
- [
375
- 'StructuredEnglish',
376
- 'It is necessary that each test has an id that is greater than 0.',
377
- ],
378
- ],
379
- ],
380
- lfInfo: { rules: {} },
381
- }),
382
- )
383
- .to.have.property('createSchema')
384
- .that.deep.equals([
385
- `\
386
- CREATE TABLE IF NOT EXISTS "test" (
387
- "id" INTEGER NULL PRIMARY KEY
388
- , -- It is necessary that each test has an id that is greater than 0.
389
- CONSTRAINT "test$qEORqfvLM2D8/gu0ZEVfvrnt19+uBo55ipVGKTdmu0k=" CHECK (0 < "id"
390
- AND "id" IS NOT NULL)
391
- );`,
392
- ]);
393
- });
@@ -1,73 +0,0 @@
1
- import * as AbstractSQLCompiler from '../../out/abstract-sql-compiler.js';
2
- import { expect } from 'chai';
3
-
4
- it('a table with a static definition should not produce a view', () => {
5
- expect(
6
- AbstractSQLCompiler.postgres.compileSchema({
7
- synonyms: {},
8
- relationships: {},
9
- tables: {
10
- test: {
11
- name: 'test',
12
- resourceName: 'test',
13
- idField: 'id',
14
- fields: [
15
- {
16
- fieldName: 'id',
17
- dataType: 'Integer',
18
- index: 'PRIMARY KEY',
19
- },
20
- ],
21
- indexes: [],
22
- primitive: false,
23
- definition: { abstractSql: ['Table', 'other table'] },
24
- },
25
- },
26
- rules: [],
27
- lfInfo: { rules: {} },
28
- }),
29
- )
30
- .to.have.property('createSchema')
31
- .that.deep.equals([
32
- `\
33
- CREATE TABLE IF NOT EXISTS "test" (
34
- "id" INTEGER NULL PRIMARY KEY
35
- );`,
36
- ]);
37
- });
38
-
39
- it('a table with a view definition should produce a view', () => {
40
- expect(
41
- AbstractSQLCompiler.postgres.compileSchema({
42
- synonyms: {},
43
- relationships: {},
44
- tables: {
45
- test: {
46
- name: 'test',
47
- resourceName: 'test',
48
- idField: 'id',
49
- fields: [
50
- {
51
- fieldName: 'id',
52
- dataType: 'Integer',
53
- index: 'PRIMARY KEY',
54
- },
55
- ],
56
- indexes: [],
57
- primitive: false,
58
- viewDefinition: { abstractSql: ['Table', 'other table'] },
59
- },
60
- },
61
- rules: [],
62
- lfInfo: { rules: {} },
63
- }),
64
- )
65
- .to.have.property('createSchema')
66
- .that.deep.equals([
67
- `\
68
- CREATE OR REPLACE VIEW "test" AS (
69
- SELECT *
70
- FROM "other table"
71
- );`,
72
- ]);
73
- });
@@ -1,192 +0,0 @@
1
- import * as AbstractSQLCompiler from '../../out/abstract-sql-compiler.js';
2
-
3
- import { expect } from 'chai';
4
- import _ from 'lodash';
5
-
6
- type ExpectedBindings = Array<
7
- AbstractSQLCompiler.Binding | AbstractSQLCompiler.Binding[]
8
- >;
9
- const bindingsTest = function (
10
- actualBindings: AbstractSQLCompiler.Binding[],
11
- expectedBindings: AbstractSQLCompiler.Binding[] | false = false,
12
- ) {
13
- if (expectedBindings === false) {
14
- it('should not have any bindings', () => {
15
- expect(actualBindings).to.be.empty;
16
- });
17
- } else {
18
- it('should have matching bindings', () => {
19
- expect(actualBindings).to.deep.equal(expectedBindings);
20
- });
21
- }
22
- };
23
-
24
- type SqlEquals = (
25
- actual:
26
- | AbstractSQLCompiler.SqlResult
27
- | AbstractSQLCompiler.SqlResult[]
28
- | string,
29
- expected: string,
30
- ) => void;
31
- const equals: SqlEquals = (actual, expected) => {
32
- if (typeof actual !== 'string') {
33
- if (Array.isArray(actual)) {
34
- throw new Error('Expected a single query, got multiple');
35
- }
36
- actual = actual.query;
37
- }
38
- expect(actual).to.equal(expected);
39
- };
40
- const sqlEquals = {
41
- websql: equals,
42
- mysql: equals,
43
- postgres(actual, expected) {
44
- let num = 1;
45
- while (_.includes(expected, '?')) {
46
- expected = expected.replace('?', '$' + num);
47
- num++;
48
- }
49
- equals(actual, expected);
50
- },
51
- } satisfies Record<string, SqlEquals>;
52
-
53
- type ExpectationSuccessFn = (
54
- result:
55
- | AbstractSQLCompiler.SqlResult
56
- | [AbstractSQLCompiler.SqlResult, AbstractSQLCompiler.SqlResult],
57
- sqlEquals: SqlEquals,
58
- ) => void;
59
- type ExpectationFailFn = (result: Error) => void;
60
- type ExpectationFn<ExpectFail extends boolean> = ExpectFail extends true
61
- ? ExpectationFailFn
62
- : ExpectationSuccessFn;
63
-
64
- function runExpectation<ExpectFail extends boolean>(
65
- describe: Mocha.SuiteFunction,
66
- engine: keyof typeof sqlEquals,
67
- expectFailure: ExpectFail,
68
- input: AbstractSQLCompiler.AbstractSqlQuery,
69
- expectedBindings: ExpectedBindings | false,
70
- expectation: ExpectationFn<ExpectFail>,
71
- ): void;
72
- function runExpectation<ExpectFail extends boolean>(
73
- describe: Mocha.SuiteFunction,
74
- engine: keyof typeof sqlEquals,
75
- expectFailure: ExpectFail,
76
- input: AbstractSQLCompiler.AbstractSqlQuery,
77
- expectation: ExpectationFn<ExpectFail>,
78
- ): void;
79
- function runExpectation<ExpectFail extends boolean>(
80
- describe: Mocha.SuiteFunction,
81
- engine: keyof typeof sqlEquals,
82
- expectFailure: ExpectFail,
83
- input: AbstractSQLCompiler.AbstractSqlQuery,
84
- ...args:
85
- | [expectation: ExpectationFn<ExpectFail>]
86
- | [
87
- expectedBindings: ExpectedBindings | false,
88
- expectation: ExpectationFn<ExpectFail>,
89
- ]
90
- ): void {
91
- let expectedBindings: ExpectedBindings | false = false;
92
- let expectation: ExpectationFn<ExpectFail>;
93
- switch (args.length) {
94
- case 1:
95
- [expectation] = args;
96
- break;
97
- case 2:
98
- [expectedBindings, expectation] = args;
99
- break;
100
- }
101
-
102
- describe('Parsing ' + JSON.stringify(input), function () {
103
- let result;
104
- try {
105
- result = AbstractSQLCompiler[engine].compileRule(input);
106
- } catch (e: any) {
107
- if (!expectFailure) {
108
- throw e;
109
- }
110
- (expectation as ExpectationFailFn)(e);
111
- return;
112
- }
113
- if (expectFailure) {
114
- throw new Error("Expected failure but didn't get one");
115
- }
116
- if (Array.isArray(result)) {
117
- for (let i = 0; i < result.length; i++) {
118
- const actualResult = result[i];
119
- if (expectedBindings === false) {
120
- bindingsTest(actualResult.bindings, false);
121
- } else if (expectedBindings[0][0] === 'Bind') {
122
- bindingsTest(
123
- actualResult.bindings,
124
- expectedBindings as AbstractSQLCompiler.Binding[],
125
- );
126
- } else {
127
- bindingsTest(
128
- actualResult.bindings,
129
- expectedBindings[i] as AbstractSQLCompiler.Binding[],
130
- );
131
- }
132
- }
133
- } else {
134
- bindingsTest(
135
- result.bindings,
136
- expectedBindings as AbstractSQLCompiler.Binding[],
137
- );
138
- }
139
- (expectation as ExpectationSuccessFn)(result, sqlEquals[engine]);
140
- });
141
- }
142
-
143
- interface BoundRunExpectation<ExpectFail extends boolean> {
144
- (
145
- input: AbstractSQLCompiler.AbstractSqlQuery,
146
- expectedBindings: ExpectedBindings | false,
147
- expectation: ExpectationFn<ExpectFail>,
148
- ): void;
149
- (
150
- input: AbstractSQLCompiler.AbstractSqlQuery,
151
- expectation: ExpectationFn<ExpectFail>,
152
- ): void;
153
- (
154
- input: AbstractSQLCompiler.AbstractSqlQuery,
155
- ...args:
156
- | [expectation: ExpectationFn<ExpectFail>]
157
- | [
158
- expectedBindings: ExpectedBindings | false,
159
- expectation: ExpectationFn<ExpectFail>,
160
- ]
161
- ): void;
162
- }
163
-
164
- type MochaBoundRunExpectation = BoundRunExpectation<false> & {
165
- fail: BoundRunExpectation<true>;
166
- skip: BoundRunExpectation<false>;
167
- only: BoundRunExpectation<false>;
168
- };
169
- const bindRunExpectation = function (engine: keyof typeof sqlEquals) {
170
- const bound: MochaBoundRunExpectation = runExpectation.bind(
171
- null,
172
- describe,
173
- engine,
174
- false,
175
- );
176
- bound.fail = runExpectation.bind(null, describe, engine, true);
177
- bound.skip = runExpectation.bind(null, describe.skip, engine, false);
178
- // eslint-disable-next-line no-only-tests/no-only-tests -- this is a false positive
179
- bound.only = runExpectation.bind(null, describe.only, engine, false);
180
- return bound;
181
- };
182
-
183
- const testFn = bindRunExpectation('postgres') as MochaBoundRunExpectation & {
184
- postgres: MochaBoundRunExpectation;
185
- mysql: MochaBoundRunExpectation;
186
- websql: MochaBoundRunExpectation;
187
- };
188
- testFn.postgres = bindRunExpectation('postgres');
189
- testFn.mysql = bindRunExpectation('mysql');
190
- testFn.websql = bindRunExpectation('websql');
191
-
192
- export default testFn;