@malloydata/malloy-tests 0.0.95-dev231019211822 → 0.0.95

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 (84) hide show
  1. package/README.md +213 -1
  2. package/dist/api.spec.d.ts +1 -1
  3. package/dist/api.spec.js +6 -13
  4. package/dist/api.spec.js.map +1 -1
  5. package/dist/databases/all/db_index.spec.js +21 -41
  6. package/dist/databases/all/db_index.spec.js.map +1 -1
  7. package/dist/databases/all/expr.spec.js +262 -339
  8. package/dist/databases/all/expr.spec.js.map +1 -1
  9. package/dist/databases/all/functions.spec.js +37 -35
  10. package/dist/databases/all/functions.spec.js.map +1 -1
  11. package/dist/databases/all/join.spec.js +125 -169
  12. package/dist/databases/all/join.spec.js.map +1 -1
  13. package/dist/databases/all/nomodel.spec.js +335 -594
  14. package/dist/databases/all/nomodel.spec.js.map +1 -1
  15. package/dist/databases/all/orderby.spec.js +82 -128
  16. package/dist/databases/all/orderby.spec.js.map +1 -1
  17. package/dist/databases/all/sql_expressions.spec.js +27 -43
  18. package/dist/databases/all/sql_expressions.spec.js.map +1 -1
  19. package/dist/databases/all/time.spec.js +63 -103
  20. package/dist/databases/all/time.spec.js.map +1 -1
  21. package/dist/databases/bigquery/double_truncation.spec.js +1 -1
  22. package/dist/databases/bigquery/handexpr.spec.js +12 -12
  23. package/dist/databases/bigquery/injestion_time_partitioning.spec.js +22 -22
  24. package/dist/databases/bigquery/joined_filters.spec.js +3 -3
  25. package/dist/databases/bigquery/json.spec.d.ts +1 -1
  26. package/dist/databases/bigquery/json.spec.js +25 -45
  27. package/dist/databases/bigquery/json.spec.js.map +1 -1
  28. package/dist/databases/bigquery/malloy_query.spec.d.ts +1 -1
  29. package/dist/databases/bigquery/malloy_query.spec.js +47 -48
  30. package/dist/databases/bigquery/malloy_query.spec.js.map +1 -1
  31. package/dist/databases/bigquery/time.spec.js +9 -13
  32. package/dist/databases/bigquery/time.spec.js.map +1 -1
  33. package/dist/databases/bigquery/wildcard_table_names.spec.js +19 -19
  34. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js +53 -87
  35. package/dist/databases/bigquery-duckdb/nested_source_table.spec.js.map +1 -1
  36. package/dist/databases/bigquery-postgres/multi_connection.spec.js +5 -20
  37. package/dist/databases/bigquery-postgres/multi_connection.spec.js.map +1 -1
  38. package/dist/databases/bigquery-postgres/streaming.spec.js +6 -6
  39. package/dist/databases/bigquery-postgres/streaming.spec.js.map +1 -1
  40. package/dist/databases/duckdb/duckdb.spec.js +24 -33
  41. package/dist/databases/duckdb/duckdb.spec.js.map +1 -1
  42. package/dist/databases/postgres/postgres.spec.js +46 -67
  43. package/dist/databases/postgres/postgres.spec.js.map +1 -1
  44. package/dist/jestMatcher.spec.d.ts +1 -0
  45. package/dist/jestMatcher.spec.js +81 -0
  46. package/dist/jestMatcher.spec.js.map +1 -0
  47. package/dist/render/render.spec.js +10 -12
  48. package/dist/render/render.spec.js.map +1 -1
  49. package/dist/tags.spec.js +22 -2
  50. package/dist/tags.spec.js.map +1 -1
  51. package/dist/util/db-jest-matchers.d.ts +17 -6
  52. package/dist/util/db-jest-matchers.js +81 -20
  53. package/dist/util/db-jest-matchers.js.map +1 -1
  54. package/dist/util/index.d.ts +1 -2
  55. package/dist/util/index.js +11 -13
  56. package/dist/util/index.js.map +1 -1
  57. package/package.json +6 -6
  58. package/src/api.spec.ts +7 -16
  59. package/src/databases/all/db_index.spec.ts +22 -48
  60. package/src/databases/all/expr.spec.ts +273 -431
  61. package/src/databases/all/functions.spec.ts +37 -35
  62. package/src/databases/all/join.spec.ts +130 -196
  63. package/src/databases/all/nomodel.spec.ts +333 -689
  64. package/src/databases/all/orderby.spec.ts +87 -161
  65. package/src/databases/all/sql_expressions.spec.ts +29 -49
  66. package/src/databases/all/time.spec.ts +73 -130
  67. package/src/databases/bigquery/double_truncation.spec.ts +1 -1
  68. package/src/databases/bigquery/handexpr.spec.ts +12 -12
  69. package/src/databases/bigquery/injestion_time_partitioning.spec.ts +22 -22
  70. package/src/databases/bigquery/joined_filters.spec.ts +3 -3
  71. package/src/databases/bigquery/json.spec.ts +25 -49
  72. package/src/databases/bigquery/malloy_query.spec.ts +47 -54
  73. package/src/databases/bigquery/time.spec.ts +13 -17
  74. package/src/databases/bigquery/wildcard_table_names.spec.ts +19 -19
  75. package/src/databases/bigquery-duckdb/nested_source_table.spec.ts +56 -98
  76. package/src/databases/bigquery-postgres/multi_connection.spec.ts +5 -23
  77. package/src/databases/bigquery-postgres/streaming.spec.ts +12 -6
  78. package/src/databases/duckdb/duckdb.spec.ts +31 -43
  79. package/src/databases/postgres/postgres.spec.ts +54 -84
  80. package/src/jestMatcher.spec.ts +88 -0
  81. package/src/render/render.spec.ts +10 -12
  82. package/src/tags.spec.ts +22 -2
  83. package/src/util/db-jest-matchers.ts +106 -32
  84. package/src/util/index.ts +16 -14
@@ -0,0 +1,88 @@
1
+ /* eslint-disable no-console */
2
+ /*
3
+ * Copyright 2023 Google LLC
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining
6
+ * a copy of this software and associated documentation files
7
+ * (the "Software"), to deal in the Software without restriction,
8
+ * including without limitation the rights to use, copy, modify, merge,
9
+ * publish, distribute, sublicense, and/or sell copies of the Software,
10
+ * and to permit persons to whom the Software is furnished to do so,
11
+ * subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be
14
+ * included in all copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+
25
+ import {runtimeFor} from './runtimes';
26
+ import './util/db-jest-matchers';
27
+
28
+ const runtime = runtimeFor('duckdb');
29
+
30
+ // uncomment out the skip if you want to play with the matchers
31
+ describe.skip('malloyResultMatches', () => {
32
+ const sampleSource = `duckdb.sql("""
33
+ SELECT 42 as num, 'whynot' as reason
34
+ UNION ALL SELECT 49, 'because'""")`;
35
+ const model = runtime.loadModel(`source: sampleSource is ${sampleSource}`);
36
+ const runtimeOrModel = runtime || model;
37
+
38
+ test('simple', async () => {
39
+ await expect(`
40
+ run: ${sampleSource}
41
+ `).malloyResultMatches(runtime, {num: 42, reason: 'whynot'});
42
+ });
43
+
44
+ test('nested', async () => {
45
+ await expect(`
46
+ run: sampleSource -> {
47
+ nest: the_nest is {
48
+ select: nestNum is num, nestWhy is reasons
49
+ }
50
+ }
51
+ `).malloyResultMatches(model, {
52
+ 'the_nest.nestNum': 42,
53
+ 'theNest.nestWhy': 'whynot',
54
+ });
55
+ });
56
+
57
+ test('multiple rows', async () => {
58
+ await expect(`
59
+ run: ${sampleSource}
60
+ `).malloyResultMatches(runtime, [
61
+ {num: 42, reason: 'whynot'},
62
+ {num: 49, reason: 'because'},
63
+ ]);
64
+ });
65
+
66
+ test('malloyResultMatches with an error', async () => {
67
+ await expect(`
68
+ rug: ${sampleSource}
69
+ `).malloyResultMatches(runtime, [
70
+ {num: 42, reason: 'whynot'},
71
+ {num: 49, reason: 'because'},
72
+ ]);
73
+ });
74
+
75
+ test('wrong data', async () => {
76
+ await expect(`
77
+ run: ${sampleSource}
78
+ `).malloyResultMatches(runtime, {num: 24, reason: 'i said so'});
79
+ });
80
+
81
+ test('failing exactly one row', async () => {
82
+ await expect(`
83
+ run: ${sampleSource}
84
+ `).malloyResultMatches(runtimeOrModel, [{}]);
85
+ });
86
+ });
87
+
88
+ afterAll(async () => await runtime.connection.close());
@@ -71,7 +71,7 @@ describe('rendering results', () => {
71
71
  expect(runtime).toBeDefined();
72
72
  if (runtime) {
73
73
  const src = `
74
- query: table('malloy-data.faa.flights') -> {
74
+ run: bigquery.table('malloy-data.faa.flights') -> {
75
75
  group_by: carrier
76
76
  aggregate: flight_count is count()
77
77
  }
@@ -216,7 +216,7 @@ describe('rendering results', () => {
216
216
  UNION ALL SELECT 'Miguel', 3, 35, 4.2, 31, 1
217
217
  UNION ALL SELECT 'Miguel', 4, 47, 4.3, 76, 0 """) extend {
218
218
 
219
- query: by_name is {
219
+ view: by_name is {
220
220
  group_by: nm
221
221
  nest: height_by_age
222
222
  # line_chart
@@ -236,12 +236,10 @@ describe('rendering results', () => {
236
236
  }
237
237
  }
238
238
 
239
- query: by_name is height -> by_name {
240
- }
239
+ query: by_name is height -> by_name
241
240
 
242
241
  # transpose
243
- query: by_name_transposed is height -> by_name {
244
- }
242
+ query: by_name_transposed is height -> by_name
245
243
 
246
244
  source: names is duckdb.sql("""SELECT 'Pedro' as nm
247
245
  UNION ALL SELECT 'Sebastian'
@@ -291,7 +289,7 @@ describe('rendering results', () => {
291
289
  # hidden
292
290
  dimension: price is apptcost
293
291
 
294
- query: by_name is {
292
+ view: by_name is {
295
293
  group_by: nm
296
294
  order_by: nm
297
295
  nest: height_by_age
@@ -320,7 +318,7 @@ describe('rendering results', () => {
320
318
  }
321
319
 
322
320
  # dashboard
323
- query: by_name_db is by_name {}
321
+ view: by_name_db is by_name {}
324
322
  }
325
323
 
326
324
  query: by_name is height -> by_name {}
@@ -378,7 +376,7 @@ describe('rendering results', () => {
378
376
  # currency
379
377
  dimension: floc is loc
380
378
 
381
- query: by_name is {
379
+ view: by_name is {
382
380
  group_by: nm
383
381
  # pivot { dimensions=["dayito"] }
384
382
  nest: pivot_f is {
@@ -400,7 +398,7 @@ describe('rendering results', () => {
400
398
  }
401
399
  }
402
400
 
403
- query: by_name is height -> by_name {}
401
+ query: by_name is height -> by_name
404
402
  `;
405
403
  const result = await (
406
404
  await duckdb.loadModel(src).loadQueryByName('by_name')
@@ -461,8 +459,8 @@ describe('rendering results', () => {
461
459
  describe('bar chart renderer', () => {
462
460
  test('date with timezone rendered correctly', async () => {
463
461
  const src = `
464
- query: mex_query # bar_chart
465
- is duckdb.sql('SELECT 1') -> {
462
+ query: mex_query is # bar_chart
463
+ duckdb.sql('SELECT 1') -> {
466
464
  timezone: 'America/Mexico_City'
467
465
  select: mex_time is @2021-02-24 03:05:06
468
466
  }
package/src/tags.spec.ts CHANGED
@@ -129,12 +129,32 @@ describe('tagParse to Tag', () => {
129
129
  ['x=.7e2', {x: {eq: '.7e2'}}],
130
130
  ['x=7E2', {x: {eq: '7E2'}}],
131
131
  ['`spacey name`=Zaphod', {'spacey name': {eq: 'Zaphod'}}],
132
+ [
133
+ 'image { alt=hello { field=department } }',
134
+ {
135
+ image: {
136
+ properties: {
137
+ alt: {eq: 'hello', properties: {field: {eq: 'department'}}},
138
+ },
139
+ },
140
+ },
141
+ ],
142
+ [
143
+ 'image image.alt=hello image.alt.field=department',
144
+ {
145
+ image: {
146
+ properties: {
147
+ alt: {eq: 'hello', properties: {field: {eq: 'department'}}},
148
+ },
149
+ },
150
+ },
151
+ ],
132
152
  ];
133
153
  test.each(tagTests)('tag %s', (expression: string, expected: TagDict) => {
134
154
  expect(expression).tagsAre(expected);
135
155
  });
136
- test('uncomment to debug just one of the expressions', () => {
137
- const x: TagTestTuple = ['a=a b=$(a)', {a: {eq: 'a'}, b: {eq: 'a'}}];
156
+ test.skip('unskip to debug just one of the expressions', () => {
157
+ const x: TagTestTuple = ['x x.y', {x: {properties: {y: {}}}}];
138
158
  expect(x[0]).tagsAre(x[1]);
139
159
  });
140
160
  });
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-console */
1
2
  /*
2
3
  * Copyright 2023 Google LLC
3
4
  *
@@ -22,29 +23,43 @@
22
23
  */
23
24
 
24
25
  import {
26
+ ModelMaterializer,
25
27
  QueryMaterializer,
26
28
  Result,
27
- SingleConnectionRuntime,
29
+ Runtime,
30
+ MalloyError,
31
+ LogMessage,
28
32
  } from '@malloydata/malloy';
29
33
 
34
+ type ExpectedResultRow = Record<string, unknown>;
35
+ type ExpectedResult = ExpectedResultRow | ExpectedResultRow[];
36
+ type Runner = Runtime | ModelMaterializer;
37
+
30
38
  declare global {
31
39
  // eslint-disable-next-line @typescript-eslint/no-namespace
32
40
  namespace jest {
33
41
  interface Matchers<R> {
34
42
  isSqlEq(): R;
35
43
  /**
36
- * Jest matcher for running a Malloy query, assumes you only care about
37
- * columns in the first row.
44
+ * Jest matcher for running a Malloy query, checks that each row
45
+ * contains the values matching the template. If you only want to
46
+ * check the first row, use the first form. If you want to check
47
+ * multiple rows, use the second.
48
+ *
49
+ * await expect('query').malloyResultMatches(runtime, {colName: colValue});
50
+ * await expect('query').malloyResultMatches(runtime, [{colName: colValue}]);
38
51
  *
39
- * await expect(runtime).queryMatches('query', {colName: colValue});
52
+ * * If "colName" has a dot in it, it is assumed to be a reference to a value in a nest
53
+ * * If you use an array, the number of rows in the result must match the rows in the match
54
+ * * The empty match {} accepts ANY data, but will errror if there is not a row
40
55
  *
41
- * @param runtime Database connection runtime
42
56
  * @param querySrc Malloy source, last query in source will be run
43
- * @param expected Key value pairs
57
+ * @param runtime Database connection runtime OR Model ( for the call to loadQuery )
58
+ * @param expected Key value pairs or array of key value pairs
44
59
  */
45
- queryMatches(
46
- querySrc: string,
47
- matchVals: Record<string, unknown>
60
+ malloyResultMatches(
61
+ runtime: Runner,
62
+ matchVals: ExpectedResult
48
63
  ): Promise<R>;
49
64
  }
50
65
  }
@@ -73,56 +88,115 @@ expect.extend({
73
88
  };
74
89
  },
75
90
 
76
- async queryMatches(
77
- runtime: SingleConnectionRuntime,
91
+ async malloyResultMatches(
78
92
  querySrc: string,
79
- expected: Record<string, unknown>
93
+ runtime: Runner,
94
+ shouldEqual: ExpectedResult
80
95
  ) {
81
- if (!runtime.supportsNesting && querySrc.indexOf('nest:') >= 0) {
82
- return {
83
- pass: true,
84
- message: () =>
85
- 'Test was skipped since connection does not support nesting.',
86
- };
96
+ // TODO -- THIS IS NOT OK BUT I AM NOT FIXING IT NOW
97
+ if (querySrc.indexOf('nest:') >= 0) {
98
+ if (runtime instanceof Runtime) {
99
+ return {
100
+ pass: true,
101
+ message: () =>
102
+ 'Test was skipped since connection does not support nesting.',
103
+ };
104
+ }
87
105
  }
88
106
 
89
107
  let query: QueryMaterializer;
90
108
  try {
91
109
  query = runtime.loadQuery(querySrc);
92
110
  } catch (e) {
93
- return {pass: false, message: () => `loadQuery failed: ${e.message}`};
111
+ return {
112
+ pass: false,
113
+ message: () => `loadQuery failed: ${e.message}`,
114
+ };
94
115
  }
95
116
 
96
117
  let result: Result;
97
118
  try {
98
119
  result = await query.run();
99
120
  } catch (e) {
100
- const failMsg =
101
- `query.run failed: ${e.message}\n` + `SQL: ${await query.getSQL()}`;
121
+ let failMsg = `query.run failed: ${e.message}`;
122
+ if (e instanceof MalloyError) {
123
+ failMsg = `Error in query compilation\n${errorLogToString(
124
+ querySrc,
125
+ e.problems
126
+ )}`;
127
+ } else {
128
+ try {
129
+ failMsg += `\nSQL: ${await query.getSQL()}`;
130
+ } catch (e2) {
131
+ // we could not show the SQL for unknown reasons
132
+ }
133
+ }
102
134
  return {pass: false, message: () => failMsg};
103
135
  }
104
136
 
137
+ const allRows = Array.isArray(shouldEqual) ? shouldEqual : [shouldEqual];
138
+ let i = 0;
105
139
  const fails: string[] = [];
106
- for (const [name, value] of Object.entries(expected)) {
107
- try {
108
- const got = result.data.path(0, name).value;
109
- const mustBe = value instanceof Date ? value.getTime() : value;
110
- const actuallyGot = got instanceof Date ? got.getTime() : got;
111
- if (actuallyGot !== mustBe) {
112
- fails.push(`Expected {${name}: ${value}} Got: ${got}`);
140
+ const gotRows = result.data.toObject().length;
141
+ if (Array.isArray(shouldEqual)) {
142
+ if (gotRows !== allRows.length) {
143
+ fails.push(`Expected result.rows=${allRows.length} Got: ${gotRows}`);
144
+ }
145
+ }
146
+ for (const expected of allRows) {
147
+ for (const [name, value] of Object.entries(expected)) {
148
+ const pExpect = JSON.stringify(value);
149
+ const row = allRows.length > 1 ? `[${i}]` : '';
150
+ const expected = `Expected ${row}{${name}: ${pExpect}}`;
151
+ try {
152
+ const nestOne = name.split('.');
153
+ const resultPath = [i, nestOne[0]];
154
+ for (const child of nestOne.slice(1)) {
155
+ resultPath.push(0);
156
+ resultPath.push(child);
157
+ }
158
+ const got = result.data.path(...resultPath).value;
159
+ const pGot = JSON.stringify(got);
160
+ const mustBe = value instanceof Date ? value.getTime() : value;
161
+ const actuallyGot = got instanceof Date ? got.getTime() : got;
162
+ if (typeof mustBe === 'number' && typeof actuallyGot !== 'number') {
163
+ fails.push(`${expected} Got: Non Numeric '${pGot}'`);
164
+ } else if (actuallyGot !== mustBe) {
165
+ fails.push(`${expected} Got: ${pGot}`);
166
+ }
167
+ } catch (e) {
168
+ fails.push(`${expected} Error: ${e.message}`);
113
169
  }
114
- } catch (e) {
115
- fails.push(`Expected {${name}: ${value}} Error: ${e.message}`);
116
170
  }
171
+ i += 1;
117
172
  }
118
173
  if (fails.length !== 0) {
119
- const failMsg = `SQL: ${await query.getSQL()}\n${fails.join('\n')}`;
174
+ const fromSQL = ' ' + (await query.getSQL()).split('\n').join('\n ');
175
+ const failMsg = `SQL Generated:\n${fromSQL}\n${fails.join('\n')}`;
120
176
  return {pass: false, message: () => failMsg};
121
177
  }
122
178
 
123
179
  return {
124
180
  pass: true,
125
- message: () => `First row matched ${JSON.stringify(expected)}`,
181
+ message: () => 'All rows matched expected results',
126
182
  };
127
183
  },
128
184
  });
185
+
186
+ function errorLogToString(src: string, msgs: LogMessage[]) {
187
+ let lovely = '';
188
+ let lineNo = 0;
189
+ for (const line of src.split('\n')) {
190
+ lovely += ` | ${line}\n`;
191
+ for (const entry of msgs) {
192
+ if (entry.at) {
193
+ if (entry.at.range.start.line === lineNo) {
194
+ const charFrom = entry.at.range.start.character;
195
+ lovely += `!!!!! ${' '.repeat(charFrom)}^ ${entry.message}\n`;
196
+ }
197
+ }
198
+ }
199
+ lineNo += 1;
200
+ }
201
+ return lovely;
202
+ }
package/src/util/index.ts CHANGED
@@ -83,7 +83,6 @@ export function describeIfDatabaseAvailable(
83
83
  interface InitValues {
84
84
  sql?: string;
85
85
  malloy?: string;
86
- connection?: string;
87
86
  }
88
87
 
89
88
  function sqlSafe(str: string): string {
@@ -92,7 +91,12 @@ function sqlSafe(str: string): string {
92
91
  .replace(/\\/g, '{backslash}')
93
92
  .replace(/"/g, '{double-quote}');
94
93
  }
95
- export function mkSqlEqWith(runtime: Runtime, initV?: InitValues) {
94
+
95
+ export function mkSqlEqWith(
96
+ runtime: Runtime,
97
+ cName: string,
98
+ initV?: InitValues
99
+ ) {
96
100
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
97
101
  return async function (
98
102
  expr: string,
@@ -101,12 +105,8 @@ export function mkSqlEqWith(runtime: Runtime, initV?: InitValues) {
101
105
  const qExpr = expr.replace(/'/g, '`');
102
106
  const sqlV = initV?.sql || 'SELECT 1 as one';
103
107
  const malloyV = initV?.malloy || '';
104
- const select = initV?.connection
105
- ? ` connection: "${initV.connection}" select`
106
- : 'select';
107
108
  const sourceDef = `
108
- sql: sqlData is {${select}: """${sqlV}""" }
109
- source: basicTypes is from_sql(sqlData) ${malloyV}
109
+ source: basicTypes is ${cName}.sql("""${sqlV}""") ${malloyV}
110
110
  `;
111
111
  let query: string;
112
112
  if (typeof result === 'boolean') {
@@ -117,17 +117,19 @@ export function mkSqlEqWith(runtime: Runtime, initV?: InitValues) {
117
117
  : `${notEq} when ${varName}`;
118
118
  const elsePick = result ? notEq : "'='";
119
119
  query = `${sourceDef}
120
- query: basicTypes
120
+ run: basicTypes
121
121
  -> {
122
- declare: ${varName} is ${expr}
122
+ extend: {dimension: ${varName} is ${expr}}
123
123
  select: calc is pick ${whenPick} else ${elsePick}
124
124
  }`;
125
125
  } else if (typeof result === 'number') {
126
126
  query = `${sourceDef}
127
- query: basicTypes
127
+ run: basicTypes
128
128
  -> {
129
- declare: expect is ${result}
130
- declare: got is ${expr}
129
+ extend: {
130
+ dimension: expect is ${result}
131
+ dimension: got is ${expr}
132
+ }
131
133
  select: calc is
132
134
  pick '=' when expect = got
133
135
  else concat('sqlEq failed', CHR(10), ' Expected: ${qExpr} == ${result}', CHR(10), ' Received: ', got::string)
@@ -137,7 +139,7 @@ export function mkSqlEqWith(runtime: Runtime, initV?: InitValues) {
137
139
  const resultNoBacks = result.replace(/\\/g, '\\\\');
138
140
  const qResult = `'${resultNoBacks.replace(/'/g, "\\'")}'`;
139
141
  query = `${sourceDef}
140
- query: basicTypes
142
+ run: basicTypes
141
143
  -> {
142
144
  select: expect is ${qResult}
143
145
  select: got is ${expr}
@@ -151,7 +153,7 @@ export function mkSqlEqWith(runtime: Runtime, initV?: InitValues) {
151
153
  } else {
152
154
  const qResult = result.replace(/'/g, '`');
153
155
  query = `${sourceDef}
154
- query: basicTypes
156
+ run: basicTypes
155
157
  -> {
156
158
  select: expect is ${result}
157
159
  select: got is ${expr}