@malloydata/malloy-tests 0.0.94 → 0.0.95-dev231024220124
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +213 -1
- package/dist/api.spec.d.ts +1 -1
- package/dist/api.spec.js +6 -13
- package/dist/api.spec.js.map +1 -1
- package/dist/databases/all/db_index.spec.js +21 -41
- package/dist/databases/all/db_index.spec.js.map +1 -1
- package/dist/databases/all/expr.spec.js +262 -339
- package/dist/databases/all/expr.spec.js.map +1 -1
- package/dist/databases/all/functions.spec.js +37 -35
- package/dist/databases/all/functions.spec.js.map +1 -1
- package/dist/databases/all/join.spec.js +125 -169
- package/dist/databases/all/join.spec.js.map +1 -1
- package/dist/databases/all/nomodel.spec.js +335 -594
- package/dist/databases/all/nomodel.spec.js.map +1 -1
- package/dist/databases/all/orderby.spec.js +82 -128
- package/dist/databases/all/orderby.spec.js.map +1 -1
- package/dist/databases/all/sql_expressions.spec.js +27 -43
- package/dist/databases/all/sql_expressions.spec.js.map +1 -1
- package/dist/databases/all/time.spec.js +63 -103
- package/dist/databases/all/time.spec.js.map +1 -1
- package/dist/databases/bigquery/double_truncation.spec.js +1 -1
- package/dist/databases/bigquery/handexpr.spec.js +12 -12
- package/dist/databases/bigquery/injestion_time_partitioning.spec.js +22 -22
- package/dist/databases/bigquery/joined_filters.spec.js +3 -3
- package/dist/databases/bigquery/json.spec.d.ts +1 -1
- package/dist/databases/bigquery/json.spec.js +25 -45
- package/dist/databases/bigquery/json.spec.js.map +1 -1
- package/dist/databases/bigquery/malloy_query.spec.d.ts +1 -1
- package/dist/databases/bigquery/malloy_query.spec.js +47 -48
- package/dist/databases/bigquery/malloy_query.spec.js.map +1 -1
- package/dist/databases/bigquery/time.spec.js +9 -13
- package/dist/databases/bigquery/time.spec.js.map +1 -1
- package/dist/databases/bigquery/wildcard_table_names.spec.js +19 -19
- package/dist/databases/bigquery-duckdb/nested_source_table.spec.js +53 -87
- package/dist/databases/bigquery-duckdb/nested_source_table.spec.js.map +1 -1
- package/dist/databases/bigquery-postgres/multi_connection.spec.js +5 -20
- package/dist/databases/bigquery-postgres/multi_connection.spec.js.map +1 -1
- package/dist/databases/bigquery-postgres/streaming.spec.js +6 -6
- package/dist/databases/bigquery-postgres/streaming.spec.js.map +1 -1
- package/dist/databases/duckdb/duckdb.spec.js +24 -33
- package/dist/databases/duckdb/duckdb.spec.js.map +1 -1
- package/dist/databases/postgres/postgres.spec.js +46 -67
- package/dist/databases/postgres/postgres.spec.js.map +1 -1
- 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/render/render.spec.js +10 -12
- package/dist/render/render.spec.js.map +1 -1
- package/dist/tags.spec.js +22 -2
- package/dist/tags.spec.js.map +1 -1
- package/dist/util/db-jest-matchers.d.ts +17 -6
- package/dist/util/db-jest-matchers.js +81 -20
- package/dist/util/db-jest-matchers.js.map +1 -1
- package/dist/util/index.d.ts +1 -2
- package/dist/util/index.js +11 -13
- package/dist/util/index.js.map +1 -1
- package/package.json +6 -6
- package/src/api.spec.ts +7 -16
- package/src/databases/all/db_index.spec.ts +22 -48
- package/src/databases/all/expr.spec.ts +273 -431
- package/src/databases/all/functions.spec.ts +37 -35
- package/src/databases/all/join.spec.ts +130 -196
- package/src/databases/all/nomodel.spec.ts +333 -689
- package/src/databases/all/orderby.spec.ts +87 -161
- package/src/databases/all/sql_expressions.spec.ts +29 -49
- package/src/databases/all/time.spec.ts +73 -130
- package/src/databases/bigquery/double_truncation.spec.ts +1 -1
- package/src/databases/bigquery/handexpr.spec.ts +12 -12
- package/src/databases/bigquery/injestion_time_partitioning.spec.ts +22 -22
- package/src/databases/bigquery/joined_filters.spec.ts +3 -3
- package/src/databases/bigquery/json.spec.ts +25 -49
- package/src/databases/bigquery/malloy_query.spec.ts +47 -54
- package/src/databases/bigquery/time.spec.ts +13 -17
- package/src/databases/bigquery/wildcard_table_names.spec.ts +19 -19
- package/src/databases/bigquery-duckdb/nested_source_table.spec.ts +56 -98
- package/src/databases/bigquery-postgres/multi_connection.spec.ts +5 -23
- package/src/databases/bigquery-postgres/streaming.spec.ts +12 -6
- package/src/databases/duckdb/duckdb.spec.ts +31 -43
- package/src/databases/postgres/postgres.spec.ts +54 -84
- package/src/jestMatcher.spec.ts +88 -0
- package/src/render/render.spec.ts +10 -12
- package/src/tags.spec.ts +22 -2
- package/src/util/db-jest-matchers.ts +106 -32
- package/src/util/index.ts +16 -14
|
@@ -27,126 +27,106 @@ const runtimes_1 = require("../../runtimes");
|
|
|
27
27
|
require("../../util/db-jest-matchers");
|
|
28
28
|
const util_1 = require("../../util");
|
|
29
29
|
const runtimes = new runtimes_1.RuntimeList((0, util_1.databasesFromEnvironmentOr)(runtimes_1.allDatabases));
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
function modelText(databaseName) {
|
|
31
|
+
return `
|
|
32
|
+
source: aircraft_models is ${databaseName}.table('malloytest.aircraft_models') extend {
|
|
32
33
|
primary_key: aircraft_model_code
|
|
33
34
|
measure:
|
|
34
35
|
aircraft_model_count is count(),
|
|
35
36
|
total_seats is sum(seats),
|
|
36
|
-
boeing_seats is sum(seats) {
|
|
37
|
+
boeing_seats is sum(seats) { where: manufacturer ? 'BOEING'},
|
|
37
38
|
percent_boeing is boeing_seats / total_seats * 100,
|
|
38
39
|
percent_boeing_floor is floor(boeing_seats / total_seats * 100),
|
|
39
40
|
dimension: seats_bucketed is floor(seats/20)*20.0
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
source: aircraft is table('malloytest.aircraft') extend {
|
|
43
|
+
source: aircraft is ${databaseName}.table('malloytest.aircraft') extend {
|
|
43
44
|
primary_key: tail_num
|
|
44
45
|
join_one: aircraft_models with aircraft_model_code
|
|
45
46
|
measure: aircraft_count is count()
|
|
46
|
-
|
|
47
|
+
view: by_manufacturer is {
|
|
47
48
|
top: 5
|
|
48
49
|
group_by: aircraft_models.manufacturer
|
|
49
50
|
aggregate: aircraft_count
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
`;
|
|
54
|
+
}
|
|
53
55
|
describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
54
|
-
const expressionModel = runtime.loadModel(
|
|
56
|
+
const expressionModel = runtime.loadModel(modelText(databaseName));
|
|
55
57
|
// basic calculations for sum, filtered sum, without a join.
|
|
56
58
|
it('basic calculations', async () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
expect(result.data.path(0, 'boeing_seats').value).toBe(252771);
|
|
76
|
-
expect(result.data.path(0, 'boeing_seats2').value).toBe(252771);
|
|
77
|
-
expect(result.data.path(0, 'boeing_seats3').value).toBe(252771);
|
|
78
|
-
expect(Math.floor(result.data.path(0, 'percent_boeing').number.value)).toBe(55);
|
|
79
|
-
expect(Math.floor(result.data.path(0, 'percent_boeing2').number.value)).toBe(55);
|
|
80
|
-
// expect(result.data.path(0, "percent_boeing_floor").value).toBe(55);
|
|
81
|
-
// expect(result.data.path(0, "percent_boeing_floor2").value).toBe(55);
|
|
59
|
+
await expect(`
|
|
60
|
+
run: aircraft_models->{
|
|
61
|
+
aggregate:
|
|
62
|
+
total_seats,
|
|
63
|
+
total_seats2 is sum(seats),
|
|
64
|
+
boeing_seats,
|
|
65
|
+
boeing_seats2 is sum(seats) { where: manufacturer ? 'BOEING'},
|
|
66
|
+
boeing_seats3 is total_seats { where: manufacturer ? 'BOEING'},
|
|
67
|
+
percent_boeing_floor,
|
|
68
|
+
}
|
|
69
|
+
`).malloyResultMatches(expressionModel, {
|
|
70
|
+
total_seats: 452415,
|
|
71
|
+
total_seats2: 452415,
|
|
72
|
+
boeing_seats: 252771,
|
|
73
|
+
boeing_seats2: 252771,
|
|
74
|
+
boeing_seats3: 252771,
|
|
75
|
+
percent_boeing_floor: 55,
|
|
76
|
+
});
|
|
82
77
|
});
|
|
83
|
-
// Floor
|
|
78
|
+
// Floor was broken (wouldn't compile because the expression returned isn't an aggregate.)
|
|
84
79
|
it('Floor() -or any function bustage with aggregates', async () => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
expect(result.data.path(0, 'percent_boeing_floor2').value).toBe(55);
|
|
80
|
+
await expect(`
|
|
81
|
+
run: aircraft_models->{
|
|
82
|
+
aggregate:
|
|
83
|
+
percent_boeing_floor
|
|
84
|
+
percent_boeing_floor2 is floor(boeing_seats / total_seats * 100)
|
|
85
|
+
}
|
|
86
|
+
`).malloyResultMatches(expressionModel, {
|
|
87
|
+
percent_boeing_floor: 55,
|
|
88
|
+
percent_boeing_floor2: 55,
|
|
89
|
+
});
|
|
96
90
|
});
|
|
97
91
|
// Model based version of sums.
|
|
98
92
|
it('model: expression fixups.', async () => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
expect(result.data.path(0, 'boeing_seats').value).toBe(6244);
|
|
93
|
+
await expect(`
|
|
94
|
+
run: aircraft->{
|
|
95
|
+
aggregate:
|
|
96
|
+
aircraft_models.total_seats
|
|
97
|
+
aircraft_models.boeing_seats
|
|
98
|
+
}
|
|
99
|
+
`).malloyResultMatches(expressionModel, {
|
|
100
|
+
total_seats: 18294,
|
|
101
|
+
boeing_seats: 6244,
|
|
102
|
+
});
|
|
110
103
|
});
|
|
111
104
|
// turtle expressions
|
|
112
105
|
it('model: turtle', async () => {
|
|
113
|
-
|
|
114
|
-
.loadQuery(`
|
|
115
|
-
query: aircraft->by_manufacturer
|
|
116
|
-
`)
|
|
117
|
-
.run();
|
|
118
|
-
expect(result.data.path(0, 'manufacturer').value).toBe('CESSNA');
|
|
106
|
+
await expect('run: aircraft->by_manufacturer').malloyResultMatches(expressionModel, { manufacturer: 'CESSNA' });
|
|
119
107
|
});
|
|
120
108
|
// filtered turtle expressions
|
|
121
109
|
(0, util_1.testIf)(runtime.supportsNesting)('model: filtered turtle', async () => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
`)
|
|
128
|
-
.run();
|
|
129
|
-
expect(result.data.path(0, 'b', 0, 'manufacturer').value).toBe('BEECH');
|
|
110
|
+
await expect(`
|
|
111
|
+
run: aircraft->{
|
|
112
|
+
nest: b is by_manufacturer refine { where: aircraft_models.manufacturer ?~'B%'}
|
|
113
|
+
}
|
|
114
|
+
`).malloyResultMatches(expressionModel, { 'b.manufacturer': 'BEECH' });
|
|
130
115
|
});
|
|
131
116
|
// having.
|
|
132
117
|
it('model: simple having', async () => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
`)
|
|
142
|
-
.run();
|
|
143
|
-
expect(result.data.path(0, 'aircraft_count').value).toBe(91);
|
|
118
|
+
await expect(`
|
|
119
|
+
run: aircraft->{
|
|
120
|
+
having: aircraft_count >90
|
|
121
|
+
group_by: state
|
|
122
|
+
aggregate: aircraft_count
|
|
123
|
+
order_by: 2
|
|
124
|
+
}
|
|
125
|
+
`).malloyResultMatches(expressionModel, { aircraft_count: 91 });
|
|
144
126
|
});
|
|
145
|
-
(0, util_1.testIf)(runtime.supportsNesting)('model:
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
-- hacking a null test for now
|
|
149
|
-
query: aircraft->{
|
|
127
|
+
(0, util_1.testIf)(runtime.supportsNesting)('model: having in a nest', async () => {
|
|
128
|
+
await expect(`
|
|
129
|
+
run: aircraft->{
|
|
150
130
|
top: 10
|
|
151
131
|
order_by: 1
|
|
152
132
|
where: region != NULL
|
|
@@ -159,14 +139,11 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
159
139
|
aggregate: aircraft_count
|
|
160
140
|
}
|
|
161
141
|
}
|
|
162
|
-
|
|
163
|
-
.run();
|
|
164
|
-
expect(result.data.path(0, 'by_state', 0, 'state').value).toBe('VA');
|
|
142
|
+
`).malloyResultMatches(expressionModel, { 'by_state.state': 'VA' });
|
|
165
143
|
});
|
|
166
144
|
(0, util_1.testIf)(runtime.supportsNesting)('model: turtle having on main', async () => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
query: aircraft->{
|
|
145
|
+
await expect(`
|
|
146
|
+
run: aircraft->{
|
|
170
147
|
order_by: 2 asc
|
|
171
148
|
having: aircraft_count ? >500
|
|
172
149
|
group_by: region
|
|
@@ -184,88 +161,86 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
184
161
|
}
|
|
185
162
|
}
|
|
186
163
|
}
|
|
187
|
-
|
|
188
|
-
.
|
|
189
|
-
|
|
164
|
+
`).malloyResultMatches(expressionModel, {
|
|
165
|
+
'by_state.by_city.city': 'ALBUQUERQUE',
|
|
166
|
+
});
|
|
190
167
|
});
|
|
191
168
|
// bigquery doesn't like to partition by floats,
|
|
192
169
|
(0, util_1.testIf)(runtime.supportsNesting)('model: having float group by partition', async () => {
|
|
193
|
-
await expect(
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
aggregate: aircraft_model_count
|
|
200
|
-
nest: foo is {
|
|
201
|
-
group_by: engines
|
|
170
|
+
await expect(`${modelText(databaseName)}
|
|
171
|
+
run: aircraft_models->{
|
|
172
|
+
order_by: 1
|
|
173
|
+
where: seats_bucketed > 0
|
|
174
|
+
having: aircraft_model_count > 400
|
|
175
|
+
group_by: seats_bucketed
|
|
202
176
|
aggregate: aircraft_model_count
|
|
203
|
-
|
|
204
|
-
|
|
177
|
+
nest: foo is {
|
|
178
|
+
group_by: engines
|
|
179
|
+
aggregate: aircraft_model_count
|
|
180
|
+
}
|
|
181
|
+
}`).malloyResultMatches(runtime, { aircraft_model_count: 448 });
|
|
205
182
|
});
|
|
206
183
|
it('model: aggregate functions distinct min max', async () => {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
expect(result.data.path(0, 'boeing_max_model').value).toBe('YL-15');
|
|
184
|
+
await expect(`
|
|
185
|
+
run: aircraft_models->{
|
|
186
|
+
aggregate:
|
|
187
|
+
distinct_seats is count(seats),
|
|
188
|
+
boeing_distinct_seats is count(seats) { where:manufacturer ? 'BOEING'},
|
|
189
|
+
min_seats is min(seats),
|
|
190
|
+
cessna_min_seats is min(seats) { where: manufacturer ? 'CESSNA'},
|
|
191
|
+
max_seats is max(seats),
|
|
192
|
+
cessna_max_seats is max(seats) { where: manufacturer ? 'CESSNA'},
|
|
193
|
+
min_code is min(aircraft_model_code),
|
|
194
|
+
boeing_min_model is min(model) { where: manufacturer ? 'BOEING'},
|
|
195
|
+
max_model is max(model),
|
|
196
|
+
boeing_max_model is max(model) { where: manufacturer ? 'BOEING'},
|
|
197
|
+
}
|
|
198
|
+
`).malloyResultMatches(expressionModel, {
|
|
199
|
+
distinct_seats: 187,
|
|
200
|
+
boeing_distinct_seats: 85,
|
|
201
|
+
min_seats: 0,
|
|
202
|
+
cessna_min_seats: 1,
|
|
203
|
+
max_seats: 660,
|
|
204
|
+
min_code: '0030109',
|
|
205
|
+
cessna_max_seats: 14,
|
|
206
|
+
boeing_min_model: '100',
|
|
207
|
+
max_model: 'ZWEIFEL PA18',
|
|
208
|
+
boeing_max_model: 'YL-15',
|
|
209
|
+
});
|
|
234
210
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
expect(result.data.path(0, 't_timestamp_year').value).toEqual(new Date('2020-01-01'));
|
|
211
|
+
// TODO not sure why this test needs to be skipped on postgres, feels like an oversight
|
|
212
|
+
(0, util_1.testIf)(databaseName !== 'postgres')('model: dates named', async () => {
|
|
213
|
+
await expect(`
|
|
214
|
+
run: ${databaseName}.table('malloytest.alltypes')->{
|
|
215
|
+
group_by:
|
|
216
|
+
t_date,
|
|
217
|
+
t_date_month is t_date.month,
|
|
218
|
+
t_date_year is t_date.year,
|
|
219
|
+
t_timestamp,
|
|
220
|
+
t_timestamp_date is t_timestamp.day,
|
|
221
|
+
t_timestamp_hour is t_timestamp.hour,
|
|
222
|
+
t_timestamp_minute is t_timestamp.minute,
|
|
223
|
+
t_timestamp_second is t_timestamp.second,
|
|
224
|
+
t_timestamp_month is t_timestamp.month,
|
|
225
|
+
t_timestamp_year is t_timestamp.year,
|
|
226
|
+
}
|
|
227
|
+
`).malloyResultMatches(runtime, {
|
|
228
|
+
t_date: new Date('2020-03-02'),
|
|
229
|
+
t_date_month: new Date('2020-03-01'),
|
|
230
|
+
t_date_year: new Date('2020-01-01'),
|
|
231
|
+
t_timestamp: new Date('2020-03-02T12:35:56.000Z'),
|
|
232
|
+
t_timestamp_second: new Date('2020-03-02T12:35:56.000Z'),
|
|
233
|
+
t_timestamp_minute: new Date('2020-03-02T12:35:00.000Z'),
|
|
234
|
+
t_timestamp_hour: new Date('2020-03-02T12:00:00.000Z'),
|
|
235
|
+
t_timestamp_date: new Date('2020-03-02'),
|
|
236
|
+
t_timestamp_month: new Date('2020-03-01'),
|
|
237
|
+
t_timestamp_year: new Date('2020-01-01'),
|
|
238
|
+
});
|
|
264
239
|
});
|
|
265
240
|
it('named query metadata undefined', async () => {
|
|
266
241
|
const result = await expressionModel
|
|
267
242
|
.loadQuery(`
|
|
268
|
-
|
|
243
|
+
run: aircraft->{
|
|
269
244
|
aggregate: aircraft_count is count()
|
|
270
245
|
}
|
|
271
246
|
`)
|
|
@@ -278,16 +253,14 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
278
253
|
});
|
|
279
254
|
it('named query metadata named', async () => {
|
|
280
255
|
const result = await expressionModel
|
|
281
|
-
.loadQuery(
|
|
282
|
-
query: aircraft->by_manufacturer
|
|
283
|
-
`)
|
|
256
|
+
.loadQuery('run: aircraft->by_manufacturer')
|
|
284
257
|
.run();
|
|
285
258
|
expect(result.resultExplore.name).toBe('by_manufacturer');
|
|
286
259
|
});
|
|
287
260
|
it('named query metadata named head of pipeline', async () => {
|
|
288
261
|
const result = await expressionModel
|
|
289
262
|
.loadQuery(`
|
|
290
|
-
|
|
263
|
+
run: aircraft->by_manufacturer->{ aggregate: c is count()}
|
|
291
264
|
`)
|
|
292
265
|
.run();
|
|
293
266
|
// TODO Same as above -- this test should check the explore name
|
|
@@ -295,65 +268,51 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
295
268
|
expect(result._queryResult.queryName).toBe(undefined);
|
|
296
269
|
});
|
|
297
270
|
it('filtered explores basic', async () => {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
query: b->{aggregate: m_count is count(aircraft_models.manufacturer) }
|
|
303
|
-
`)
|
|
304
|
-
.run();
|
|
305
|
-
expect(result.data.path(0, 'm_count').value).toBe(63);
|
|
271
|
+
await expect(`
|
|
272
|
+
run: aircraft extend { where: aircraft_models.manufacturer ? ~'B%' }
|
|
273
|
+
-> {aggregate: m_count is count(aircraft_models.manufacturer) }
|
|
274
|
+
`).malloyResultMatches(expressionModel, { m_count: 63 });
|
|
306
275
|
});
|
|
307
276
|
it('sql cast', async () => {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
expect(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
expect(result.data.path(0, 'a').number.value).toBe(312);
|
|
327
|
-
}
|
|
277
|
+
await expect(`
|
|
278
|
+
run: aircraft -> {
|
|
279
|
+
group_by: a is "312"::"integer"
|
|
280
|
+
}
|
|
281
|
+
`).malloyResultMatches(expressionModel, { a: 312 });
|
|
282
|
+
});
|
|
283
|
+
(0, util_1.testIf)(runtime.connection.name !== 'postgres')('sql safe cast', async () => {
|
|
284
|
+
await expect(`
|
|
285
|
+
run: ${databaseName}.sql('SELECT 1') -> { select:
|
|
286
|
+
bad_date is '123':::date
|
|
287
|
+
bad_number is 'abc':::number
|
|
288
|
+
good_number is "312":::"integer"
|
|
289
|
+
}
|
|
290
|
+
`).malloyResultMatches(expressionModel, {
|
|
291
|
+
bad_date: null,
|
|
292
|
+
bad_number: null,
|
|
293
|
+
good_number: 312,
|
|
294
|
+
});
|
|
328
295
|
});
|
|
329
296
|
it('many_field.sum() has correct locality', async () => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
join_many: a on a.aircraft_model_code = a.aircraft_model_code
|
|
337
|
-
dimension: a_year_built is a.year_built
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// run: a -> {
|
|
341
|
-
// aggregate: avg_year_built is avg(year_built)
|
|
342
|
-
// }
|
|
297
|
+
await expect(`
|
|
298
|
+
source: a is ${databaseName}.table('malloytest.aircraft')
|
|
299
|
+
source: am is ${databaseName}.table('malloytest.aircraft_models') extend {
|
|
300
|
+
join_many: a on a.aircraft_model_code = a.aircraft_model_code
|
|
301
|
+
dimension: a_year_built is a.year_built
|
|
302
|
+
}
|
|
343
303
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
304
|
+
run: am -> {
|
|
305
|
+
aggregate: avg_a_year_built1 is floor(a_year_built.avg())
|
|
306
|
+
aggregate: avg_a_year_built2 is floor(a.avg(a_year_built))
|
|
307
|
+
}
|
|
308
|
+
`).malloyResultMatches(runtime, {
|
|
309
|
+
avg_a_year_built1: 1969,
|
|
310
|
+
avg_a_year_built2: 1969,
|
|
311
|
+
});
|
|
352
312
|
});
|
|
353
313
|
(0, util_1.testIf)(runtime.supportsNesting)('query with aliasname used twice', async () => {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
query: aircraft->{
|
|
314
|
+
await expect(`
|
|
315
|
+
run: aircraft->{
|
|
357
316
|
group_by: first is substr(city,1,1)
|
|
358
317
|
aggregate: aircraft_count is count()
|
|
359
318
|
nest: aircraft is {
|
|
@@ -370,145 +329,111 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
370
329
|
aircraft_count
|
|
371
330
|
order_by: 2 desc, 1
|
|
372
331
|
}
|
|
373
|
-
`)
|
|
374
|
-
.run();
|
|
375
|
-
expect(result.data.path(0, 'first_three').value).toBe('SAB');
|
|
376
|
-
});
|
|
377
|
-
it.skip('join foreign_key reverse', async () => {
|
|
378
|
-
const result = await expressionModel
|
|
379
|
-
.loadQuery(`
|
|
380
|
-
source: a is table('malloytest.aircraft') {
|
|
381
|
-
primary_key: tail_num
|
|
382
|
-
measure: aircraft_count is count()
|
|
383
|
-
}
|
|
384
|
-
query: table('malloytest.aircraft_models') {
|
|
385
|
-
primary_key: aircraft_model_code
|
|
386
|
-
join_many: a on a.aircraft_model_code
|
|
387
|
-
|
|
388
|
-
some_measures is {
|
|
389
|
-
aggregate: am_count is count()
|
|
390
|
-
aggregate: a.aircraft_count
|
|
391
|
-
}
|
|
392
|
-
} -> some_measure
|
|
393
|
-
`)
|
|
394
|
-
.run();
|
|
395
|
-
expect(result.data.path(0, 'first_three').value).toBe('SAN');
|
|
332
|
+
`).malloyResultMatches(expressionModel, { first_three: 'SAB' });
|
|
396
333
|
});
|
|
397
|
-
it('joined filtered
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
}
|
|
334
|
+
it('joined filtered sources', async () => {
|
|
335
|
+
await expect(`
|
|
336
|
+
source: a_models is ${databaseName}.table('malloytest.aircraft_models') extend {
|
|
337
|
+
where: manufacturer ? ~'B%'
|
|
338
|
+
primary_key: aircraft_model_code
|
|
339
|
+
measure:model_count is count()
|
|
340
|
+
}
|
|
405
341
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
342
|
+
source: aircraft2 is ${databaseName}.table('malloytest.aircraft') extend {
|
|
343
|
+
join_one: model is a_models with aircraft_model_code
|
|
344
|
+
measure: aircraft_count is count()
|
|
345
|
+
}
|
|
410
346
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
347
|
+
run: aircraft2->{
|
|
348
|
+
aggregate:
|
|
349
|
+
model.model_count
|
|
350
|
+
aircraft_count
|
|
351
|
+
}
|
|
352
|
+
`).malloyResultMatches(expressionModel, {
|
|
353
|
+
model_count: 244,
|
|
354
|
+
aircraft_count: 3599,
|
|
355
|
+
});
|
|
420
356
|
});
|
|
421
357
|
it('joined filtered explores with dependancies', async () => {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
-> { select: aircraft_model_code, manufacturer, seats }
|
|
428
|
-
) {
|
|
358
|
+
await expect(`
|
|
359
|
+
source: bo_models is
|
|
360
|
+
${databaseName}.table('malloytest.aircraft_models') extend { where: manufacturer ? ~ 'BO%' }
|
|
361
|
+
-> { select: aircraft_model_code, manufacturer, seats }
|
|
362
|
+
extend {
|
|
429
363
|
primary_key: aircraft_model_code
|
|
430
364
|
measure: bo_count is count()
|
|
431
365
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
-> { select: aircraft_model_code, manufacturer, seats }
|
|
437
|
-
) {
|
|
366
|
+
source: b_models is
|
|
367
|
+
${databaseName}.table('malloytest.aircraft_models') extend { where: manufacturer ? ~ 'B%' }
|
|
368
|
+
-> { select: aircraft_model_code, manufacturer, seats }
|
|
369
|
+
extend {
|
|
438
370
|
where: bo_models.seats > 200
|
|
439
371
|
primary_key: aircraft_model_code
|
|
440
372
|
measure: b_count is count()
|
|
441
373
|
join_one: bo_models with aircraft_model_code
|
|
442
374
|
}
|
|
443
375
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
376
|
+
source: models is ${databaseName}.table('malloytest.aircraft_models') extend {
|
|
377
|
+
join_one: b_models with aircraft_model_code
|
|
378
|
+
measure: model_count is count()
|
|
379
|
+
}
|
|
448
380
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
.run();
|
|
456
|
-
expect(result.data.path(0, 'model_count').value).toBe(60461);
|
|
457
|
-
expect(result.data.path(0, 'b_count').value).toBe(355);
|
|
381
|
+
run: models -> {
|
|
382
|
+
aggregate: model_count
|
|
383
|
+
aggregate: b_models.b_count
|
|
384
|
+
-- aggregate: b_models.bo_models.bo_count
|
|
385
|
+
}
|
|
386
|
+
`).malloyResultMatches(runtime, { model_count: 60461, b_count: 355 });
|
|
458
387
|
});
|
|
459
|
-
it('group by
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
expect(result.data.path(0, 'aircraft_models_id').value).toBe('7102802');
|
|
388
|
+
it('group by join - simple group by', async () => {
|
|
389
|
+
await expect(`
|
|
390
|
+
run: aircraft->{
|
|
391
|
+
group_by: aircraft_models
|
|
392
|
+
aggregate: aircraft_count
|
|
393
|
+
}
|
|
394
|
+
`).malloyResultMatches(expressionModel, {
|
|
395
|
+
aircraft_models_id: '7102802',
|
|
396
|
+
aircraft_count: 58,
|
|
397
|
+
});
|
|
470
398
|
});
|
|
471
399
|
it('group by explore - pipeline', async () => {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
expect(result.data.path(0, 'manufacturer').value).toBe('CESSNA');
|
|
400
|
+
await expect(`
|
|
401
|
+
run: aircraft->{
|
|
402
|
+
group_by: aircraft_models
|
|
403
|
+
aggregate: aircraft_count
|
|
404
|
+
} -> {
|
|
405
|
+
group_by: aircraft_models.manufacturer
|
|
406
|
+
aggregate: aircraft_count is aircraft_count.sum()
|
|
407
|
+
}
|
|
408
|
+
`).malloyResultMatches(expressionModel, {
|
|
409
|
+
aircraft_count: 1048,
|
|
410
|
+
manufacturer: 'CESSNA',
|
|
411
|
+
});
|
|
485
412
|
});
|
|
486
413
|
it('group by explore - pipeline 2 levels', async () => {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
414
|
+
await expect(`
|
|
415
|
+
run: ${databaseName}.table('malloytest.flights') extend {
|
|
416
|
+
join_one: a is ${databaseName}.table('malloytest.aircraft') extend {
|
|
417
|
+
join_one: state_facts
|
|
418
|
+
is ${databaseName}.table('malloytest.state_facts') extend {primary_key: state}
|
|
419
|
+
with state
|
|
492
420
|
} on tail_num = a.tail_num
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
query: f-> {
|
|
421
|
+
} -> {
|
|
496
422
|
group_by: a.state_facts
|
|
497
423
|
aggregate: flight_count is count()
|
|
498
424
|
} -> {
|
|
499
425
|
group_by: state_facts.popular_name
|
|
500
426
|
aggregate: flight_count is flight_count.sum()
|
|
501
427
|
}
|
|
502
|
-
`)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
expect(result.data.path(0, 'popular_name').value).toBe('Isabella');
|
|
428
|
+
`).malloyResultMatches(runtime, {
|
|
429
|
+
flight_count: 199726,
|
|
430
|
+
popular_name: 'Isabella',
|
|
431
|
+
});
|
|
507
432
|
});
|
|
508
433
|
});
|
|
509
434
|
describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
510
|
-
const sqlEq = (0, util_1.mkSqlEqWith)(runtime, {
|
|
511
|
-
malloy:
|
|
435
|
+
const sqlEq = (0, util_1.mkSqlEqWith)(runtime, databaseName, {
|
|
436
|
+
malloy: `extend {
|
|
512
437
|
dimension: friName is 'friday'
|
|
513
438
|
dimension: friDay is 5
|
|
514
439
|
dimension: satName is 'saturday'
|
|
@@ -565,40 +490,38 @@ describe.each(runtimes.runtimeList)('%s', (databaseName, runtime) => {
|
|
|
565
490
|
expect(await sqlEq(`'${back}${tick}'`, tick)).isSqlEq();
|
|
566
491
|
});
|
|
567
492
|
test('quote double quote', async () => {
|
|
568
|
-
await expect(
|
|
569
|
-
query: from_sql(x) -> {
|
|
493
|
+
await expect(`run: ${databaseName}.sql("SELECT 1") -> {
|
|
570
494
|
select: double_quote is "${back}${dq}"
|
|
571
|
-
}
|
|
572
|
-
`, { double_quote: '"' });
|
|
495
|
+
}`).malloyResultMatches(runtime, { double_quote: '"' });
|
|
573
496
|
});
|
|
574
497
|
test('quote backslash', async () => {
|
|
575
498
|
expect(await sqlEq(`'${back}${back}'`, back)).isSqlEq();
|
|
576
499
|
});
|
|
577
500
|
});
|
|
578
501
|
test('nullish ?? operator', async () => {
|
|
579
|
-
await expect(
|
|
502
|
+
await expect(`run: ${databaseName}.sql("""
|
|
580
503
|
SELECT '' as null_value, '' as string_value
|
|
581
504
|
UNION ALL SELECT null, 'correct'
|
|
582
|
-
"""
|
|
583
|
-
query: from_sql(nullTest) -> {
|
|
505
|
+
""") -> {
|
|
584
506
|
where: null_value = null
|
|
585
507
|
select:
|
|
586
508
|
found_null is null_value ?? 'correct',
|
|
587
509
|
else_pass is string_value ?? 'incorrect'
|
|
588
510
|
literal_null is null ?? 'correct'
|
|
589
|
-
}
|
|
511
|
+
}`).malloyResultMatches(runtime, {
|
|
512
|
+
found_null: 'correct',
|
|
513
|
+
else_pass: 'correct',
|
|
514
|
+
literal_null: 'correct',
|
|
515
|
+
});
|
|
590
516
|
});
|
|
591
517
|
test('dimension expressions expanded with parens properly', async () => {
|
|
592
|
-
await expect(
|
|
593
|
-
sql: tbl is { connection: "${databaseName}" select: """SELECT 1 as n"""}
|
|
594
|
-
query: from_sql(tbl) + {
|
|
518
|
+
await expect(`run: ${databaseName}.sql("SELECT 1") extend {
|
|
595
519
|
dimension: fot is (false) or (true)
|
|
596
520
|
} -> {
|
|
597
521
|
select:
|
|
598
522
|
no_paren is false and fot
|
|
599
523
|
paren is false and (fot)
|
|
600
|
-
}
|
|
601
|
-
`, { paren: false, no_paren: false });
|
|
524
|
+
}`).malloyResultMatches(runtime, { paren: false, no_paren: false });
|
|
602
525
|
});
|
|
603
526
|
});
|
|
604
527
|
afterAll(async () => {
|