@malloydata/malloy-tests 0.0.135 → 0.0.136-dev240326234246
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/dist/api.spec.d.ts +1 -0
- package/dist/api.spec.js +113 -0
- package/dist/api.spec.js.map +1 -0
- package/dist/databases/all/db_index.spec.d.ts +1 -0
- package/dist/databases/all/db_index.spec.js +126 -0
- package/dist/databases/all/db_index.spec.js.map +1 -0
- package/dist/databases/all/expr.spec.d.ts +1 -0
- package/dist/databases/all/expr.spec.js +652 -0
- package/dist/databases/all/expr.spec.js.map +1 -0
- package/dist/databases/all/functions.spec.d.ts +1 -0
- package/dist/databases/all/functions.spec.js +1180 -0
- package/dist/databases/all/functions.spec.js.map +1 -0
- package/dist/databases/all/join.spec.d.ts +1 -0
- package/dist/databases/all/join.spec.js +255 -0
- package/dist/databases/all/join.spec.js.map +1 -0
- package/dist/databases/all/lenses.spec.d.ts +1 -0
- package/dist/databases/all/lenses.spec.js +374 -0
- package/dist/databases/all/lenses.spec.js.map +1 -0
- package/dist/databases/all/nomodel.spec.d.ts +1 -0
- package/dist/databases/all/nomodel.spec.js +1070 -0
- package/dist/databases/all/nomodel.spec.js.map +1 -0
- package/dist/databases/all/orderby.spec.d.ts +1 -0
- package/dist/databases/all/orderby.spec.js +170 -0
- package/dist/databases/all/orderby.spec.js.map +1 -0
- package/dist/databases/all/problems.spec.d.ts +1 -0
- package/dist/databases/all/problems.spec.js +106 -0
- package/dist/databases/all/problems.spec.js.map +1 -0
- package/dist/databases/all/sql_expressions.spec.d.ts +1 -0
- package/dist/databases/all/sql_expressions.spec.js +73 -0
- package/dist/databases/all/sql_expressions.spec.js.map +1 -0
- package/dist/databases/all/time.spec.d.ts +1 -0
- package/dist/databases/all/time.spec.js +602 -0
- package/dist/databases/all/time.spec.js.map +1 -0
- package/dist/databases/bigquery/double_truncation.spec.d.ts +1 -0
- package/dist/databases/bigquery/double_truncation.spec.js +50 -0
- package/dist/databases/bigquery/double_truncation.spec.js.map +1 -0
- package/dist/databases/bigquery/handexpr.spec.d.ts +1 -0
- package/dist/databases/bigquery/handexpr.spec.js +723 -0
- package/dist/databases/bigquery/handexpr.spec.js.map +1 -0
- package/dist/databases/bigquery/injestion_time_partitioning.spec.d.ts +1 -0
- package/dist/databases/bigquery/injestion_time_partitioning.spec.js +235 -0
- package/dist/databases/bigquery/injestion_time_partitioning.spec.js.map +1 -0
- package/dist/databases/bigquery/joined_filters.spec.d.ts +1 -0
- package/dist/databases/bigquery/joined_filters.spec.js +72 -0
- package/dist/databases/bigquery/joined_filters.spec.js.map +1 -0
- package/dist/databases/bigquery/json.spec.d.ts +1 -0
- package/dist/databases/bigquery/json.spec.js +66 -0
- package/dist/databases/bigquery/json.spec.js.map +1 -0
- package/dist/databases/bigquery/malloy_query.spec.d.ts +1 -0
- package/dist/databases/bigquery/malloy_query.spec.js +840 -0
- package/dist/databases/bigquery/malloy_query.spec.js.map +1 -0
- package/dist/databases/bigquery/performance.skipped.spec.d.ts +1 -0
- package/dist/databases/bigquery/performance.skipped.spec.js +70 -0
- package/dist/databases/bigquery/performance.skipped.spec.js.map +1 -0
- package/dist/databases/bigquery/time.spec.d.ts +1 -0
- package/dist/databases/bigquery/time.spec.js +52 -0
- package/dist/databases/bigquery/time.spec.js.map +1 -0
- package/dist/databases/bigquery/wildcard_table_names.spec.d.ts +1 -0
- package/dist/databases/bigquery/wildcard_table_names.spec.js +212 -0
- package/dist/databases/bigquery/wildcard_table_names.spec.js.map +1 -0
- package/dist/databases/bigquery-duckdb/nested_source_table.spec.d.ts +1 -0
- package/dist/databases/bigquery-duckdb/nested_source_table.spec.js +213 -0
- package/dist/databases/bigquery-duckdb/nested_source_table.spec.js.map +1 -0
- package/dist/databases/duckdb/duckdb.spec.d.ts +1 -0
- package/dist/databases/duckdb/duckdb.spec.js +124 -0
- package/dist/databases/duckdb/duckdb.spec.js.map +1 -0
- package/dist/databases/duckdb/streaming.spec.d.ts +1 -0
- package/dist/databases/duckdb/streaming.spec.js +142 -0
- package/dist/databases/duckdb/streaming.spec.js.map +1 -0
- package/dist/databases/multi-connection/multi_connection.spec.d.ts +1 -0
- package/dist/databases/multi-connection/multi_connection.spec.js +120 -0
- package/dist/databases/multi-connection/multi_connection.spec.js.map +1 -0
- package/dist/databases/postgres/postgres.spec.d.ts +1 -0
- package/dist/databases/postgres/postgres.spec.js +140 -0
- package/dist/databases/postgres/postgres.spec.js.map +1 -0
- package/dist/databases/shared/test_list.d.ts +3 -0
- package/dist/databases/shared/test_list.js +5 -0
- package/dist/databases/shared/test_list.js.map +1 -0
- package/dist/databases/streaming/streaming.spec.d.ts +1 -0
- package/dist/databases/streaming/streaming.spec.js +93 -0
- package/dist/databases/streaming/streaming.spec.js.map +1 -0
- package/dist/dependencies.spec.d.ts +1 -0
- package/dist/dependencies.spec.js +63 -0
- package/dist/dependencies.spec.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/jestMatcher.spec.d.ts +1 -0
- package/dist/jestMatcher.spec.js +81 -0
- package/dist/jestMatcher.spec.js.map +1 -0
- package/dist/model/sql_source.spec.d.ts +1 -0
- package/dist/model/sql_source.spec.js +47 -0
- package/dist/model/sql_source.spec.js.map +1 -0
- package/dist/models/faa_model.d.ts +5 -0
- package/dist/models/faa_model.js +997 -0
- package/dist/models/faa_model.js.map +1 -0
- package/dist/models/medicare_model.d.ts +4 -0
- package/dist/models/medicare_model.js +259 -0
- package/dist/models/medicare_model.js.map +1 -0
- package/dist/render/drill.spec.d.ts +1 -0
- package/dist/render/drill.spec.js +107 -0
- package/dist/render/drill.spec.js.map +1 -0
- package/dist/render/render.spec.d.ts +1 -0
- package/dist/render/render.spec.js +548 -0
- package/dist/render/render.spec.js.map +1 -0
- package/dist/runtimes.d.ts +35 -0
- package/dist/runtimes.js +180 -0
- package/dist/runtimes.js.map +1 -0
- package/dist/tags.spec.d.ts +8 -0
- package/dist/tags.spec.js +490 -0
- package/dist/tags.spec.js.map +1 -0
- package/dist/util/db-jest-matchers.d.ts +30 -0
- package/dist/util/db-jest-matchers.js +157 -0
- package/dist/util/db-jest-matchers.js.map +1 -0
- package/dist/util/index.d.ts +15 -0
- package/dist/util/index.js +182 -0
- package/dist/util/index.js.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,1070 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
/*
|
|
4
|
+
* Copyright 2023 Google LLC
|
|
5
|
+
*
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
|
7
|
+
* a copy of this software and associated documentation files
|
|
8
|
+
* (the "Software"), to deal in the Software without restriction,
|
|
9
|
+
* including without limitation the rights to use, copy, modify, merge,
|
|
10
|
+
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
11
|
+
* and to permit persons to whom the Software is furnished to do so,
|
|
12
|
+
* subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be
|
|
15
|
+
* included in all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
18
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
19
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
20
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
21
|
+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
22
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
23
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
24
|
+
*/
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
const runtimes_1 = require("../../runtimes");
|
|
28
|
+
const util_1 = require("../../util");
|
|
29
|
+
require("../../util/db-jest-matchers");
|
|
30
|
+
const runtimes = new runtimes_1.RuntimeList((0, util_1.databasesFromEnvironmentOr)(runtimes_1.allDatabases));
|
|
31
|
+
// No prebuilt shared model, each test is complete. Makes debugging easier.
|
|
32
|
+
function rootDbPath(databaseName) {
|
|
33
|
+
return databaseName === 'bigquery' ? 'malloy-data.' : '';
|
|
34
|
+
}
|
|
35
|
+
// TODO: Figure out how to generalize this.
|
|
36
|
+
function getSplitFunction(db) {
|
|
37
|
+
return {
|
|
38
|
+
'bigquery': (column, splitChar) => `split(${column}, '${splitChar}')`,
|
|
39
|
+
'postgres': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
|
|
40
|
+
'duckdb': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
|
|
41
|
+
'duckdb_wasm': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
|
|
42
|
+
'motherduck': (column, splitChar) => `string_to_array(${column}, '${splitChar}')`,
|
|
43
|
+
'snowflake': (column, splitChar) => `split(${column}, '${splitChar}')`,
|
|
44
|
+
}[db];
|
|
45
|
+
}
|
|
46
|
+
afterAll(async () => {
|
|
47
|
+
await runtimes.closeAll();
|
|
48
|
+
});
|
|
49
|
+
runtimes.runtimeMap.forEach((runtime, databaseName) => {
|
|
50
|
+
const q = runtime.getQuoter();
|
|
51
|
+
// Issue: #1284
|
|
52
|
+
it(`parenthesize output field values - ${databaseName}`, async () => {
|
|
53
|
+
await expect(`
|
|
54
|
+
run: ${databaseName}.table('malloytest.aircraft') -> {
|
|
55
|
+
group_by: r is 1
|
|
56
|
+
|
|
57
|
+
calculate:
|
|
58
|
+
zero is 1 - rank()
|
|
59
|
+
zero_bare is 0 - zero
|
|
60
|
+
zero_paren is 0 - (zero)
|
|
61
|
+
}
|
|
62
|
+
`).malloyResultMatches(runtime, { zero_bare: 0, zero_paren: 0 });
|
|
63
|
+
});
|
|
64
|
+
// Issue: #151
|
|
65
|
+
it(`bug 151 which used to throw unknown dialect is still fixed- ${databaseName}`, async () => {
|
|
66
|
+
await expect(`
|
|
67
|
+
query: q is ${databaseName}.table('malloytest.aircraft')->{
|
|
68
|
+
where: state != null
|
|
69
|
+
group_by: state
|
|
70
|
+
}
|
|
71
|
+
run: q extend {
|
|
72
|
+
view: foo is {
|
|
73
|
+
order_by: 1 desc
|
|
74
|
+
group_by: state
|
|
75
|
+
}
|
|
76
|
+
} -> foo
|
|
77
|
+
`).malloyResultMatches(runtime, { state: 'WY' });
|
|
78
|
+
});
|
|
79
|
+
// Issue #149
|
|
80
|
+
it(`refine query from query - ${databaseName}`, async () => {
|
|
81
|
+
await expect(`
|
|
82
|
+
run: ${databaseName}.table('malloytest.state_facts')
|
|
83
|
+
-> {group_by: state; order_by: 1 desc; limit: 1}
|
|
84
|
+
extend {
|
|
85
|
+
dimension: lower_state is lower(state)
|
|
86
|
+
} -> {select: lower_state}
|
|
87
|
+
`).malloyResultMatches(runtime, { lower_state: 'wy' });
|
|
88
|
+
});
|
|
89
|
+
// issue #157
|
|
90
|
+
it(`source- not -found - ${databaseName}`, async () => {
|
|
91
|
+
// console.log(result.data.toObject());
|
|
92
|
+
let error;
|
|
93
|
+
try {
|
|
94
|
+
await runtime
|
|
95
|
+
.loadQuery(`
|
|
96
|
+
source: foo is ${databaseName}.table('malloytest.state_facts') extend {primary_key: state}
|
|
97
|
+
run: foox->{aggregate: c is count()}
|
|
98
|
+
`)
|
|
99
|
+
.run();
|
|
100
|
+
}
|
|
101
|
+
catch (e) {
|
|
102
|
+
error = e;
|
|
103
|
+
}
|
|
104
|
+
expect(error.toString()).not.toContain('Unknown Dialect');
|
|
105
|
+
});
|
|
106
|
+
it(`join_many - ${databaseName}`, async () => {
|
|
107
|
+
await expect(`
|
|
108
|
+
source: m is ${databaseName}.table('malloytest.aircraft_models') extend {
|
|
109
|
+
join_many:
|
|
110
|
+
a is ${databaseName}.table('malloytest.aircraft') extend {
|
|
111
|
+
measure: avg_year is floor(avg(year_built))
|
|
112
|
+
} on a.aircraft_model_code=aircraft_model_code
|
|
113
|
+
measure: avg_seats is floor(avg(seats))
|
|
114
|
+
}
|
|
115
|
+
run: m->{aggregate: avg_seats, a.avg_year}
|
|
116
|
+
`).malloyResultMatches(runtime, { avg_year: 1969, avg_seats: 7 });
|
|
117
|
+
});
|
|
118
|
+
it(`join_many condition no primary key - ${databaseName}`, async () => {
|
|
119
|
+
await expect(`
|
|
120
|
+
source: a is ${databaseName}.table('malloytest.airports')
|
|
121
|
+
source: b is ${databaseName}.table('malloytest.state_facts') extend {
|
|
122
|
+
join_many: a on state=a.state
|
|
123
|
+
}
|
|
124
|
+
run: b->{aggregate: c is airport_count.sum()}
|
|
125
|
+
`).malloyResultMatches(runtime, { c: 19701 });
|
|
126
|
+
});
|
|
127
|
+
it(`join_many filter multiple values - ${databaseName}`, async () => {
|
|
128
|
+
await expect(`
|
|
129
|
+
source: a is ${databaseName}.table('malloytest.airports') extend {
|
|
130
|
+
where: state = 'NH' | 'CA'
|
|
131
|
+
}
|
|
132
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
133
|
+
join_many: a on state=a.state
|
|
134
|
+
} -> {
|
|
135
|
+
aggregate: c is airport_count.sum()
|
|
136
|
+
group_by: a.state
|
|
137
|
+
}
|
|
138
|
+
`).malloyResultMatches(runtime, [
|
|
139
|
+
{ state: null, c: 18605 },
|
|
140
|
+
{ state: 'CA', c: 984 },
|
|
141
|
+
{ state: 'NH', c: 112 },
|
|
142
|
+
]);
|
|
143
|
+
});
|
|
144
|
+
it(`join_one condition no primary key - ${databaseName}`, async () => {
|
|
145
|
+
await expect(`
|
|
146
|
+
source: a is ${databaseName}.table('malloytest.state_facts')
|
|
147
|
+
source: b is ${databaseName}.table('malloytest.airports') extend {
|
|
148
|
+
join_one: a on state=a.state
|
|
149
|
+
}
|
|
150
|
+
run: b -> {
|
|
151
|
+
aggregate: c is a.airport_count.sum()
|
|
152
|
+
}
|
|
153
|
+
`).malloyResultMatches(runtime, { c: 19701 });
|
|
154
|
+
});
|
|
155
|
+
it(`join_one filter multiple values - ${databaseName}`, async () => {
|
|
156
|
+
await expect(`
|
|
157
|
+
source: a is ${databaseName}.table('malloytest.state_facts') extend {
|
|
158
|
+
where: state = 'TX' | 'LA'
|
|
159
|
+
}
|
|
160
|
+
source: b is ${databaseName}.table('malloytest.airports') extend {
|
|
161
|
+
join_one: a on state=a.state
|
|
162
|
+
}
|
|
163
|
+
run: b-> {
|
|
164
|
+
aggregate: c is a.airport_count.sum()
|
|
165
|
+
group_by: a.state
|
|
166
|
+
}
|
|
167
|
+
`).malloyResultMatches(runtime, [
|
|
168
|
+
{ state: 'TX', c: 1845 },
|
|
169
|
+
{ state: 'LA', c: 500 },
|
|
170
|
+
{ state: null, c: 0 },
|
|
171
|
+
]);
|
|
172
|
+
});
|
|
173
|
+
it(`join_many cross from - ${databaseName}`, async () => {
|
|
174
|
+
// a cross join produces a Many to Many result.
|
|
175
|
+
// symmetric aggregate are needed on both sides of the join
|
|
176
|
+
// Check the row count and that sums on each side work properly.
|
|
177
|
+
await expect(`
|
|
178
|
+
source: a is ${databaseName}.table('malloytest.state_facts')
|
|
179
|
+
source: f is a extend {
|
|
180
|
+
join_cross: a
|
|
181
|
+
}
|
|
182
|
+
run: f->{
|
|
183
|
+
aggregate:
|
|
184
|
+
row_count is count(concat(state,a.state))
|
|
185
|
+
left_count is count()
|
|
186
|
+
right_count is a.count()
|
|
187
|
+
left_sum is airport_count.sum()
|
|
188
|
+
right_sum is a.airport_count.sum()
|
|
189
|
+
}
|
|
190
|
+
`).malloyResultMatches(runtime, {
|
|
191
|
+
row_count: 51 * 51,
|
|
192
|
+
left_sum: 19701,
|
|
193
|
+
right_sum: 19701,
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
it(`join_one only - ${databaseName}`, async () => {
|
|
197
|
+
// a cross join produces a Many to Many result.
|
|
198
|
+
// symmetric aggregate are needed on both sides of the join
|
|
199
|
+
// Check the row count and that sums on each side work properly.
|
|
200
|
+
await expect(`
|
|
201
|
+
query: q is ${databaseName}.table('malloytest.state_facts')->{
|
|
202
|
+
aggregate: r is airport_count.sum()
|
|
203
|
+
}
|
|
204
|
+
source: f is ${databaseName}.table('malloytest.state_facts') extend {
|
|
205
|
+
join_one: a is q
|
|
206
|
+
}
|
|
207
|
+
run: f->{
|
|
208
|
+
aggregate:
|
|
209
|
+
row_count is count(concat(state,a.r))
|
|
210
|
+
left_sum is airport_count.sum()
|
|
211
|
+
right_sum is a.r.sum()
|
|
212
|
+
sum_sum is sum(airport_count + a.r)
|
|
213
|
+
}
|
|
214
|
+
`).malloyResultMatches(runtime, {
|
|
215
|
+
row_count: 51,
|
|
216
|
+
left_sum: 19701,
|
|
217
|
+
right_sum: 19701,
|
|
218
|
+
sum_sum: 19701 + 51 * 19701,
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
it(`join_many cross ON - ${databaseName}`, async () => {
|
|
222
|
+
// a cross join produces a Many to Many result.
|
|
223
|
+
// symmetric aggregate are needed on both sides of the join
|
|
224
|
+
// Check the row count and that sums on each side work properly.
|
|
225
|
+
await expect(`
|
|
226
|
+
source: a is ${databaseName}.table('malloytest.state_facts')
|
|
227
|
+
source: f is a extend {
|
|
228
|
+
join_cross: a on a.state = 'CA' | 'NY'
|
|
229
|
+
}
|
|
230
|
+
run: f->{
|
|
231
|
+
aggregate:
|
|
232
|
+
row_count is count(concat(state,a.state))
|
|
233
|
+
left_sum is airport_count.sum()
|
|
234
|
+
right_sum is a.airport_count.sum()
|
|
235
|
+
}
|
|
236
|
+
`).malloyResultMatches(runtime, {
|
|
237
|
+
row_count: 51 * 2,
|
|
238
|
+
left_sum: 19701,
|
|
239
|
+
right_sum: 1560,
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
it(`limit - provided - ${databaseName}`, async () => {
|
|
243
|
+
// a cross join produces a Many to Many result.
|
|
244
|
+
// symmetric aggregate are needed on both sides of the join
|
|
245
|
+
// Check the row count and that sums on each side work properly.
|
|
246
|
+
const result = await runtime
|
|
247
|
+
.loadQuery(`
|
|
248
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
249
|
+
group_by: state
|
|
250
|
+
aggregate: c is count()
|
|
251
|
+
limit: 3
|
|
252
|
+
}
|
|
253
|
+
`)
|
|
254
|
+
.run();
|
|
255
|
+
expect(result.resultExplore.limit).toBe(3);
|
|
256
|
+
});
|
|
257
|
+
const matrixModel = `
|
|
258
|
+
##! experimental.join_types
|
|
259
|
+
source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
|
|
260
|
+
select: *
|
|
261
|
+
where: state ~ r'^(A|M)'
|
|
262
|
+
} extend {
|
|
263
|
+
measure:
|
|
264
|
+
am_count is count()
|
|
265
|
+
am_sum is airport_count.sum()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
query: ac_states_base is ${databaseName}.table('malloytest.state_facts') -> {
|
|
269
|
+
select: *
|
|
270
|
+
where: state ~ r'^(A|C)'
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// mulitply the number of rows in ac_states so we have a many to one join
|
|
274
|
+
source: ac_states is ac_states_base -> {
|
|
275
|
+
extend: {
|
|
276
|
+
join_cross: b is ac_states_base
|
|
277
|
+
}
|
|
278
|
+
select:
|
|
279
|
+
b.state
|
|
280
|
+
b.airport_count
|
|
281
|
+
} extend {
|
|
282
|
+
measure:
|
|
283
|
+
ac_count is count()
|
|
284
|
+
ac_sum is airport_count.sum()
|
|
285
|
+
}
|
|
286
|
+
`;
|
|
287
|
+
it(`join inner- ${databaseName}`, async () => {
|
|
288
|
+
// a cross join produces a Many to Many result.
|
|
289
|
+
// symmetric aggregate are needed on both sides of the join
|
|
290
|
+
// Check the row count and that sums on each side work properly.
|
|
291
|
+
await expect(`
|
|
292
|
+
${matrixModel}
|
|
293
|
+
run: ac_states -> {
|
|
294
|
+
extend: {
|
|
295
|
+
join_one: am_states inner on state = am_states.state
|
|
296
|
+
}
|
|
297
|
+
aggregate:
|
|
298
|
+
ac_count
|
|
299
|
+
ac_sum
|
|
300
|
+
am_states.am_sum
|
|
301
|
+
am_states.am_count
|
|
302
|
+
|
|
303
|
+
}
|
|
304
|
+
`).malloyResultMatches(runtime, {
|
|
305
|
+
ac_count: 28,
|
|
306
|
+
ac_sum: 10402,
|
|
307
|
+
am_count: 4,
|
|
308
|
+
am_sum: 1486,
|
|
309
|
+
//show_sql_fail: 1,
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
it(`join left - ${databaseName}`, async () => {
|
|
313
|
+
// a cross join produces a Many to Many result.
|
|
314
|
+
// symmetric aggregate are needed on both sides of the join
|
|
315
|
+
// Check the row count and that sums on each side work properly.
|
|
316
|
+
await expect(`
|
|
317
|
+
${matrixModel}
|
|
318
|
+
run: ac_states -> {
|
|
319
|
+
extend: {
|
|
320
|
+
join_one: am_states left on state = am_states.state
|
|
321
|
+
}
|
|
322
|
+
aggregate:
|
|
323
|
+
ac_count
|
|
324
|
+
ac_sum
|
|
325
|
+
am_states.am_sum
|
|
326
|
+
am_states.am_count
|
|
327
|
+
|
|
328
|
+
}
|
|
329
|
+
`).malloyResultMatches(runtime, {
|
|
330
|
+
ac_count: 49,
|
|
331
|
+
ac_sum: 21336,
|
|
332
|
+
am_count: 4,
|
|
333
|
+
am_sum: 1486,
|
|
334
|
+
//show_sql_fail: 1,
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
it(`join right - ${databaseName}`, async () => {
|
|
338
|
+
// a cross join produces a Many to Many result.
|
|
339
|
+
// symmetric aggregate are needed on both sides of the join
|
|
340
|
+
// Check the row count and that sums on each side work properly.
|
|
341
|
+
await expect(`
|
|
342
|
+
${matrixModel}
|
|
343
|
+
run: ac_states -> {
|
|
344
|
+
extend: {
|
|
345
|
+
join_one: am_states right on state = am_states.state
|
|
346
|
+
}
|
|
347
|
+
aggregate:
|
|
348
|
+
ac_count
|
|
349
|
+
ac_sum
|
|
350
|
+
am_states.am_sum
|
|
351
|
+
am_states.am_count
|
|
352
|
+
|
|
353
|
+
}
|
|
354
|
+
`).malloyResultMatches(runtime, {
|
|
355
|
+
ac_count: 28,
|
|
356
|
+
ac_sum: 10402,
|
|
357
|
+
am_count: 12,
|
|
358
|
+
am_sum: 4139,
|
|
359
|
+
//show_sql_fail: 1,
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
it(`join full - ${databaseName}`, async () => {
|
|
363
|
+
// a cross join produces a Many to Many result.
|
|
364
|
+
// symmetric aggregate are needed on both sides of the join
|
|
365
|
+
// Check the row count and that sums on each side work properly.
|
|
366
|
+
await expect(`
|
|
367
|
+
${matrixModel}
|
|
368
|
+
run: ac_states -> {
|
|
369
|
+
extend: {
|
|
370
|
+
join_one: am_states full on state = am_states.state
|
|
371
|
+
}
|
|
372
|
+
aggregate:
|
|
373
|
+
ac_count
|
|
374
|
+
ac_sum
|
|
375
|
+
am_states.am_sum
|
|
376
|
+
am_states.am_count
|
|
377
|
+
|
|
378
|
+
}
|
|
379
|
+
`).malloyResultMatches(runtime, {
|
|
380
|
+
ac_count: 49,
|
|
381
|
+
ac_sum: 21336,
|
|
382
|
+
am_count: 12,
|
|
383
|
+
am_sum: 4139,
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
it(`leafy count - ${databaseName}`, async () => {
|
|
387
|
+
// in a joined table when the joined is leafiest
|
|
388
|
+
// we need to make sure we don't count rows that
|
|
389
|
+
// don't match the join.
|
|
390
|
+
await expect(`
|
|
391
|
+
source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
|
|
392
|
+
select: *
|
|
393
|
+
where: state ~ r'^(A|M)'
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
source: states is ${databaseName}.table('malloytest.state_facts') extend {
|
|
397
|
+
join_many: am_states on state=am_states.state
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
run: states -> {
|
|
401
|
+
where: state = 'CA'
|
|
402
|
+
aggregate:
|
|
403
|
+
leafy_count is am_states.count()
|
|
404
|
+
root_count is count()
|
|
405
|
+
}
|
|
406
|
+
`).malloyResultMatches(runtime, {
|
|
407
|
+
leafy_count: 0,
|
|
408
|
+
root_count: 1,
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
it(`nest/unnest -basic - ${databaseName}`, async () => {
|
|
412
|
+
// in a joined table when the joined is leafiest
|
|
413
|
+
// we need to make sure we don't count rows that
|
|
414
|
+
// don't match the join.
|
|
415
|
+
await expect(`
|
|
416
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
417
|
+
group_by: state
|
|
418
|
+
aggregate: c is airport_count.sum()
|
|
419
|
+
nest: p is {
|
|
420
|
+
group_by: popular_name
|
|
421
|
+
aggregate: d is airport_count.sum()
|
|
422
|
+
}
|
|
423
|
+
} -> {
|
|
424
|
+
group_by: state, c
|
|
425
|
+
aggregate: p.d.sum()
|
|
426
|
+
}
|
|
427
|
+
`).malloyResultMatches(runtime, {
|
|
428
|
+
state: 'TX',
|
|
429
|
+
c: 1845,
|
|
430
|
+
d: 1845,
|
|
431
|
+
});
|
|
432
|
+
});
|
|
433
|
+
it(`count at root should not use distinct key - ${databaseName}`, async () => {
|
|
434
|
+
const q = await runtime
|
|
435
|
+
.loadQuery(`
|
|
436
|
+
source: states is ${databaseName}.table('malloytest.state_facts')
|
|
437
|
+
|
|
438
|
+
run: states -> { aggregate: c is count() }
|
|
439
|
+
`)
|
|
440
|
+
.run();
|
|
441
|
+
expect(q.sql.toLowerCase()).not.toContain('distinct');
|
|
442
|
+
});
|
|
443
|
+
it(`leafy nested count - ${databaseName}`, async () => {
|
|
444
|
+
// in a joined table when the joined is leafiest
|
|
445
|
+
// we need to make sure we don't count rows that
|
|
446
|
+
// don't match the join.
|
|
447
|
+
await expect(`
|
|
448
|
+
source: am_states is ${databaseName}.table('malloytest.state_facts') -> {
|
|
449
|
+
group_by: state,popular_name
|
|
450
|
+
where: state ~ r'^(A|M)'
|
|
451
|
+
nest: nested_state is {
|
|
452
|
+
group_by: state,popular_name
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
source: states is ${databaseName}.table('malloytest.state_facts') extend {
|
|
457
|
+
join_many: am_states on state=am_states.state
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
run: states -> {
|
|
461
|
+
where: state = 'CA'
|
|
462
|
+
group_by:
|
|
463
|
+
state
|
|
464
|
+
am_state is am_states.state
|
|
465
|
+
aggregate:
|
|
466
|
+
leafy_count is am_states.nested_state.count()
|
|
467
|
+
root_count is count()
|
|
468
|
+
}
|
|
469
|
+
`).malloyResultMatches(runtime, {
|
|
470
|
+
leafy_count: 0,
|
|
471
|
+
root_count: 1,
|
|
472
|
+
state: 'CA',
|
|
473
|
+
am_state: null,
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
it(`basic index - ${databaseName}`, async () => {
|
|
477
|
+
// Make sure basic indexing works.
|
|
478
|
+
await expect(`
|
|
479
|
+
run: ${databaseName}.table('malloytest.flights') -> {
|
|
480
|
+
index: *
|
|
481
|
+
}
|
|
482
|
+
-> {
|
|
483
|
+
select: *
|
|
484
|
+
order_by: fieldValue
|
|
485
|
+
where: fieldName = 'carrier'
|
|
486
|
+
}
|
|
487
|
+
`).malloyResultMatches(runtime, {
|
|
488
|
+
fieldValue: 'AA',
|
|
489
|
+
});
|
|
490
|
+
});
|
|
491
|
+
test(`number as null 2 - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
492
|
+
// a cross join produces a Many to Many result.
|
|
493
|
+
// symmetric aggregate are needed on both sides of the join
|
|
494
|
+
// Check the row count and that sums on each side work properly.
|
|
495
|
+
await expect(`
|
|
496
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
497
|
+
group_by: state
|
|
498
|
+
nest: ugly is {
|
|
499
|
+
group_by: popular_name
|
|
500
|
+
aggregate: foo is NULLIF(sum(airport_count)*0,0)+1
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
`).malloyResultMatches(runtime, { 'ugly.foo': null });
|
|
504
|
+
}));
|
|
505
|
+
// average should only include non-null values in the denominator
|
|
506
|
+
it(`avg ignore null- ${databaseName}`, async () => {
|
|
507
|
+
await expect(`
|
|
508
|
+
source: one is ${databaseName}.sql("""
|
|
509
|
+
SELECT 2 as ${q `a`}
|
|
510
|
+
UNION ALL SELECT 4
|
|
511
|
+
UNION ALL SELECT null
|
|
512
|
+
""")
|
|
513
|
+
run: one -> {
|
|
514
|
+
extend: { join_cross: x1 is one }
|
|
515
|
+
aggregate:
|
|
516
|
+
avg_a is a.avg()
|
|
517
|
+
avg_b is x1.a.avg()
|
|
518
|
+
}`).malloyResultMatches(runtime, { avg_a: 3 });
|
|
519
|
+
});
|
|
520
|
+
it(`limit - not provided - ${databaseName}`, async () => {
|
|
521
|
+
// a cross join produces a Many to Many result.
|
|
522
|
+
// symmetric aggregate are needed on both sides of the join
|
|
523
|
+
// Check the row count and that sums on each side work properly.
|
|
524
|
+
const result = await runtime
|
|
525
|
+
.loadQuery(`run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
526
|
+
group_by: state
|
|
527
|
+
aggregate: c is count()
|
|
528
|
+
}`)
|
|
529
|
+
.run();
|
|
530
|
+
expect(result.resultExplore.limit).toBe(undefined);
|
|
531
|
+
});
|
|
532
|
+
it(`ungrouped top level - ${databaseName}`, async () => {
|
|
533
|
+
await expect(`
|
|
534
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
535
|
+
measure: total_births is births.sum()
|
|
536
|
+
measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
|
|
537
|
+
} -> {
|
|
538
|
+
group_by: state
|
|
539
|
+
aggregate: births_per_100k
|
|
540
|
+
}`).malloyResultMatches(runtime, { births_per_100k: 9742 });
|
|
541
|
+
});
|
|
542
|
+
test(`ungrouped top level with nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
543
|
+
await expect(`
|
|
544
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
545
|
+
measure: total_births is births.sum()
|
|
546
|
+
measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
|
|
547
|
+
} -> {
|
|
548
|
+
group_by: state
|
|
549
|
+
aggregate: births_per_100k
|
|
550
|
+
nest: by_name is {
|
|
551
|
+
group_by: popular_name
|
|
552
|
+
aggregate: total_births
|
|
553
|
+
}
|
|
554
|
+
limit: 1000
|
|
555
|
+
}`).malloyResultMatches(runtime, { births_per_100k: 9742 });
|
|
556
|
+
}));
|
|
557
|
+
it(`ungrouped - eliminate rows - ${databaseName}`, async () => {
|
|
558
|
+
await expect(`
|
|
559
|
+
run : ${databaseName}.table('malloytest.state_facts') extend {
|
|
560
|
+
measure: m is all(births.sum())
|
|
561
|
+
where: state='CA' | 'NY'
|
|
562
|
+
} -> {
|
|
563
|
+
order_by: state
|
|
564
|
+
group_by: state
|
|
565
|
+
aggregate: m
|
|
566
|
+
}`).malloyResultMatches(runtime, [
|
|
567
|
+
{ state: 'CA', m: 52504699 },
|
|
568
|
+
{ state: 'NY', m: 52504699 },
|
|
569
|
+
]);
|
|
570
|
+
});
|
|
571
|
+
test(`ungrouped nested with no grouping above - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
572
|
+
await expect(`
|
|
573
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
574
|
+
measure: total_births is births.sum()
|
|
575
|
+
measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
|
|
576
|
+
} -> {
|
|
577
|
+
aggregate: total_births
|
|
578
|
+
nest: by_name is {
|
|
579
|
+
group_by: popular_name
|
|
580
|
+
aggregate: births_per_100k
|
|
581
|
+
}
|
|
582
|
+
}`).malloyResultMatches(runtime, { 'by_name.births_per_100k': 66703 });
|
|
583
|
+
}));
|
|
584
|
+
test(`ungrouped - partial grouping - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
585
|
+
await expect(`
|
|
586
|
+
run: ${databaseName}.table('malloytest.airports') extend {
|
|
587
|
+
measure: c is count()
|
|
588
|
+
} -> {
|
|
589
|
+
where: state = 'TX' | 'NY'
|
|
590
|
+
group_by:
|
|
591
|
+
faa_region
|
|
592
|
+
state
|
|
593
|
+
aggregate:
|
|
594
|
+
c
|
|
595
|
+
all_ is all(c)
|
|
596
|
+
airport_count is c { where: fac_type = 'AIRPORT'}
|
|
597
|
+
nest: fac_type is {
|
|
598
|
+
group_by: fac_type
|
|
599
|
+
aggregate:
|
|
600
|
+
c
|
|
601
|
+
all_ is all(c)
|
|
602
|
+
all_state_region is exclude(c,fac_type)
|
|
603
|
+
all_of_this_type is exclude(c, state, faa_region)
|
|
604
|
+
all_top is exclude(c, state, faa_region, fac_type)
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
`).malloyResultMatches(runtime, {
|
|
608
|
+
'fac_type.all_': 1845,
|
|
609
|
+
'fac_type.all_state_region': 1845,
|
|
610
|
+
'fac_type.all_of_this_type': 1782,
|
|
611
|
+
'fac_type.all_top': 2421,
|
|
612
|
+
});
|
|
613
|
+
}));
|
|
614
|
+
test(`ungrouped - all nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
615
|
+
await expect(`
|
|
616
|
+
run: ${databaseName}.table('malloytest.airports') extend {
|
|
617
|
+
measure: c is count()
|
|
618
|
+
} -> {
|
|
619
|
+
where: state = 'TX' | 'NY'
|
|
620
|
+
group_by:
|
|
621
|
+
state
|
|
622
|
+
aggregate:
|
|
623
|
+
c
|
|
624
|
+
all_ is all(c)
|
|
625
|
+
airport_count is c { where: fac_type = 'AIRPORT'}
|
|
626
|
+
nest: fac_type is {
|
|
627
|
+
group_by: fac_type, major
|
|
628
|
+
aggregate:
|
|
629
|
+
c
|
|
630
|
+
all_ is all(c)
|
|
631
|
+
all_major is all(c,major)
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
`).malloyResultMatches(runtime, {
|
|
635
|
+
'fac_type.all_': 1845,
|
|
636
|
+
'fac_type.all_major': 1819,
|
|
637
|
+
});
|
|
638
|
+
}));
|
|
639
|
+
test(`ungrouped nested - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
640
|
+
await expect(`
|
|
641
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
642
|
+
measure: total_births is births.sum()
|
|
643
|
+
measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
|
|
644
|
+
} -> {
|
|
645
|
+
group_by: popular_name
|
|
646
|
+
nest: by_state is {
|
|
647
|
+
group_by: state
|
|
648
|
+
aggregate: births_per_100k
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
`).malloyResultMatches(runtime, { 'by_state.births_per_100k': 36593 });
|
|
652
|
+
}));
|
|
653
|
+
test(`ungrouped nested expression - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
654
|
+
await expect(`
|
|
655
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
656
|
+
measure: total_births is births.sum()
|
|
657
|
+
measure: births_per_100k is floor(total_births/ all(total_births) * 100000)
|
|
658
|
+
} -> {
|
|
659
|
+
group_by: upper_name is upper(popular_name)
|
|
660
|
+
nest: by_state is {
|
|
661
|
+
group_by: state
|
|
662
|
+
aggregate: births_per_100k
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
`).malloyResultMatches(runtime, { 'by_state.births_per_100k': 36593 });
|
|
666
|
+
}));
|
|
667
|
+
test(`ungrouped nested group by float - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
668
|
+
await expect(`
|
|
669
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
670
|
+
measure: total_births is births.sum()
|
|
671
|
+
measure: ug is all(total_births)
|
|
672
|
+
} -> {
|
|
673
|
+
group_by: f is floor(airport_count/300.0)
|
|
674
|
+
nest: by_state is {
|
|
675
|
+
group_by: state
|
|
676
|
+
aggregate: ug
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
`).malloyResultMatches(runtime, { 'by_state.ug': 62742230 });
|
|
680
|
+
}));
|
|
681
|
+
it(`run simple sql - ${databaseName}`, async () => {
|
|
682
|
+
const result = await runtime
|
|
683
|
+
.loadQuery(`run: conn.sql('select 1 as ${q `one`}')`)
|
|
684
|
+
.run();
|
|
685
|
+
expect(result.data.value[0]['one']).toBe(1);
|
|
686
|
+
});
|
|
687
|
+
it(`simple sql is exactly as written - ${databaseName}`, async () => {
|
|
688
|
+
const result = await runtime
|
|
689
|
+
.loadQuery(`run: conn.sql('select 1 as ${q `one`}')`)
|
|
690
|
+
.run();
|
|
691
|
+
if (databaseName === 'postgres') {
|
|
692
|
+
expect(result.sql).toBe(`WITH __stage0 AS (
|
|
693
|
+
select 1 as ${q `one`})
|
|
694
|
+
SELECT row_to_json(finalStage) as row FROM __stage0 AS finalStage`);
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
expect(result.sql).toBe(`select 1 as ${q `one`}`);
|
|
698
|
+
}
|
|
699
|
+
expect(result.resultExplore).not.toBeUndefined();
|
|
700
|
+
});
|
|
701
|
+
it(`source from query defined as sql query - ${databaseName}`, async () => {
|
|
702
|
+
const result = await runtime
|
|
703
|
+
.loadQuery(`
|
|
704
|
+
query: q is conn.sql('select 1 as ${q `one`}')
|
|
705
|
+
source: s is q
|
|
706
|
+
run: s -> { select: * }
|
|
707
|
+
`)
|
|
708
|
+
.run();
|
|
709
|
+
expect(result.data.path(0, 'one').number.value).toBe(1);
|
|
710
|
+
});
|
|
711
|
+
it(`source from query defined as other query - ${databaseName}`, async () => {
|
|
712
|
+
const result = await runtime
|
|
713
|
+
.loadQuery(`
|
|
714
|
+
query: q is conn.table('malloytest.flights') -> { group_by: carrier }
|
|
715
|
+
source: s is q
|
|
716
|
+
run: s -> { select: *; order_by: carrier }
|
|
717
|
+
`)
|
|
718
|
+
.run();
|
|
719
|
+
expect(result.data.path(0, 'carrier').string.value).toBe('AA');
|
|
720
|
+
});
|
|
721
|
+
it(`all with parameters - basic - ${databaseName}`, async () => {
|
|
722
|
+
await expect(`
|
|
723
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
724
|
+
measure: total_births is births.sum()
|
|
725
|
+
} -> {
|
|
726
|
+
group_by: popular_name, state
|
|
727
|
+
aggregate:
|
|
728
|
+
total_births
|
|
729
|
+
all_births is all(total_births)
|
|
730
|
+
all_name is exclude(total_births, state)
|
|
731
|
+
}
|
|
732
|
+
`).malloyResultMatches(runtime, {
|
|
733
|
+
all_births: 295727065,
|
|
734
|
+
all_name: 197260594,
|
|
735
|
+
});
|
|
736
|
+
});
|
|
737
|
+
test(`all with parameters - nest - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
738
|
+
await expect(`
|
|
739
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
740
|
+
measure: total_births is births.sum()
|
|
741
|
+
dimension: abc is floor(airport_count/300)
|
|
742
|
+
} -> {
|
|
743
|
+
group_by: abc
|
|
744
|
+
aggregate: total_births
|
|
745
|
+
nest: by_stuff is {
|
|
746
|
+
group_by: popular_name, state
|
|
747
|
+
aggregate:
|
|
748
|
+
total_births
|
|
749
|
+
all_births is all(total_births)
|
|
750
|
+
all_name is exclude(total_births, state)
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
`).malloyResultMatches(runtime, {
|
|
754
|
+
'by_stuff.all_births': 119809719,
|
|
755
|
+
'by_stuff.all_name': 61091215,
|
|
756
|
+
});
|
|
757
|
+
}));
|
|
758
|
+
test(`single value to udf - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
|
|
759
|
+
await expect(`
|
|
760
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
761
|
+
view: fun is {
|
|
762
|
+
aggregate: t is count()
|
|
763
|
+
} -> { select: t1 is t+1 }
|
|
764
|
+
} -> { nest: fun }
|
|
765
|
+
`).malloyResultMatches(runtime, { 'fun.t1': 52 });
|
|
766
|
+
}));
|
|
767
|
+
test(`Multi value to udf - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
|
|
768
|
+
await expect(`
|
|
769
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
770
|
+
view: fun is {
|
|
771
|
+
group_by: one is 1
|
|
772
|
+
aggregate: t is count()
|
|
773
|
+
} -> { select: t1 is t+1 }
|
|
774
|
+
} -> {
|
|
775
|
+
nest: fun
|
|
776
|
+
}
|
|
777
|
+
`).malloyResultMatches(runtime, { 'fun.t1': 52 });
|
|
778
|
+
}));
|
|
779
|
+
test(`Multi value to udf group by - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsPipelinesInViews, async () => {
|
|
780
|
+
await expect(`
|
|
781
|
+
run: ${databaseName}.table('malloytest.state_facts') extend {
|
|
782
|
+
view: fun is {
|
|
783
|
+
group_by: one is 1
|
|
784
|
+
aggregate: t is count()
|
|
785
|
+
} -> { group_by: t1 is t+1 }
|
|
786
|
+
} -> {
|
|
787
|
+
nest: fun
|
|
788
|
+
}
|
|
789
|
+
`).malloyResultMatches(runtime, { 'fun.t1': 52 });
|
|
790
|
+
}));
|
|
791
|
+
const sql1234 = `${databaseName}.sql('SELECT 1 as ${q `a`}, 2 as ${q `b`} UNION ALL SELECT 3, 4')`;
|
|
792
|
+
it(`sql as source - ${databaseName}`, async () => {
|
|
793
|
+
await expect(`
|
|
794
|
+
run: ${sql1234} -> { select: a }
|
|
795
|
+
`).malloyResultMatches(runtime, { a: 1 });
|
|
796
|
+
});
|
|
797
|
+
it(`sql directly - ${databaseName}`, async () => {
|
|
798
|
+
await expect(`run: ${sql1234}`).malloyResultMatches(runtime, { a: 1 });
|
|
799
|
+
});
|
|
800
|
+
it(`sql with turducken- ${databaseName}`, async () => {
|
|
801
|
+
const turduckenQuery = `
|
|
802
|
+
run: ${databaseName}.sql("""
|
|
803
|
+
SELECT
|
|
804
|
+
'something' as SOMETHING,
|
|
805
|
+
*
|
|
806
|
+
FROM %{
|
|
807
|
+
${databaseName}.table('malloytest.state_facts') -> {
|
|
808
|
+
group_by: popular_name
|
|
809
|
+
aggregate: state_count is count()
|
|
810
|
+
}
|
|
811
|
+
} AS by_name_query
|
|
812
|
+
""") -> {
|
|
813
|
+
select: *; where: popular_name = 'Emma'
|
|
814
|
+
}`;
|
|
815
|
+
await expect(turduckenQuery).malloyResultMatches(runtime, { state_count: 6 });
|
|
816
|
+
});
|
|
817
|
+
// local declarations
|
|
818
|
+
it(`local declarations external query - ${databaseName}`, async () => {
|
|
819
|
+
await expect(`
|
|
820
|
+
run: ${sql1234} -> {
|
|
821
|
+
extend: { dimension: c is a + 1 }
|
|
822
|
+
select: c
|
|
823
|
+
}
|
|
824
|
+
`).malloyResultMatches(runtime, { c: 2 });
|
|
825
|
+
});
|
|
826
|
+
it(`local declarations named query - ${databaseName}`, async () => {
|
|
827
|
+
await expect(`
|
|
828
|
+
run: ${sql1234} extend {
|
|
829
|
+
view: bar is {
|
|
830
|
+
extend: { dimension: c is a + 1 }
|
|
831
|
+
select: c
|
|
832
|
+
}
|
|
833
|
+
} -> bar
|
|
834
|
+
`).malloyResultMatches(runtime, { c: 2 });
|
|
835
|
+
});
|
|
836
|
+
it(`local declarations refined named query - ${databaseName}`, async () => {
|
|
837
|
+
await expect(`
|
|
838
|
+
run: ${sql1234} extend {
|
|
839
|
+
view: bar is {
|
|
840
|
+
extend: {dimension: c is a + 1}
|
|
841
|
+
select: c
|
|
842
|
+
}
|
|
843
|
+
view: baz is bar + {
|
|
844
|
+
extend: {dimension: d is c + 1}
|
|
845
|
+
select: d
|
|
846
|
+
}
|
|
847
|
+
} -> baz
|
|
848
|
+
`).malloyResultMatches(runtime, { d: 3 });
|
|
849
|
+
});
|
|
850
|
+
it(`regexp match- ${databaseName}`, async () => {
|
|
851
|
+
await expect(`
|
|
852
|
+
run: ${databaseName}.sql("""
|
|
853
|
+
SELECT 'hello mom' as ${q `a`}, 'cheese tastes good' as ${q `b`}
|
|
854
|
+
UNION ALL SELECT 'lloyd is a bozo', 'michael likes poetry'
|
|
855
|
+
""") -> {
|
|
856
|
+
aggregate: llo is count() {where: a ~ r'llo'}
|
|
857
|
+
aggregate: m2 is count() {where: a !~ r'bozo'}
|
|
858
|
+
}
|
|
859
|
+
`).malloyResultMatches(runtime, { llo: 2, m2: 1 });
|
|
860
|
+
});
|
|
861
|
+
it(`substitution precedence- ${databaseName}`, async () => {
|
|
862
|
+
await expect(`
|
|
863
|
+
run: ${databaseName}.sql("""
|
|
864
|
+
SELECT 5 as ${q `a`}, 2 as ${q `b`}
|
|
865
|
+
UNION ALL SELECT 3, 4
|
|
866
|
+
""") -> {
|
|
867
|
+
extend: {dimension: c is b + 4}
|
|
868
|
+
select: x is a * c
|
|
869
|
+
}
|
|
870
|
+
`).malloyResultMatches(runtime, { x: 30 });
|
|
871
|
+
});
|
|
872
|
+
test(`array unnest - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsArraysInData, async () => {
|
|
873
|
+
const splitFN = getSplitFunction(databaseName);
|
|
874
|
+
await expect(`
|
|
875
|
+
run: ${databaseName}.sql("""
|
|
876
|
+
SELECT
|
|
877
|
+
${q `city`},
|
|
878
|
+
${splitFN(q `city`, ' ')} as ${q `words`}
|
|
879
|
+
FROM ${rootDbPath(databaseName)}malloytest.aircraft
|
|
880
|
+
""") -> {
|
|
881
|
+
where: words.value != null
|
|
882
|
+
group_by: words.value
|
|
883
|
+
aggregate: c is count()
|
|
884
|
+
}
|
|
885
|
+
`).malloyResultMatches(runtime, { c: 145 });
|
|
886
|
+
}));
|
|
887
|
+
// make sure we can count the total number of elements when fanning out.
|
|
888
|
+
test(`array unnest x 2 - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.supportsArraysInData, async () => {
|
|
889
|
+
const splitFN = getSplitFunction(databaseName);
|
|
890
|
+
await expect(`
|
|
891
|
+
run: ${databaseName}.sql("""
|
|
892
|
+
SELECT
|
|
893
|
+
${q `city`},
|
|
894
|
+
${splitFN(q `city`, ' ')} as ${q `words`},
|
|
895
|
+
${splitFN(q `city`, 'A')} as ${q `abreak`}
|
|
896
|
+
FROM ${rootDbPath(databaseName)}malloytest.aircraft
|
|
897
|
+
WHERE ${q `city`} IS NOT null
|
|
898
|
+
""") -> {
|
|
899
|
+
aggregate:
|
|
900
|
+
b is count()
|
|
901
|
+
c is words.count()
|
|
902
|
+
a is abreak.count()
|
|
903
|
+
}`).malloyResultMatches(runtime, { b: 3552, c: 4586, a: 6601 });
|
|
904
|
+
}));
|
|
905
|
+
test(`can unnest from file - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting && runtime.dialect.readsNestedData, async () => {
|
|
906
|
+
await expect(`
|
|
907
|
+
source: ga_sample is ${databaseName}.table('malloytest.ga_sample')
|
|
908
|
+
|
|
909
|
+
run: ga_sample -> {
|
|
910
|
+
where: hits.product.productBrand != null
|
|
911
|
+
group_by:
|
|
912
|
+
hits.product.productBrand
|
|
913
|
+
hits.product.productSKU
|
|
914
|
+
aggregate:
|
|
915
|
+
h is hits.count()
|
|
916
|
+
c is count()
|
|
917
|
+
p is hits.product.count()
|
|
918
|
+
}
|
|
919
|
+
`).malloyResultMatches(runtime, { h: 1192, c: 681, p: 1192 });
|
|
920
|
+
}));
|
|
921
|
+
test(`nest null - ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
922
|
+
const result = await runtime
|
|
923
|
+
.loadQuery(`
|
|
924
|
+
run: ${databaseName}.table('malloytest.airports') -> {
|
|
925
|
+
where: faa_region = null
|
|
926
|
+
group_by: faa_region
|
|
927
|
+
aggregate: airport_count is count()
|
|
928
|
+
nest: by_state is {
|
|
929
|
+
where: state != null
|
|
930
|
+
group_by: state
|
|
931
|
+
aggregate: airport_count is count()
|
|
932
|
+
}
|
|
933
|
+
nest: by_state1 is {
|
|
934
|
+
where: state != null
|
|
935
|
+
group_by: state
|
|
936
|
+
aggregate: airport_count is count()
|
|
937
|
+
limit: 1
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
`)
|
|
941
|
+
.run();
|
|
942
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
943
|
+
const d = result.data.toObject();
|
|
944
|
+
expect(d[0]['by_state']).not.toBe(null);
|
|
945
|
+
expect(d[0]['by_state1']).not.toBe(null);
|
|
946
|
+
}));
|
|
947
|
+
test(`number as null- ${databaseName}`, (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
948
|
+
const result = await runtime
|
|
949
|
+
.loadQuery(`
|
|
950
|
+
source: s is ${databaseName}.table('malloytest.state_facts') extend {
|
|
951
|
+
}
|
|
952
|
+
run: s-> {
|
|
953
|
+
group_by: state
|
|
954
|
+
nest: ugly is {
|
|
955
|
+
group_by: popular_name
|
|
956
|
+
aggregate: foo is NULLIF(sum(airport_count)*0,0)+1
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
`)
|
|
960
|
+
.run();
|
|
961
|
+
expect(result.data.path(0, 'ugly', 0, 'foo').value).toBe(null);
|
|
962
|
+
}));
|
|
963
|
+
it(`removes surpuflous order_by - solo aggregates - ${databaseName}`, async () => {
|
|
964
|
+
const result = await runtime
|
|
965
|
+
.loadQuery(`
|
|
966
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
967
|
+
aggregate: airport_count.sum()
|
|
968
|
+
}
|
|
969
|
+
`)
|
|
970
|
+
.run();
|
|
971
|
+
expect(result.sql).not.toContain('ORDER BY');
|
|
972
|
+
});
|
|
973
|
+
it(`removes surpuflous order_by - pipeline - ${databaseName}`, async () => {
|
|
974
|
+
const result = await runtime
|
|
975
|
+
.loadQuery(`
|
|
976
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
977
|
+
group_by: state
|
|
978
|
+
aggregate: airport_count.sum()
|
|
979
|
+
order_by: state desc
|
|
980
|
+
}
|
|
981
|
+
-> {
|
|
982
|
+
aggregate: airport_count.sum()
|
|
983
|
+
}
|
|
984
|
+
`)
|
|
985
|
+
.run();
|
|
986
|
+
expect(result.sql).not.toContain('ORDER BY');
|
|
987
|
+
});
|
|
988
|
+
it(`removes surpuflous order_by - joined_query - ${databaseName}`, async () => {
|
|
989
|
+
const result = await runtime
|
|
990
|
+
.loadQuery(`
|
|
991
|
+
query: foo is ${databaseName}.table('malloytest.state_facts') -> {
|
|
992
|
+
group_by: state
|
|
993
|
+
aggregate: airport_count.sum()
|
|
994
|
+
order_by: state desc
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
998
|
+
extend: {
|
|
999
|
+
join_one: foo on state = foo.state
|
|
1000
|
+
}
|
|
1001
|
+
aggregate: x is foo.airport_count.sum()
|
|
1002
|
+
}
|
|
1003
|
+
`)
|
|
1004
|
+
.run();
|
|
1005
|
+
expect(result.sql).not.toContain('ORDER BY');
|
|
1006
|
+
});
|
|
1007
|
+
it(`removes surpuflous order_by - joined_query pipeline - ${databaseName}`, async () => {
|
|
1008
|
+
const result = await runtime
|
|
1009
|
+
.loadQuery(`
|
|
1010
|
+
query: foo is ${databaseName}.table('malloytest.state_facts') -> {
|
|
1011
|
+
group_by: state
|
|
1012
|
+
aggregate: airport_count.sum()
|
|
1013
|
+
order_by: state desc
|
|
1014
|
+
} -> {
|
|
1015
|
+
group_by: state
|
|
1016
|
+
aggregate: airport_count.sum()
|
|
1017
|
+
order_by: state desc
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
run: ${databaseName}.table('malloytest.state_facts') -> {
|
|
1021
|
+
extend: {
|
|
1022
|
+
join_one: foo on state = foo.state
|
|
1023
|
+
}
|
|
1024
|
+
aggregate: x is foo.airport_count.sum()
|
|
1025
|
+
}
|
|
1026
|
+
`)
|
|
1027
|
+
.run();
|
|
1028
|
+
expect(result.sql).not.toContain('ORDER BY');
|
|
1029
|
+
});
|
|
1030
|
+
describe('quoting and strings', () => {
|
|
1031
|
+
const tick = "'";
|
|
1032
|
+
const back = '\\';
|
|
1033
|
+
test('backslash quote', async () => {
|
|
1034
|
+
await expect(`
|
|
1035
|
+
run: ${databaseName}.sql('SELECT 1 as one') -> {
|
|
1036
|
+
select: tick is '${back}${tick}'
|
|
1037
|
+
}
|
|
1038
|
+
`).malloyResultMatches(runtime, { tick });
|
|
1039
|
+
});
|
|
1040
|
+
test('backslash backslash', async () => {
|
|
1041
|
+
await expect(`
|
|
1042
|
+
run: ${databaseName}.sql("SELECT 1 as one") -> {
|
|
1043
|
+
select: back is '${back}${back}'
|
|
1044
|
+
}
|
|
1045
|
+
`).malloyResultMatches(runtime, { back });
|
|
1046
|
+
});
|
|
1047
|
+
test('spaces in names', (0, util_1.onlyIf)(runtime.supportsNesting, async () => {
|
|
1048
|
+
await expect(`
|
|
1049
|
+
source: \`space race\` is ${databaseName}.table('malloytest.state_facts') extend {
|
|
1050
|
+
join_one: \`j space\` is ${databaseName}.table('malloytest.state_facts') on \`j space\`.state=state
|
|
1051
|
+
view: \`q u e r y\` is {
|
|
1052
|
+
group_by:
|
|
1053
|
+
\`P O P\` is popular_name
|
|
1054
|
+
\`J P O P\` is \`j space\`.popular_name
|
|
1055
|
+
aggregate: \`c o u n t\` is count()
|
|
1056
|
+
calculate:
|
|
1057
|
+
\`R O W\` is row_number()
|
|
1058
|
+
\`l a g\` is lag(\`P O P\`, 1)
|
|
1059
|
+
nest: \`by state\` is {
|
|
1060
|
+
group_by: \`J S\` is \`j space\`.state
|
|
1061
|
+
aggregate: \`c o u n t\` is count()
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
run: \`space race\` -> \`q u e r y\`
|
|
1066
|
+
`).malloyResultMatches(runtime, { 'c o u n t': 24 });
|
|
1067
|
+
}));
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
//# sourceMappingURL=nomodel.spec.js.map
|