@malloydata/malloy 0.0.15 → 0.0.16-dev221214152428
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/dialect/dialect.d.ts +1 -0
- package/dist/dialect/duckdb.d.ts +1 -0
- package/dist/dialect/duckdb.js +3 -0
- package/dist/dialect/postgres.d.ts +1 -0
- package/dist/dialect/postgres.js +1 -0
- package/dist/dialect/standardsql.d.ts +1 -0
- package/dist/dialect/standardsql.js +1 -0
- package/dist/lang/lib/Malloy/MalloyParser.d.ts +1 -0
- package/dist/lang/lib/Malloy/MalloyParser.js +405 -398
- package/dist/model/malloy_query.js +113 -22
- package/package.json +1 -1
|
@@ -1658,6 +1658,9 @@ class QueryQuery extends QueryField {
|
|
|
1658
1658
|
let structSQL = qs.structSourceSQL(stageWriter);
|
|
1659
1659
|
if ((0, malloy_types_1.isIndexSegment)(this.firstSegment)) {
|
|
1660
1660
|
structSQL = this.parent.dialect.sqlSampleTable(structSQL, this.firstSegment.sample);
|
|
1661
|
+
if (this.firstSegment.sample) {
|
|
1662
|
+
structSQL = stageWriter.addStage(`SELECT * from ${structSQL} as x limit 100000 `);
|
|
1663
|
+
}
|
|
1661
1664
|
}
|
|
1662
1665
|
const structRelationship = qs.fieldDef.structRelationship;
|
|
1663
1666
|
if (structRelationship.type === "basetable") {
|
|
@@ -2211,23 +2214,13 @@ class QueryQueryReduce extends QueryQuery {
|
|
|
2211
2214
|
}
|
|
2212
2215
|
class QueryQueryProject extends QueryQuery {
|
|
2213
2216
|
}
|
|
2214
|
-
|
|
2217
|
+
// generates a single stage query for the index.
|
|
2218
|
+
// wildcards have been expanded
|
|
2219
|
+
// nested repeated fields are safe to use.
|
|
2220
|
+
class QueryQueryIndexStage extends QueryQuery {
|
|
2215
2221
|
constructor(fieldDef, parent, stageWriter) {
|
|
2216
2222
|
super(fieldDef, parent, stageWriter);
|
|
2217
|
-
this.fanPrefixes = [];
|
|
2218
2223
|
this.fieldDef = fieldDef;
|
|
2219
|
-
this.findFanPrefexes(parent);
|
|
2220
|
-
}
|
|
2221
|
-
// we want to generate a different query for each
|
|
2222
|
-
// nested structure so we don't do a crazy cross product.
|
|
2223
|
-
findFanPrefexes(qs) {
|
|
2224
|
-
for (const [_name, f] of qs.nameMap) {
|
|
2225
|
-
if (f instanceof QueryStruct &&
|
|
2226
|
-
(f.fieldDef.structRelationship.type === "many" ||
|
|
2227
|
-
f.fieldDef.structRelationship.type === "nested")) {
|
|
2228
|
-
this.fanPrefixes.push(f.getFullOutputName());
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
2224
|
}
|
|
2232
2225
|
// get a field ref and expand it.
|
|
2233
2226
|
expandField(f) {
|
|
@@ -2238,13 +2231,7 @@ class QueryQueryIndex extends QueryQuery {
|
|
|
2238
2231
|
let resultIndex = 1;
|
|
2239
2232
|
const groupIndex = resultStruct.groupSet;
|
|
2240
2233
|
this.maxGroupSet = groupIndex;
|
|
2241
|
-
|
|
2242
|
-
let fieldNames = this.firstSegment.fields || [];
|
|
2243
|
-
if (fieldNames.length === 0) {
|
|
2244
|
-
fieldNames.push("**");
|
|
2245
|
-
}
|
|
2246
|
-
fieldNames = this.expandWildCards(fieldNames, (qf) => ["string", "number", "timestamp", "date"].indexOf(qf.fieldDef.type) !==
|
|
2247
|
-
-1);
|
|
2234
|
+
const fieldNames = this.firstSegment.fields || [];
|
|
2248
2235
|
for (const f of fieldNames) {
|
|
2249
2236
|
const { as, field } = this.expandField(f);
|
|
2250
2237
|
resultStruct.addField(as, field, {
|
|
@@ -2343,6 +2330,110 @@ class QueryQueryIndex extends QueryQuery {
|
|
|
2343
2330
|
FROM ${resultStage}\n`);
|
|
2344
2331
|
return this.resultStage;
|
|
2345
2332
|
}
|
|
2333
|
+
}
|
|
2334
|
+
class QueryQueryIndex extends QueryQuery {
|
|
2335
|
+
constructor(fieldDef, parent, stageWriter) {
|
|
2336
|
+
super(fieldDef, parent, stageWriter);
|
|
2337
|
+
this.rootFields = [];
|
|
2338
|
+
this.fanPrefixMap = {};
|
|
2339
|
+
this.fieldDef = fieldDef;
|
|
2340
|
+
this.findFanPrefexes(parent);
|
|
2341
|
+
}
|
|
2342
|
+
// we want to generate a different query for each
|
|
2343
|
+
// nested structure so we don't do a crazy cross product.
|
|
2344
|
+
findFanPrefexes(qs) {
|
|
2345
|
+
for (const [_name, f] of qs.nameMap) {
|
|
2346
|
+
if (f instanceof QueryStruct &&
|
|
2347
|
+
(f.fieldDef.structRelationship.type === "many" ||
|
|
2348
|
+
f.fieldDef.structRelationship.type === "nested") &&
|
|
2349
|
+
f.fieldDef.fields.length > 1 && // leave arrays in parent.
|
|
2350
|
+
this.parent.dialect.dontUnionIndex === false) {
|
|
2351
|
+
this.fanPrefixMap[f.getFullOutputName()] = [];
|
|
2352
|
+
this.findFanPrefexes(f);
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
expandIndexWildCards() {
|
|
2357
|
+
// if no fields were specified, look in the parent struct for strings.
|
|
2358
|
+
let fieldNames = this.firstSegment.fields || [];
|
|
2359
|
+
if (fieldNames.length === 0) {
|
|
2360
|
+
fieldNames.push("**");
|
|
2361
|
+
}
|
|
2362
|
+
fieldNames = this.expandWildCards(fieldNames, (qf) => ["string", "number", "timestamp", "date"].indexOf(qf.fieldDef.type) !==
|
|
2363
|
+
-1);
|
|
2364
|
+
return fieldNames;
|
|
2365
|
+
}
|
|
2366
|
+
// return the number of stages it is going to take to generate this index.
|
|
2367
|
+
getStageFields() {
|
|
2368
|
+
const s = [];
|
|
2369
|
+
if (this.rootFields.length > 0) {
|
|
2370
|
+
s.push(this.rootFields);
|
|
2371
|
+
}
|
|
2372
|
+
for (const fieldList of Object.values(this.fanPrefixMap)) {
|
|
2373
|
+
if (fieldList.length > 0) {
|
|
2374
|
+
s.push(fieldList);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
return s;
|
|
2378
|
+
}
|
|
2379
|
+
// Map fields into stages based on their level of repeated nesting
|
|
2380
|
+
//
|
|
2381
|
+
mapFieldsIntoStages(fieldNames) {
|
|
2382
|
+
// find all the fanned prefixes, longest ones first.
|
|
2383
|
+
const fannedPrefixes = Object.keys(this.fanPrefixMap).sort((k1, k2) => {
|
|
2384
|
+
if (k1.length < k2.length) {
|
|
2385
|
+
return 1;
|
|
2386
|
+
}
|
|
2387
|
+
if (k1.length > k2.length) {
|
|
2388
|
+
return -1;
|
|
2389
|
+
}
|
|
2390
|
+
return 0;
|
|
2391
|
+
});
|
|
2392
|
+
// Find the deepest fanned prefix
|
|
2393
|
+
for (const fn of fieldNames) {
|
|
2394
|
+
let found = false;
|
|
2395
|
+
for (const prefix of fannedPrefixes) {
|
|
2396
|
+
if (fn.startsWith(prefix)) {
|
|
2397
|
+
this.fanPrefixMap[prefix].push(fn);
|
|
2398
|
+
found = true;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
if (!found) {
|
|
2402
|
+
this.rootFields.push(fn);
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
expandFields(_resultStruct) {
|
|
2407
|
+
const fieldNames = this.expandIndexWildCards();
|
|
2408
|
+
this.mapFieldsIntoStages(fieldNames);
|
|
2409
|
+
}
|
|
2410
|
+
generateSQL(stageWriter) {
|
|
2411
|
+
const stages = this.getStageFields();
|
|
2412
|
+
const outputStageNames = [];
|
|
2413
|
+
for (const fields of stages) {
|
|
2414
|
+
const q = new QueryQueryIndexStage({
|
|
2415
|
+
...this.fieldDef,
|
|
2416
|
+
pipeline: [
|
|
2417
|
+
{
|
|
2418
|
+
...this.fieldDef.pipeline[0],
|
|
2419
|
+
fields: fields,
|
|
2420
|
+
},
|
|
2421
|
+
],
|
|
2422
|
+
}, this.parent, stageWriter);
|
|
2423
|
+
q.prepare(stageWriter);
|
|
2424
|
+
const lastStageName = q.generateSQL(stageWriter);
|
|
2425
|
+
outputStageNames.push(lastStageName);
|
|
2426
|
+
}
|
|
2427
|
+
if (outputStageNames.length === 1) {
|
|
2428
|
+
this.resultStage = outputStageNames[0];
|
|
2429
|
+
}
|
|
2430
|
+
else {
|
|
2431
|
+
this.resultStage = stageWriter.addStage(outputStageNames
|
|
2432
|
+
.map((n) => `SELECT * FROM ${n}\n`)
|
|
2433
|
+
.join(" UNION ALL \n"));
|
|
2434
|
+
}
|
|
2435
|
+
return this.resultStage;
|
|
2436
|
+
}
|
|
2346
2437
|
/** All Indexes have the same output schema */
|
|
2347
2438
|
getResultStructDef() {
|
|
2348
2439
|
return {
|
|
@@ -2499,7 +2590,7 @@ class QueryStruct extends QueryNode {
|
|
|
2499
2590
|
}
|
|
2500
2591
|
// if this is an inline object, include the parents alias.
|
|
2501
2592
|
if (this.fieldDef.structRelationship.type === "inline" && this.parent) {
|
|
2502
|
-
return this.parent.
|
|
2593
|
+
return this.parent.getSQLIdentifier() + "." + super.getIdentifier();
|
|
2503
2594
|
}
|
|
2504
2595
|
// we are somewhere in the join tree. Make sure the alias is unique.
|
|
2505
2596
|
return this.getAliasIdentifier();
|