@malloydata/malloy 0.0.248-dev250325232143 → 0.0.248-dev250326010711
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 +8 -2
- package/dist/dialect/dialect.js +6 -1
- package/dist/dialect/mysql/mysql.d.ts +2 -2
- package/dist/dialect/mysql/mysql.js +1 -5
- package/dist/dialect/standardsql/standardsql.d.ts +2 -1
- package/dist/dialect/standardsql/standardsql.js +6 -0
- package/dist/lang/ast/expressions/expr-filter-expr.js +0 -3
- package/dist/model/filter_compilers.d.ts +1 -1
- package/dist/model/filter_compilers.js +3 -0
- package/dist/model/malloy_query.js +13 -4
- package/dist/model/malloy_types.d.ts +1 -1
- package/package.json +4 -4
|
@@ -29,7 +29,8 @@ export type FieldReferenceType = 'table' | 'nest source' | 'array[scalar]' | 'ar
|
|
|
29
29
|
export declare const dayIndex: number;
|
|
30
30
|
export declare function inDays(units: string): boolean;
|
|
31
31
|
export declare function qtz(qi: QueryInfo): string | undefined;
|
|
32
|
-
export type OrderByClauseType = 'output_name' | 'ordinal';
|
|
32
|
+
export type OrderByClauseType = 'output_name' | 'ordinal' | 'expression';
|
|
33
|
+
export type OrderByRequest = 'query' | 'turtle' | 'analytical';
|
|
33
34
|
export declare abstract class Dialect {
|
|
34
35
|
abstract name: string;
|
|
35
36
|
abstract defaultNumberType: string;
|
|
@@ -121,7 +122,12 @@ export declare abstract class Dialect {
|
|
|
121
122
|
sqlSumDistinct(_key: string, _value: string, _funcName: string): string;
|
|
122
123
|
sqlAggDistinct(_key: string, _values: string[], _func: (valNames: string[]) => string): string;
|
|
123
124
|
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|
|
124
|
-
|
|
125
|
+
/**
|
|
126
|
+
* MySQL is NULLs first, all other dialects have a way to make NULLs last.
|
|
127
|
+
* isBaseOrdering is a hack to allow the MySQL dialect to partially implement
|
|
128
|
+
* NULLs last, but should go away once MySQL fully implements NULLs last.
|
|
129
|
+
*/
|
|
130
|
+
sqlOrderBy(orderTerms: string[], _orderFor?: OrderByRequest): string;
|
|
125
131
|
sqlTzStr(qi: QueryInfo): string;
|
|
126
132
|
sqlMakeUnnestKey(key: string, rowKey: string): string;
|
|
127
133
|
sqlStringAggDistinct(distinctKey: string, valueSQL: string, separatorSQL: string): string;
|
package/dist/dialect/dialect.js
CHANGED
|
@@ -179,7 +179,12 @@ class Dialect {
|
|
|
179
179
|
}
|
|
180
180
|
return tableSQL;
|
|
181
181
|
}
|
|
182
|
-
|
|
182
|
+
/**
|
|
183
|
+
* MySQL is NULLs first, all other dialects have a way to make NULLs last.
|
|
184
|
+
* isBaseOrdering is a hack to allow the MySQL dialect to partially implement
|
|
185
|
+
* NULLs last, but should go away once MySQL fully implements NULLs last.
|
|
186
|
+
*/
|
|
187
|
+
sqlOrderBy(orderTerms, _orderFor) {
|
|
183
188
|
return `ORDER BY ${orderTerms.join(',')}`;
|
|
184
189
|
}
|
|
185
190
|
sqlTzStr(qi) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Sampling, MeasureTimeExpr, TimeLiteralNode, RegexMatchExpr, TimeDeltaExpr, TimeTruncExpr, TimeExtractExpr, TypecastExpr, LeafAtomicTypeDef, AtomicTypeDef, ArrayLiteralNode, RecordLiteralNode } from '../../model/malloy_types';
|
|
2
|
-
import type { DialectFieldList, FieldReferenceType, QueryInfo } from '../dialect';
|
|
2
|
+
import type { DialectFieldList, FieldReferenceType, OrderByClauseType, QueryInfo } from '../dialect';
|
|
3
3
|
import { Dialect } from '../dialect';
|
|
4
4
|
import type { DialectFunctionOverloadDef } from '../functions';
|
|
5
5
|
export declare class MySQLDialect extends Dialect {
|
|
@@ -30,6 +30,7 @@ export declare class MySQLDialect extends Dialect {
|
|
|
30
30
|
supportsArraysInData: boolean;
|
|
31
31
|
compoundObjectInSchema: boolean;
|
|
32
32
|
booleanAsNumbers: boolean;
|
|
33
|
+
orderByClause: OrderByClauseType;
|
|
33
34
|
malloyTypeToSQLType(malloyType: AtomicTypeDef): string;
|
|
34
35
|
sqlTypeToMalloyType(sqlType: string): LeafAtomicTypeDef;
|
|
35
36
|
quoteTablePath(tablePath: string): string;
|
|
@@ -65,7 +66,6 @@ export declare class MySQLDialect extends Dialect {
|
|
|
65
66
|
sqlMeasureTimeExpr(df: MeasureTimeExpr): string;
|
|
66
67
|
sqlAggDistinct(_key: string, _values: string[], _func: (valNames: string[]) => string): string;
|
|
67
68
|
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|
|
68
|
-
sqlOrderBy(orderTerms: string[]): string;
|
|
69
69
|
sqlLiteralString(literal: string): string;
|
|
70
70
|
sqlLiteralRegexp(literal: string): string;
|
|
71
71
|
getDialectFunctionOverrides(): {
|
|
@@ -94,6 +94,7 @@ class MySQLDialect extends dialect_1.Dialect {
|
|
|
94
94
|
this.supportsArraysInData = false;
|
|
95
95
|
this.compoundObjectInSchema = false;
|
|
96
96
|
this.booleanAsNumbers = true;
|
|
97
|
+
this.orderByClause = 'ordinal';
|
|
97
98
|
}
|
|
98
99
|
malloyTypeToSQLType(malloyType) {
|
|
99
100
|
switch (malloyType.type) {
|
|
@@ -400,11 +401,6 @@ class MySQLDialect extends dialect_1.Dialect {
|
|
|
400
401
|
}
|
|
401
402
|
return tableSQL;
|
|
402
403
|
}
|
|
403
|
-
sqlOrderBy(orderTerms) {
|
|
404
|
-
return `ORDER BY ${orderTerms
|
|
405
|
-
.map(t => `${t.trim().slice(0, t.trim().lastIndexOf(' '))} IS NULL DESC, ${t}`)
|
|
406
|
-
.join(',')}`;
|
|
407
|
-
}
|
|
408
404
|
sqlLiteralString(literal) {
|
|
409
405
|
const noVirgule = literal.replace(/\\/g, '\\\\');
|
|
410
406
|
return "'" + noVirgule.replace(/'/g, "\\'") + "'";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Sampling, AtomicTypeDef, TimeTruncExpr, TimeExtractExpr, TimeDeltaExpr, TypecastExpr, RegexMatchExpr, TimeLiteralNode, MeasureTimeExpr, LeafAtomicTypeDef, RecordLiteralNode, ArrayLiteralNode } from '../../model/malloy_types';
|
|
2
2
|
import type { DialectFunctionOverloadDef } from '../functions';
|
|
3
|
-
import type { DialectFieldList, QueryInfo } from '../dialect';
|
|
3
|
+
import type { DialectFieldList, OrderByRequest, QueryInfo } from '../dialect';
|
|
4
4
|
import { Dialect } from '../dialect';
|
|
5
5
|
export declare class StandardSQLDialect extends Dialect {
|
|
6
6
|
name: string;
|
|
@@ -30,6 +30,7 @@ export declare class StandardSQLDialect extends Dialect {
|
|
|
30
30
|
quoteTablePath(tablePath: string): string;
|
|
31
31
|
sqlGroupSetTable(groupSetCount: number): string;
|
|
32
32
|
sqlAnyValue(groupSet: number, fieldName: string): string;
|
|
33
|
+
sqlOrderBy(orderTerms: string[], obr?: OrderByRequest): string;
|
|
33
34
|
sqlAggregateTurtle(groupSet: number, fieldList: DialectFieldList, orderBy: string | undefined, limit: number | undefined): string;
|
|
34
35
|
sqlAnyValueTurtle(groupSet: number, fieldList: DialectFieldList): string;
|
|
35
36
|
sqlAnyValueLastTurtle(name: string, groupSet: number, sqlName: string): string;
|
|
@@ -110,6 +110,12 @@ class StandardSQLDialect extends dialect_1.Dialect {
|
|
|
110
110
|
sqlAnyValue(groupSet, fieldName) {
|
|
111
111
|
return `ANY_VALUE(CASE WHEN group_set=${groupSet} THEN ${fieldName} END)`;
|
|
112
112
|
}
|
|
113
|
+
sqlOrderBy(orderTerms, obr) {
|
|
114
|
+
if (obr === 'analytical' || obr === 'turtle') {
|
|
115
|
+
return `ORDER BY ${orderTerms.join(',')}`;
|
|
116
|
+
}
|
|
117
|
+
return `ORDER BY ${orderTerms.map(t => `${t} NULLS LAST`).join(',')}`;
|
|
118
|
+
}
|
|
113
119
|
// can array agg or any_value a struct...
|
|
114
120
|
sqlAggregateTurtle(groupSet, fieldList, orderBy, limit) {
|
|
115
121
|
let tail = '';
|
|
@@ -58,9 +58,6 @@ class ExprFilterExpression extends expression_def_1.ExpressionDef {
|
|
|
58
58
|
return this.loggedErrorExpr('filter-expression-error', `Filter parse error: ${err.message}`);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
-
if (!fParse.parsed) {
|
|
62
|
-
return this.loggedErrorExpr('filter-expression-type', 'FJKLD:JDKSL: expression parsed to null');
|
|
63
|
-
}
|
|
64
61
|
const filterMatch = {
|
|
65
62
|
node: 'filterMatch',
|
|
66
63
|
dataType: matchExpr.type,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BooleanFilter, FilterExpression, NumberFilter, StringFilter, TemporalFilter } from '@malloydata/malloy-filter';
|
|
2
2
|
import type { Dialect } from '../dialect';
|
|
3
3
|
export declare const FilterCompilers: {
|
|
4
|
-
compile(t: string, c: FilterExpression, x: string, d: Dialect): string;
|
|
4
|
+
compile(t: string, c: FilterExpression | null, x: string, d: Dialect): string;
|
|
5
5
|
numberCompile(nc: NumberFilter, x: string, d: Dialect): string;
|
|
6
6
|
booleanCompile(bc: BooleanFilter, x: string, _d: Dialect): string;
|
|
7
7
|
stringCompile(sc: StringFilter, x: string, d: Dialect): string;
|
|
@@ -37,6 +37,9 @@ function unlike(disLiked, x) {
|
|
|
37
37
|
*/
|
|
38
38
|
exports.FilterCompilers = {
|
|
39
39
|
compile(t, c, x, d) {
|
|
40
|
+
if (c === null) {
|
|
41
|
+
return 'true';
|
|
42
|
+
}
|
|
40
43
|
if (t === 'string' && (0, malloy_filter_1.isStringFilter)(c)) {
|
|
41
44
|
return exports.FilterCompilers.stringCompile(c, x, d);
|
|
42
45
|
}
|
|
@@ -677,7 +677,7 @@ class QueryField extends QueryNode {
|
|
|
677
677
|
}
|
|
678
678
|
}
|
|
679
679
|
if (obSQL.length > 0) {
|
|
680
|
-
orderBy = ' ' + this.parent.dialect.sqlOrderBy(obSQL);
|
|
680
|
+
orderBy = ' ' + this.parent.dialect.sqlOrderBy(obSQL, 'analytical');
|
|
681
681
|
}
|
|
682
682
|
}
|
|
683
683
|
let between = '';
|
|
@@ -889,7 +889,7 @@ class QueryField extends QueryNode {
|
|
|
889
889
|
expr.dataType === 'date' ||
|
|
890
890
|
expr.dataType === 'timestamp' ||
|
|
891
891
|
expr.dataType === 'boolean') {
|
|
892
|
-
if ((0, malloy_filter_1.isFilterExpression)(expr.filter)) {
|
|
892
|
+
if (expr.filter === null || (0, malloy_filter_1.isFilterExpression)(expr.filter)) {
|
|
893
893
|
return filter_compilers_1.FilterCompilers.compile(expr.dataType, expr.filter, expr.e.sql || '', this.parent.dialect);
|
|
894
894
|
}
|
|
895
895
|
}
|
|
@@ -2249,6 +2249,10 @@ class QueryQuery extends QueryField {
|
|
|
2249
2249
|
else if (this.parent.dialect.orderByClause === 'output_name') {
|
|
2250
2250
|
o.push(`${this.parent.dialect.sqlMaybeQuoteIdentifier(f.field)} ${f.dir || 'ASC'}`);
|
|
2251
2251
|
}
|
|
2252
|
+
else if (this.parent.dialect.orderByClause === 'expression') {
|
|
2253
|
+
const fieldExpr = fi.getSQL();
|
|
2254
|
+
o.push(`${fieldExpr} ${f.dir || 'ASC'}`);
|
|
2255
|
+
}
|
|
2252
2256
|
}
|
|
2253
2257
|
else {
|
|
2254
2258
|
throw new Error(`Unknown field in ORDER BY ${f.field}`);
|
|
@@ -2262,10 +2266,15 @@ class QueryQuery extends QueryField {
|
|
|
2262
2266
|
const orderingField = resultStruct.getFieldByNumber(f.field);
|
|
2263
2267
|
o.push(`${this.parent.dialect.sqlMaybeQuoteIdentifier(orderingField.name)} ${f.dir || 'ASC'}`);
|
|
2264
2268
|
}
|
|
2269
|
+
else if (this.parent.dialect.orderByClause === 'expression') {
|
|
2270
|
+
const orderingField = resultStruct.getFieldByNumber(f.field);
|
|
2271
|
+
const fieldExpr = orderingField.fif.getSQL();
|
|
2272
|
+
o.push(`${fieldExpr} ${f.dir || 'ASC'}`);
|
|
2273
|
+
}
|
|
2265
2274
|
}
|
|
2266
2275
|
}
|
|
2267
2276
|
if (o.length > 0) {
|
|
2268
|
-
s = this.parent.dialect.sqlOrderBy(o) + '\n';
|
|
2277
|
+
s = this.parent.dialect.sqlOrderBy(o, 'query') + '\n';
|
|
2269
2278
|
}
|
|
2270
2279
|
return s;
|
|
2271
2280
|
}
|
|
@@ -2689,7 +2698,7 @@ class QueryQuery extends QueryField {
|
|
|
2689
2698
|
}
|
|
2690
2699
|
}
|
|
2691
2700
|
if (obSQL.length > 0) {
|
|
2692
|
-
orderBy = ' ' + this.parent.dialect.sqlOrderBy(obSQL);
|
|
2701
|
+
orderBy = ' ' + this.parent.dialect.sqlOrderBy(obSQL, 'turtle');
|
|
2693
2702
|
}
|
|
2694
2703
|
const dialectFieldList = this.buildDialectFieldList(resultStruct);
|
|
2695
2704
|
let resultType;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloydata/malloy",
|
|
3
|
-
"version": "0.0.248-
|
|
3
|
+
"version": "0.0.248-dev250326010711",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/index.js",
|
|
@@ -41,9 +41,9 @@
|
|
|
41
41
|
"generate-version-file": "VERSION=$(npm pkg get version --workspaces=false | tr -d \\\")\necho \"// generated with 'generate-version-file' script; do not edit manually\\nexport const MALLOY_VERSION = '$VERSION';\" > src/version.ts"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@malloydata/malloy-filter": "^0.0.248-
|
|
45
|
-
"@malloydata/malloy-interfaces": "^0.0.248-
|
|
46
|
-
"@malloydata/malloy-tag": "^0.0.248-
|
|
44
|
+
"@malloydata/malloy-filter": "^0.0.248-dev250326010711",
|
|
45
|
+
"@malloydata/malloy-interfaces": "^0.0.248-dev250326010711",
|
|
46
|
+
"@malloydata/malloy-tag": "^0.0.248-dev250326010711",
|
|
47
47
|
"antlr4ts": "^0.5.0-alpha.4",
|
|
48
48
|
"assert": "^2.0.0",
|
|
49
49
|
"jest-diff": "^29.6.2",
|