@malloydata/malloy 0.0.196-dev241007221852 → 0.0.196-dev241007232826
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 +3 -1
- package/dist/dialect/dialect.js +3 -0
- package/dist/dialect/dialect_map.js +2 -0
- package/dist/dialect/index.d.ts +1 -0
- package/dist/dialect/index.js +3 -1
- package/dist/dialect/mysql/dialect_functions.d.ts +2 -0
- package/dist/dialect/mysql/dialect_functions.js +51 -0
- package/dist/dialect/mysql/function_overrides.d.ts +2 -0
- package/dist/dialect/mysql/function_overrides.js +51 -0
- package/dist/dialect/mysql/index.d.ts +1 -0
- package/dist/dialect/mysql/index.js +24 -0
- package/dist/dialect/mysql/mysql.d.ts +78 -0
- package/dist/dialect/mysql/mysql.js +450 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -2
- package/dist/model/malloy_query.js +4 -1
- package/package.json +1 -1
|
@@ -59,6 +59,8 @@ export declare abstract class Dialect {
|
|
|
59
59
|
hasModOperator: boolean;
|
|
60
60
|
supportsLeftJoinUnnest: boolean;
|
|
61
61
|
supportsCountApprox: boolean;
|
|
62
|
+
supportsFullJoin: boolean;
|
|
63
|
+
nativeBoolean: boolean;
|
|
62
64
|
abstract getDialectFunctionOverrides(): {
|
|
63
65
|
[name: string]: DialectFunctionOverloadDef[];
|
|
64
66
|
};
|
|
@@ -76,7 +78,7 @@ export declare abstract class Dialect {
|
|
|
76
78
|
abstract sqlSumDistinctHashedKey(sqlDistinctKey: string): string;
|
|
77
79
|
abstract sqlGenerateUUID(): string;
|
|
78
80
|
abstract sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, isArray: boolean): string;
|
|
79
|
-
abstract sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string): string;
|
|
81
|
+
abstract sqlUnnestPipelineHead(isSingleton: boolean, sourceSQLExpression: string, fieldList?: DialectFieldList): string;
|
|
80
82
|
abstract sqlCreateFunction(id: string, funcText: string): string;
|
|
81
83
|
abstract sqlCreateFunctionCombineLastStage(lastStageName: string, fieldList: DialectFieldList): string;
|
|
82
84
|
abstract sqlCreateTableAsSelect(tableName: string, sql: string): string;
|
package/dist/dialect/dialect.js
CHANGED
|
@@ -81,6 +81,9 @@ class Dialect {
|
|
|
81
81
|
// can LEFT JOIN UNNEST
|
|
82
82
|
this.supportsLeftJoinUnnest = true;
|
|
83
83
|
this.supportsCountApprox = false;
|
|
84
|
+
// MYSQL doesn't have full join, maybe others.
|
|
85
|
+
this.supportsFullJoin = true;
|
|
86
|
+
this.nativeBoolean = true;
|
|
84
87
|
}
|
|
85
88
|
sqlFinalStage(_lastStageName, _fields) {
|
|
86
89
|
throw new Error('Dialect has no final Stage but called Anyway');
|
|
@@ -28,6 +28,7 @@ const postgres_1 = require("./postgres");
|
|
|
28
28
|
const snowflake_1 = require("./snowflake");
|
|
29
29
|
const standardsql_1 = require("./standardsql");
|
|
30
30
|
const trino_1 = require("./trino");
|
|
31
|
+
const mysql_1 = require("./mysql");
|
|
31
32
|
const dialectMap = new Map();
|
|
32
33
|
function getDialect(name) {
|
|
33
34
|
const d = dialectMap.get(name);
|
|
@@ -51,4 +52,5 @@ registerDialect(new duckdb_1.DuckDBDialect());
|
|
|
51
52
|
registerDialect(new snowflake_1.SnowflakeDialect());
|
|
52
53
|
registerDialect(new trino_1.TrinoDialect());
|
|
53
54
|
registerDialect(new trino_1.PrestoDialect());
|
|
55
|
+
registerDialect(new mysql_1.MySQLDialect());
|
|
54
56
|
//# sourceMappingURL=dialect_map.js.map
|
package/dist/dialect/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { PostgresDialect } from './postgres';
|
|
|
7
7
|
export { DuckDBDialect } from './duckdb';
|
|
8
8
|
export { SnowflakeDialect } from './snowflake';
|
|
9
9
|
export { TrinoDialect } from './trino';
|
|
10
|
+
export { MySQLDialect } from './mysql';
|
|
10
11
|
export { getDialect, registerDialect } from './dialect_map';
|
|
11
12
|
export { getMalloyStandardFunctions } from './functions';
|
|
12
13
|
export type { MalloyStandardFunctionImplementations } from './functions';
|
package/dist/dialect/index.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
exports.getMalloyStandardFunctions = exports.registerDialect = exports.getDialect = exports.TrinoDialect = exports.SnowflakeDialect = exports.DuckDBDialect = exports.PostgresDialect = exports.StandardSQLDialect = exports.qtz = exports.Dialect = exports.sql = exports.literal = exports.variadicParam = exports.param = exports.spread = exports.maxScalar = exports.minAggregate = exports.minScalar = exports.overload = exports.makeParam = exports.anyExprType = exports.arg = void 0;
|
|
25
|
+
exports.getMalloyStandardFunctions = exports.registerDialect = exports.getDialect = exports.MySQLDialect = exports.TrinoDialect = exports.SnowflakeDialect = exports.DuckDBDialect = exports.PostgresDialect = exports.StandardSQLDialect = exports.qtz = exports.Dialect = exports.sql = exports.literal = exports.variadicParam = exports.param = exports.spread = exports.maxScalar = exports.minAggregate = exports.minScalar = exports.overload = exports.makeParam = exports.anyExprType = exports.arg = void 0;
|
|
26
26
|
var util_1 = require("./functions/util");
|
|
27
27
|
Object.defineProperty(exports, "arg", { enumerable: true, get: function () { return util_1.arg; } });
|
|
28
28
|
Object.defineProperty(exports, "anyExprType", { enumerable: true, get: function () { return util_1.anyExprType; } });
|
|
@@ -49,6 +49,8 @@ var snowflake_1 = require("./snowflake");
|
|
|
49
49
|
Object.defineProperty(exports, "SnowflakeDialect", { enumerable: true, get: function () { return snowflake_1.SnowflakeDialect; } });
|
|
50
50
|
var trino_1 = require("./trino");
|
|
51
51
|
Object.defineProperty(exports, "TrinoDialect", { enumerable: true, get: function () { return trino_1.TrinoDialect; } });
|
|
52
|
+
var mysql_1 = require("./mysql");
|
|
53
|
+
Object.defineProperty(exports, "MySQLDialect", { enumerable: true, get: function () { return mysql_1.MySQLDialect; } });
|
|
52
54
|
var dialect_map_1 = require("./dialect_map");
|
|
53
55
|
Object.defineProperty(exports, "getDialect", { enumerable: true, get: function () { return dialect_map_1.getDialect; } });
|
|
54
56
|
Object.defineProperty(exports, "registerDialect", { enumerable: true, get: function () { return dialect_map_1.registerDialect; } });
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MYSQL_DIALECT_FUNCTIONS = void 0;
|
|
10
|
+
const string_agg = {
|
|
11
|
+
default_separator: {
|
|
12
|
+
takes: { 'value': { dimension: 'string' } },
|
|
13
|
+
returns: { measure: 'string' },
|
|
14
|
+
supportsOrderBy: true,
|
|
15
|
+
impl: { sql: 'GROUP_CONCAT(${value} ${order_by:})' },
|
|
16
|
+
},
|
|
17
|
+
with_separator: {
|
|
18
|
+
takes: {
|
|
19
|
+
'value': { dimension: 'string' },
|
|
20
|
+
'separator': { literal: 'string' },
|
|
21
|
+
},
|
|
22
|
+
returns: { measure: 'string' },
|
|
23
|
+
supportsOrderBy: true,
|
|
24
|
+
impl: { sql: 'GROUP_CONCAT(${value} ${order_by:} SEPARATOR ${separator})' },
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
const string_agg_distinct = {
|
|
28
|
+
default_separator: {
|
|
29
|
+
...string_agg['default_separator'],
|
|
30
|
+
isSymmetric: true,
|
|
31
|
+
supportsOrderBy: 'only_default',
|
|
32
|
+
impl: {
|
|
33
|
+
sql: 'GROUP_CONCAT(DISTINCT ${value} ${order_by:})',
|
|
34
|
+
defaultOrderByArgIndex: 0,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
with_separator: {
|
|
38
|
+
...string_agg['with_separator'],
|
|
39
|
+
isSymmetric: true,
|
|
40
|
+
supportsOrderBy: 'only_default',
|
|
41
|
+
impl: {
|
|
42
|
+
sql: 'GROUP_CONCAT(DISTINCT ${value} ${order_by:} SEPARATOR ${separator})',
|
|
43
|
+
defaultOrderByArgIndex: 0,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
exports.MYSQL_DIALECT_FUNCTIONS = {
|
|
48
|
+
string_agg,
|
|
49
|
+
string_agg_distinct,
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=dialect_functions.js.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.MYSQL_MALLOY_STANDARD_OVERLOADS = void 0;
|
|
10
|
+
exports.MYSQL_MALLOY_STANDARD_OVERLOADS = {
|
|
11
|
+
regexp_extract: { function: 'REGEXP_SUBSTR' },
|
|
12
|
+
replace: {
|
|
13
|
+
// In Postgres we specifically need to say that the replacement should be global.
|
|
14
|
+
regular_expression: {
|
|
15
|
+
sql: 'REGEXP_REPLACE(${value}, ${pattern}, ${replacement}, 1,0)',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
trunc: {
|
|
19
|
+
to_integer: {
|
|
20
|
+
sql: '(FLOOR(${value}) + IF(${value} < 0,1,0))',
|
|
21
|
+
},
|
|
22
|
+
to_precision: {
|
|
23
|
+
sql: '(ABS(FLOOR(${value} * POW(10,${precision}))/POW(10,${precision}))*IF(${value} < 0, -1, 1))',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
log: {
|
|
27
|
+
sql: 'log(${base},${value})',
|
|
28
|
+
},
|
|
29
|
+
div: { sql: 'FLOOR(${dividend} / ${divisor})' },
|
|
30
|
+
strpos: { sql: 'LOCATE(${search_string},${test_string})' },
|
|
31
|
+
starts_with: { sql: "COALESCE(${value} LIKE CONCAT(${prefix}, '%'),0)" },
|
|
32
|
+
ends_with: { sql: "COALESCE(${value} LIKE CONCAT('%',${suffix}),0)" },
|
|
33
|
+
trim: {
|
|
34
|
+
characters: {
|
|
35
|
+
sql: 'TRIM(BOTH ${trim_characters} FROM ${value})',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
ltrim: {
|
|
39
|
+
characters: {
|
|
40
|
+
sql: 'TRIM(LEADING ${trim_characters} FROM ${value})',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
rtrim: {
|
|
44
|
+
characters: {
|
|
45
|
+
sql: 'TRIM(TRAILING ${trim_characters} FROM ${value})',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
byte_length: { sql: '(LENGTH(CAST(${value} AS VARBINARY)))' },
|
|
49
|
+
chr: { sql: "CASE WHEN ${value} = 0 THEN '' ELSE CHR(${value}) END" },
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=function_overrides.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './mysql';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
__exportStar(require("./mysql"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Sampling, MeasureTimeExpr, TimeLiteralNode, RegexMatchExpr, TimeDeltaExpr, TimeTruncExpr, TimeExtractExpr, TypecastExpr, LeafAtomicDef, AtomicTypeDef } from '../../model/malloy_types';
|
|
2
|
+
import { Dialect, DialectFieldList, QueryInfo } from '../dialect';
|
|
3
|
+
import { DialectFunctionOverloadDef } from '../functions';
|
|
4
|
+
export declare class MySQLDialect extends Dialect {
|
|
5
|
+
name: string;
|
|
6
|
+
defaultNumberType: string;
|
|
7
|
+
defaultDecimalType: string;
|
|
8
|
+
udfPrefix: string;
|
|
9
|
+
hasFinalStage: boolean;
|
|
10
|
+
stringTypeName: string;
|
|
11
|
+
divisionIsInteger: boolean;
|
|
12
|
+
supportsSumDistinctFunction: boolean;
|
|
13
|
+
unnestWithNumbers: boolean;
|
|
14
|
+
defaultSampling: {
|
|
15
|
+
rows: number;
|
|
16
|
+
};
|
|
17
|
+
supportUnnestArrayAgg: boolean;
|
|
18
|
+
supportsAggDistinct: boolean;
|
|
19
|
+
supportsCTEinCoorelatedSubQueries: boolean;
|
|
20
|
+
supportsSafeCast: boolean;
|
|
21
|
+
dontUnionIndex: boolean;
|
|
22
|
+
supportsQualify: boolean;
|
|
23
|
+
supportsNesting: boolean;
|
|
24
|
+
experimental: boolean;
|
|
25
|
+
nativeBoolean: boolean;
|
|
26
|
+
supportsFullJoin: boolean;
|
|
27
|
+
supportsPipelinesInViews: boolean;
|
|
28
|
+
readsNestedData: boolean;
|
|
29
|
+
supportsComplexFilteredSources: boolean;
|
|
30
|
+
malloyTypeToSQLType(malloyType: AtomicTypeDef): string;
|
|
31
|
+
sqlTypeToMalloyType(sqlType: string): LeafAtomicDef;
|
|
32
|
+
quoteTablePath(tablePath: string): string;
|
|
33
|
+
sqlGroupSetTable(groupSetCount: number): string;
|
|
34
|
+
sqlAnyValue(_groupSet: number, fieldName: string): string;
|
|
35
|
+
private mapFields;
|
|
36
|
+
sqlAggregateTurtle(groupSet: number, fieldList: DialectFieldList, orderBy: string | undefined, limit: number | undefined): string;
|
|
37
|
+
sqlAnyValueTurtle(groupSet: number, fieldList: DialectFieldList): string;
|
|
38
|
+
sqlAnyValueLastTurtle(name: string, groupSet: number, sqlName: string): string;
|
|
39
|
+
sqlCoaleseMeasuresInline(groupSet: number, fieldList: DialectFieldList): string;
|
|
40
|
+
malloyToSQL(t: string): string;
|
|
41
|
+
unnestColumns(fieldList: DialectFieldList): string;
|
|
42
|
+
jsonTable(source: string, fieldList: DialectFieldList): string;
|
|
43
|
+
sqlUnnestAlias(source: string, alias: string, fieldList: DialectFieldList, _needDistinctKey: boolean, _isArray: boolean, _isInNestedPipeline: boolean): string;
|
|
44
|
+
sqlUnnestPipelineHead(_isSingleton: boolean, sourceSQLExpression: string, fieldList: DialectFieldList): string;
|
|
45
|
+
sqlSumDistinctHashedKey(_sqlDistinctKey: string): string;
|
|
46
|
+
sqlSumDistinct(key: string, value: string, funcName: string): string;
|
|
47
|
+
sqlGenerateUUID(): string;
|
|
48
|
+
sqlFieldReference(alias: string, fieldName: string, fieldType: string, isNested: boolean, _isArray: boolean): string;
|
|
49
|
+
sqlCreateFunction(id: string, funcText: string): string;
|
|
50
|
+
sqlCreateFunctionCombineLastStage(lastStageName: string): string;
|
|
51
|
+
sqlSelectAliasAsStruct(_alias: string, _fieldList: DialectFieldList): string;
|
|
52
|
+
sqlMaybeQuoteIdentifier(identifier: string): string;
|
|
53
|
+
sqlCreateTableAsSelect(_tableName: string, _sql: string): string;
|
|
54
|
+
sqlNowExpr(): string;
|
|
55
|
+
sqlTruncExpr(qi: QueryInfo, trunc: TimeTruncExpr): string;
|
|
56
|
+
truncToUnit(expr: string, units: string): string;
|
|
57
|
+
sqlTimeExtractExpr(qi: QueryInfo, te: TimeExtractExpr): string;
|
|
58
|
+
sqlAlterTimeExpr(df: TimeDeltaExpr): string;
|
|
59
|
+
sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
|
|
60
|
+
sqlRegexpMatch(df: RegexMatchExpr): string;
|
|
61
|
+
sqlLiteralTime(qi: QueryInfo, lt: TimeLiteralNode): string;
|
|
62
|
+
sqlMeasureTimeExpr(df: MeasureTimeExpr): string;
|
|
63
|
+
sqlAggDistinct(_key: string, _values: string[], _func: (valNames: string[]) => string): string;
|
|
64
|
+
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|
|
65
|
+
sqlOrderBy(orderTerms: string[]): string;
|
|
66
|
+
sqlLiteralString(literal: string): string;
|
|
67
|
+
sqlLiteralRegexp(literal: string): string;
|
|
68
|
+
getDialectFunctionOverrides(): {
|
|
69
|
+
[name: string]: DialectFunctionOverloadDef[];
|
|
70
|
+
};
|
|
71
|
+
getDialectFunctions(): {
|
|
72
|
+
[name: string]: DialectFunctionOverloadDef[];
|
|
73
|
+
};
|
|
74
|
+
mapFieldsForJsonObject(fieldList: DialectFieldList, nullValues?: boolean): string;
|
|
75
|
+
castToString(expression: string): string;
|
|
76
|
+
concat(...values: string[]): string;
|
|
77
|
+
validateTypeName(sqlType: string): boolean;
|
|
78
|
+
}
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
*
|
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
* a copy of this software and associated documentation files
|
|
7
|
+
* (the "Software"), to deal in the Software without restriction,
|
|
8
|
+
* including without limitation the rights to use, copy, modify, merge,
|
|
9
|
+
* publish, distribute, sublicense, and/or sell copies of the Software,
|
|
10
|
+
* and to permit persons to whom the Software is furnished to do so,
|
|
11
|
+
* subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be
|
|
14
|
+
* included in all copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.MySQLDialect = void 0;
|
|
26
|
+
// import {
|
|
27
|
+
// Dialect,
|
|
28
|
+
// DialectFieldList,
|
|
29
|
+
// QueryInfo,
|
|
30
|
+
// qtz,
|
|
31
|
+
// DialectFunctionOverloadDef,
|
|
32
|
+
// } from '..';
|
|
33
|
+
const malloy_types_1 = require("../../model/malloy_types");
|
|
34
|
+
const utils_1 = require("../../model/utils");
|
|
35
|
+
const dialect_1 = require("../dialect");
|
|
36
|
+
const functions_1 = require("../functions");
|
|
37
|
+
const dialect_functions_1 = require("./dialect_functions");
|
|
38
|
+
const function_overrides_1 = require("./function_overrides");
|
|
39
|
+
const castMap = {
|
|
40
|
+
number: 'double precision',
|
|
41
|
+
string: 'varchar(255)',
|
|
42
|
+
};
|
|
43
|
+
const msExtractionMap = {
|
|
44
|
+
day_of_week: 'DAYOFWEEK',
|
|
45
|
+
day_of_year: 'DAYOFYEAR',
|
|
46
|
+
};
|
|
47
|
+
const inSeconds = {
|
|
48
|
+
second: 1,
|
|
49
|
+
minute: 60,
|
|
50
|
+
hour: 3600,
|
|
51
|
+
day: 24 * 3600,
|
|
52
|
+
week: 7 * 24 * 3600,
|
|
53
|
+
};
|
|
54
|
+
const mysqlToMalloyTypes = {
|
|
55
|
+
// TODO: This assumes tinyint is always going to be a boolean.
|
|
56
|
+
'tinyint': { type: 'boolean' },
|
|
57
|
+
'smallint': { type: 'number', numberType: 'integer' },
|
|
58
|
+
'mediumint': { type: 'number', numberType: 'integer' },
|
|
59
|
+
'int': { type: 'number', numberType: 'integer' },
|
|
60
|
+
'bigint': { type: 'number', numberType: 'integer' },
|
|
61
|
+
'tinyint unsigned': { type: 'number', numberType: 'integer' },
|
|
62
|
+
'smallint unsigned': { type: 'number', numberType: 'integer' },
|
|
63
|
+
'mediumint unsigned': { type: 'number', numberType: 'integer' },
|
|
64
|
+
'int unsigned': { type: 'number', numberType: 'integer' },
|
|
65
|
+
'bigint unsigned': { type: 'number', numberType: 'integer' },
|
|
66
|
+
'double': { type: 'number', numberType: 'float' },
|
|
67
|
+
'varchar': { type: 'string' },
|
|
68
|
+
'varbinary': { type: 'string' },
|
|
69
|
+
'char': { type: 'string' },
|
|
70
|
+
'text': { type: 'string' },
|
|
71
|
+
'date': { type: 'date' },
|
|
72
|
+
'datetime': { type: 'timestamp' },
|
|
73
|
+
'timestamp': { type: 'timestamp' },
|
|
74
|
+
'time': { type: 'string' },
|
|
75
|
+
'decimal': { type: 'number', numberType: 'float' },
|
|
76
|
+
// TODO: Check if we need special handling for boolean.
|
|
77
|
+
'tinyint(1)': { type: 'boolean' },
|
|
78
|
+
};
|
|
79
|
+
class MySQLDialect extends dialect_1.Dialect {
|
|
80
|
+
constructor() {
|
|
81
|
+
super(...arguments);
|
|
82
|
+
this.name = 'mysql';
|
|
83
|
+
this.defaultNumberType = 'DOUBLE PRECISION';
|
|
84
|
+
this.defaultDecimalType = 'DECIMAL';
|
|
85
|
+
this.udfPrefix = 'ms_temp.__udf';
|
|
86
|
+
this.hasFinalStage = false;
|
|
87
|
+
// TODO: this may not be enough for lager casts.
|
|
88
|
+
this.stringTypeName = 'VARCHAR(255)';
|
|
89
|
+
this.divisionIsInteger = true;
|
|
90
|
+
this.supportsSumDistinctFunction = true;
|
|
91
|
+
this.unnestWithNumbers = false;
|
|
92
|
+
this.defaultSampling = { rows: 50000 };
|
|
93
|
+
this.supportUnnestArrayAgg = true;
|
|
94
|
+
this.supportsAggDistinct = true;
|
|
95
|
+
this.supportsCTEinCoorelatedSubQueries = true;
|
|
96
|
+
this.supportsSafeCast = false;
|
|
97
|
+
this.dontUnionIndex = false;
|
|
98
|
+
this.supportsQualify = false;
|
|
99
|
+
this.supportsNesting = true;
|
|
100
|
+
this.experimental = true;
|
|
101
|
+
this.nativeBoolean = false;
|
|
102
|
+
this.supportsFullJoin = false;
|
|
103
|
+
this.supportsPipelinesInViews = false;
|
|
104
|
+
this.readsNestedData = false;
|
|
105
|
+
this.supportsComplexFilteredSources = false;
|
|
106
|
+
}
|
|
107
|
+
malloyTypeToSQLType(malloyType) {
|
|
108
|
+
if (malloyType.type === 'number') {
|
|
109
|
+
if (malloyType.numberType === 'integer') {
|
|
110
|
+
return 'BIGINT';
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
return 'DOUBLE';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return malloyType.type;
|
|
117
|
+
}
|
|
118
|
+
sqlTypeToMalloyType(sqlType) {
|
|
119
|
+
var _a, _b;
|
|
120
|
+
// Remove trailing params
|
|
121
|
+
const baseSqlType = (_b = (_a = sqlType.match(/^(\w+)/)) === null || _a === void 0 ? void 0 : _a.at(0)) !== null && _b !== void 0 ? _b : sqlType;
|
|
122
|
+
return (mysqlToMalloyTypes[baseSqlType.toLowerCase()] || {
|
|
123
|
+
type: 'sql native',
|
|
124
|
+
rawType: baseSqlType,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
quoteTablePath(tablePath) {
|
|
128
|
+
return tablePath
|
|
129
|
+
.split('.')
|
|
130
|
+
.map(part => `\`${part}\``)
|
|
131
|
+
.join('.');
|
|
132
|
+
}
|
|
133
|
+
sqlGroupSetTable(groupSetCount) {
|
|
134
|
+
return `CROSS JOIN (select number - 1 as group_set from JSON_TABLE(cast(concat("[1", repeat(",1", ${groupSetCount}), "]") as JSON),"$[*]" COLUMNS(number FOR ORDINALITY)) group_set) as group_set`;
|
|
135
|
+
}
|
|
136
|
+
sqlAnyValue(_groupSet, fieldName) {
|
|
137
|
+
return `MAX(${fieldName})`;
|
|
138
|
+
}
|
|
139
|
+
mapFields(fieldList) {
|
|
140
|
+
return fieldList.map(f => `"${f.rawName}", ${f.sqlExpression}`).join(', ');
|
|
141
|
+
}
|
|
142
|
+
sqlAggregateTurtle(groupSet, fieldList, orderBy, limit) {
|
|
143
|
+
const separator = limit ? ',xrmmex' : ',';
|
|
144
|
+
let gc = `GROUP_CONCAT(
|
|
145
|
+
IF(group_set=${groupSet},
|
|
146
|
+
JSON_OBJECT(${this.mapFields(fieldList)})
|
|
147
|
+
, null
|
|
148
|
+
)
|
|
149
|
+
${orderBy}
|
|
150
|
+
SEPARATOR '${separator}'
|
|
151
|
+
)`;
|
|
152
|
+
if (limit) {
|
|
153
|
+
gc = `SUBSTRING_INDEX(${gc}, '${separator}', ${limit})`;
|
|
154
|
+
gc = `REPLACE(${gc},'${separator}',',')`;
|
|
155
|
+
}
|
|
156
|
+
gc = `JSON_EXTRACT(CONCAT('[',${gc},']'),'$')`;
|
|
157
|
+
return gc;
|
|
158
|
+
}
|
|
159
|
+
sqlAnyValueTurtle(groupSet, fieldList) {
|
|
160
|
+
const fields = this.mapFieldsForJsonObject(fieldList);
|
|
161
|
+
return `MAX(CASE WHEN group_set=${groupSet} THEN JSON_OBJECT(${fields}) END)`;
|
|
162
|
+
}
|
|
163
|
+
sqlAnyValueLastTurtle(name, groupSet, sqlName) {
|
|
164
|
+
return `MAX(CASE WHEN group_set=${groupSet} AND ${name} IS NOT NULL THEN ${name} END) as ${sqlName}`;
|
|
165
|
+
}
|
|
166
|
+
sqlCoaleseMeasuresInline(groupSet, fieldList) {
|
|
167
|
+
const fields = this.mapFieldsForJsonObject(fieldList);
|
|
168
|
+
const nullValues = this.mapFieldsForJsonObject(fieldList, true);
|
|
169
|
+
return `COALESCE(MAX(CASE WHEN group_set=${groupSet} THEN JSON_OBJECT(${fields}) END),JSON_OBJECT(${nullValues}))`;
|
|
170
|
+
}
|
|
171
|
+
malloyToSQL(t) {
|
|
172
|
+
if (t === 'number') {
|
|
173
|
+
return 'DOUBLE';
|
|
174
|
+
}
|
|
175
|
+
else if (t === 'string') {
|
|
176
|
+
return 'TEXT';
|
|
177
|
+
}
|
|
178
|
+
else if (t === 'struct') {
|
|
179
|
+
return 'JSON';
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
return t;
|
|
183
|
+
}
|
|
184
|
+
unnestColumns(fieldList) {
|
|
185
|
+
const fields = [];
|
|
186
|
+
for (const f of fieldList) {
|
|
187
|
+
fields.push(`${this.sqlMaybeQuoteIdentifier(f.sqlOutputName)} ${this.malloyToSQL(f.type)} PATH "$.${f.rawName}"`);
|
|
188
|
+
}
|
|
189
|
+
return fields.join(',\n');
|
|
190
|
+
}
|
|
191
|
+
jsonTable(source, fieldList) {
|
|
192
|
+
return `JSON_TABLE(${source}, '$[*]'
|
|
193
|
+
COLUMNS (
|
|
194
|
+
__row_id FOR ORDINALITY,
|
|
195
|
+
${this.unnestColumns(fieldList)}
|
|
196
|
+
)
|
|
197
|
+
)`;
|
|
198
|
+
}
|
|
199
|
+
// LTNOTE: We'll make this work with Arrays once MToy's changes land.
|
|
200
|
+
sqlUnnestAlias(source, alias, fieldList, _needDistinctKey, _isArray, _isInNestedPipeline) {
|
|
201
|
+
return `
|
|
202
|
+
LEFT JOIN ${this.jsonTable(source, fieldList)} as ${alias} ON 1=1`;
|
|
203
|
+
}
|
|
204
|
+
sqlUnnestPipelineHead(_isSingleton, sourceSQLExpression, fieldList) {
|
|
205
|
+
return this.jsonTable(sourceSQLExpression, fieldList);
|
|
206
|
+
}
|
|
207
|
+
sqlSumDistinctHashedKey(_sqlDistinctKey) {
|
|
208
|
+
return 'UNUSED';
|
|
209
|
+
}
|
|
210
|
+
sqlSumDistinct(key, value, funcName) {
|
|
211
|
+
const sqlDistinctKey = `CONCAT(${key}, '')`;
|
|
212
|
+
const upperPart = `CAST(CONV(SUBSTRING(MD5(${sqlDistinctKey}), 1, 16), 16, 10) AS DECIMAL(65, 0)) * 4294967296`;
|
|
213
|
+
const lowerPart = `CAST(CONV(SUBSTRING(MD5(${sqlDistinctKey}), 16, 8), 16, 10) AS DECIMAL(65, 0))`;
|
|
214
|
+
const hashkey = `(${upperPart} + ${lowerPart})`;
|
|
215
|
+
const v = `COALESCE(${value},0)`;
|
|
216
|
+
const sqlSum = `(SUM(DISTINCT ${hashkey} + ${v}) - SUM(DISTINCT ${hashkey}))`;
|
|
217
|
+
if (funcName === 'SUM') {
|
|
218
|
+
return sqlSum;
|
|
219
|
+
}
|
|
220
|
+
else if (funcName === 'AVG') {
|
|
221
|
+
return `(${sqlSum})/NULLIF(COUNT(DISTINCT CASE WHEN ${value} IS NOT NULL THEN ${key} END),0)`;
|
|
222
|
+
}
|
|
223
|
+
throw new Error(`Unknown Symmetric Aggregate function ${funcName}`);
|
|
224
|
+
}
|
|
225
|
+
sqlGenerateUUID() {
|
|
226
|
+
// TODO: This causes the query to become slow, figure out another way to make UUID deterministic.
|
|
227
|
+
return 'CONCAT(ROW_NUMBER() OVER(), UUID())';
|
|
228
|
+
}
|
|
229
|
+
sqlFieldReference(alias, fieldName, fieldType, isNested, _isArray) {
|
|
230
|
+
let ret = `${alias}.\`${fieldName}\``;
|
|
231
|
+
if (isNested) {
|
|
232
|
+
switch (fieldType) {
|
|
233
|
+
case 'string':
|
|
234
|
+
ret = `CONCAT(${ret}, '')`;
|
|
235
|
+
break;
|
|
236
|
+
// TODO: Fix this.
|
|
237
|
+
case 'number':
|
|
238
|
+
ret = `CAST(${ret} as double)`;
|
|
239
|
+
break;
|
|
240
|
+
case 'struct':
|
|
241
|
+
ret = `CAST(${ret} as JSON)`;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
return ret;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
return `${alias}.\`${fieldName}\``;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
sqlCreateFunction(id, funcText) {
|
|
251
|
+
// TODO:
|
|
252
|
+
return `CREATE FUNCTION ${id}(JSONB) RETURNS JSONB AS $$\n${(0, utils_1.indent)(funcText)}\n$$ LANGUAGE SQL;\n`;
|
|
253
|
+
}
|
|
254
|
+
sqlCreateFunctionCombineLastStage(lastStageName) {
|
|
255
|
+
// TODO:
|
|
256
|
+
return `SELECT ARRAY((SELECT AS STRUCT * FROM ${lastStageName}))\n`;
|
|
257
|
+
}
|
|
258
|
+
sqlSelectAliasAsStruct(_alias, _fieldList) {
|
|
259
|
+
return 'MYSQL: Implement this';
|
|
260
|
+
// return `JSON_OBJECT(${physicalFieldNames
|
|
261
|
+
// .map(name => `'${name.replace(/`/g, '')}', \`${alias}\`.${name}`)
|
|
262
|
+
// .join(',')})`;
|
|
263
|
+
}
|
|
264
|
+
sqlMaybeQuoteIdentifier(identifier) {
|
|
265
|
+
return `\`${identifier}\``;
|
|
266
|
+
}
|
|
267
|
+
// TODO: Check what this is.
|
|
268
|
+
sqlCreateTableAsSelect(_tableName, _sql) {
|
|
269
|
+
throw new Error('Not implemented Yet');
|
|
270
|
+
}
|
|
271
|
+
sqlNowExpr() {
|
|
272
|
+
return 'LOCALTIMESTAMP';
|
|
273
|
+
}
|
|
274
|
+
// truncToUnit(sql, unit: string): string {
|
|
275
|
+
// return `EXTRACT(${unit} FROM ${sql})`;
|
|
276
|
+
// }
|
|
277
|
+
sqlTruncExpr(qi, trunc) {
|
|
278
|
+
// LTNOTE: how come this can be undefined?
|
|
279
|
+
let truncThis = trunc.e.sql || 'why could this be undefined';
|
|
280
|
+
if (trunc.units === 'week') {
|
|
281
|
+
truncThis = `DATE_SUB(${truncThis}, INTERVAL DAYOFWEEK(${truncThis}) - 1 DAY)`;
|
|
282
|
+
}
|
|
283
|
+
if (trunc.e.dataType === 'timestamp') {
|
|
284
|
+
const tz = (0, dialect_1.qtz)(qi);
|
|
285
|
+
if (tz) {
|
|
286
|
+
const civilSource = `(CONVERT_TZ(${truncThis}, 'UTC','${tz}'))`;
|
|
287
|
+
const civilTrunc = `${this.truncToUnit(civilSource, trunc.units)}`;
|
|
288
|
+
const truncTsTz = `CONVERT_TZ(${civilTrunc}, '${tz}', 'UTC')`;
|
|
289
|
+
return `(${truncTsTz})`; // TODO: should it cast?
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
const result = `${this.truncToUnit(truncThis, trunc.units)}`;
|
|
293
|
+
return result;
|
|
294
|
+
}
|
|
295
|
+
truncToUnit(expr, units) {
|
|
296
|
+
let format = "'%Y-%m-%d %H:%i:%s'";
|
|
297
|
+
switch (units) {
|
|
298
|
+
case 'minute':
|
|
299
|
+
format = "'%Y-%m-%d %H:%i:00'";
|
|
300
|
+
break;
|
|
301
|
+
case 'hour':
|
|
302
|
+
format = "'%Y-%m-%d %H:00:00'";
|
|
303
|
+
break;
|
|
304
|
+
case 'day':
|
|
305
|
+
case 'week':
|
|
306
|
+
format = "'%Y-%m-%d 00:00:00'";
|
|
307
|
+
break;
|
|
308
|
+
case 'month':
|
|
309
|
+
format = "'%Y-%m-01 00:00:00'";
|
|
310
|
+
break;
|
|
311
|
+
case 'quarter':
|
|
312
|
+
format = `CASE WHEN MONTH(${expr}) > 9 THEN '%Y-10-01 00:00:00' WHEN MONTH(${expr}) > 6 THEN '%Y-07-01 00:00:00' WHEN MONTH(${expr}) > 3 THEN '%Y-04-01 00:00:00' ELSE '%Y-01-01 00:00:00' end`;
|
|
313
|
+
break;
|
|
314
|
+
case 'year':
|
|
315
|
+
format = "'%Y-01-01 00:00:00'";
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
return `TIMESTAMP(DATE_FORMAT(${expr}, ${format}))`;
|
|
319
|
+
}
|
|
320
|
+
sqlTimeExtractExpr(qi, te) {
|
|
321
|
+
const msUnits = msExtractionMap[te.units] || te.units;
|
|
322
|
+
let extractFrom = te.e.sql;
|
|
323
|
+
if (te.e.dataType === 'timestamp') {
|
|
324
|
+
const tz = (0, dialect_1.qtz)(qi);
|
|
325
|
+
if (tz) {
|
|
326
|
+
extractFrom = `CONVERT_TZ(${extractFrom}, 'UTC', '${tz}')`;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return `${msUnits}(${extractFrom})`;
|
|
330
|
+
}
|
|
331
|
+
sqlAlterTimeExpr(df) {
|
|
332
|
+
let timeframe = df.units;
|
|
333
|
+
let n = df.kids.delta.sql;
|
|
334
|
+
if (timeframe === 'quarter') {
|
|
335
|
+
timeframe = 'month';
|
|
336
|
+
n = `${n}*3`;
|
|
337
|
+
}
|
|
338
|
+
else if (timeframe === 'week') {
|
|
339
|
+
timeframe = 'day';
|
|
340
|
+
n = `${n}*7`;
|
|
341
|
+
}
|
|
342
|
+
const interval = `INTERVAL ${n} ${timeframe} `;
|
|
343
|
+
return `(${df.kids.base.sql})${df.op}${interval}`;
|
|
344
|
+
}
|
|
345
|
+
sqlCast(qi, cast) {
|
|
346
|
+
const op = `${cast.srcType}::${cast.dstType}`;
|
|
347
|
+
const tz = (0, dialect_1.qtz)(qi);
|
|
348
|
+
if (op === 'timestamp::date' && tz) {
|
|
349
|
+
return `CAST(CONVERT_TZ(${cast.e.sql}, 'UTC', '${tz}') AS DATE) `;
|
|
350
|
+
}
|
|
351
|
+
else if (op === 'date::timestamp' && tz) {
|
|
352
|
+
return ` CONVERT_TZ(${cast.e.sql}, '${tz}', 'UTC')`;
|
|
353
|
+
}
|
|
354
|
+
if (cast.srcType !== cast.dstType) {
|
|
355
|
+
const dstType = typeof cast.dstType === 'string'
|
|
356
|
+
? castMap[cast.dstType]
|
|
357
|
+
: cast.dstType.raw;
|
|
358
|
+
if (cast.safe) {
|
|
359
|
+
throw new Error("Mysql dialect doesn't support Safe Cast");
|
|
360
|
+
}
|
|
361
|
+
if (cast.dstType === 'string') {
|
|
362
|
+
return `CONCAT(${cast.e.sql}, '')`;
|
|
363
|
+
}
|
|
364
|
+
return `CAST(${cast.e.sql} AS ${dstType})`;
|
|
365
|
+
}
|
|
366
|
+
// LTNOTE: I don't understand how this could be undefined.
|
|
367
|
+
return cast.e.sql || 'weirdly undefined';
|
|
368
|
+
}
|
|
369
|
+
sqlRegexpMatch(df) {
|
|
370
|
+
return `REGEXP_LIKE(${df.kids.expr.sql}, ${df.kids.regex.sql})`;
|
|
371
|
+
}
|
|
372
|
+
sqlLiteralTime(qi, lt) {
|
|
373
|
+
if (lt.dataType === 'date') {
|
|
374
|
+
return `DATE '${lt.literal}'`;
|
|
375
|
+
}
|
|
376
|
+
const tz = lt.timezone || (0, dialect_1.qtz)(qi);
|
|
377
|
+
if (tz) {
|
|
378
|
+
return ` CONVERT_TZ('${lt.literal}', '${tz}', 'UTC')`;
|
|
379
|
+
}
|
|
380
|
+
return `TIMESTAMP '${lt.literal}'`;
|
|
381
|
+
}
|
|
382
|
+
sqlMeasureTimeExpr(df) {
|
|
383
|
+
let lVal = df.kids.left.sql;
|
|
384
|
+
let rVal = df.kids.right.sql;
|
|
385
|
+
if (inSeconds[df.units]) {
|
|
386
|
+
lVal = `UNIX_TIMESTAMP(${lVal})`;
|
|
387
|
+
rVal = `UNIX_TIMESTAMP(${rVal})`;
|
|
388
|
+
const duration = `${rVal}-${lVal}`;
|
|
389
|
+
return df.units === 'second'
|
|
390
|
+
? `FLOOR(${duration})`
|
|
391
|
+
: `FLOOR((${duration})/${inSeconds[df.units].toString()}.0)`;
|
|
392
|
+
}
|
|
393
|
+
throw new Error(`Unknown or unhandled MySQL time unit: ${df.units}`);
|
|
394
|
+
}
|
|
395
|
+
sqlAggDistinct(_key, _values, _func) {
|
|
396
|
+
throw new Error('MySQL dialect does not support nesting.');
|
|
397
|
+
}
|
|
398
|
+
sqlSampleTable(tableSQL, sample) {
|
|
399
|
+
if (sample !== undefined) {
|
|
400
|
+
if ((0, malloy_types_1.isSamplingEnable)(sample) && sample.enable) {
|
|
401
|
+
sample = this.defaultSampling;
|
|
402
|
+
}
|
|
403
|
+
if ((0, malloy_types_1.isSamplingRows)(sample)) {
|
|
404
|
+
return `(SELECT * FROM ${tableSQL} ORDER BY rand() LIMIT ${sample.rows} )`;
|
|
405
|
+
}
|
|
406
|
+
else if ((0, malloy_types_1.isSamplingPercent)(sample)) {
|
|
407
|
+
return `(SELECT * FROM (SELECT ROW_NUMBER() OVER (ORDER BY rand()) as __row_number, __source_tbl.* from ${tableSQL} as __source_tbl) as __rand_tbl where __row_number % FLOOR(100.0 / ${sample.percent}) = 1)`;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return tableSQL;
|
|
411
|
+
}
|
|
412
|
+
sqlOrderBy(orderTerms) {
|
|
413
|
+
return `ORDER BY ${orderTerms
|
|
414
|
+
.map(t => `${t.trim().slice(0, t.trim().lastIndexOf(' '))} IS NULL DESC, ${t}`)
|
|
415
|
+
.join(',')}`;
|
|
416
|
+
}
|
|
417
|
+
sqlLiteralString(literal) {
|
|
418
|
+
const noVirgule = literal.replace(/\\/g, '\\\\');
|
|
419
|
+
return "'" + noVirgule.replace(/'/g, "\\'") + "'";
|
|
420
|
+
}
|
|
421
|
+
sqlLiteralRegexp(literal) {
|
|
422
|
+
return "'" + literal.replace(/'/g, "''") + "'";
|
|
423
|
+
}
|
|
424
|
+
getDialectFunctionOverrides() {
|
|
425
|
+
return (0, functions_1.expandOverrideMap)(function_overrides_1.MYSQL_MALLOY_STANDARD_OVERLOADS);
|
|
426
|
+
}
|
|
427
|
+
getDialectFunctions() {
|
|
428
|
+
return (0, functions_1.expandBlueprintMap)(dialect_functions_1.MYSQL_DIALECT_FUNCTIONS);
|
|
429
|
+
}
|
|
430
|
+
mapFieldsForJsonObject(fieldList, nullValues) {
|
|
431
|
+
return fieldList
|
|
432
|
+
.map(f => `${f.sqlOutputName.replace(/`/g, "'")}, ${nullValues ? 'NULL' : f.sqlExpression}\n`)
|
|
433
|
+
.join(', ');
|
|
434
|
+
}
|
|
435
|
+
castToString(expression) {
|
|
436
|
+
return `CONCAT(${expression}, '')`;
|
|
437
|
+
}
|
|
438
|
+
concat(...values) {
|
|
439
|
+
return `CONCAT(${values.join(',')})`;
|
|
440
|
+
}
|
|
441
|
+
validateTypeName(sqlType) {
|
|
442
|
+
// Letters: BIGINT
|
|
443
|
+
// Numbers: INT8
|
|
444
|
+
// Spaces,
|
|
445
|
+
// Parentheses, Commas: NUMERIC(5, 2)
|
|
446
|
+
return sqlType.match(/^[A-Za-z\s(),0-9]*$/) !== null;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
exports.MySQLDialect = MySQLDialect;
|
|
450
|
+
//# sourceMappingURL=mysql.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, } from './dialect';
|
|
1
|
+
export { DuckDBDialect, StandardSQLDialect, TrinoDialect, PostgresDialect, SnowflakeDialect, MySQLDialect, registerDialect, arg, qtz, overload, minScalar, anyExprType, minAggregate, maxScalar, sql, makeParam, param, variadicParam, literal, spread, Dialect, } from './dialect';
|
|
2
2
|
export type { DialectFieldList, DialectFunctionOverloadDef, QueryInfo, MalloyStandardFunctionImplementations, DefinitionBlueprint, DefinitionBlueprintMap, OverloadedDefinitionBlueprint, } from './dialect';
|
|
3
3
|
export type { QueryDataRow, StructDef, TableSourceDef, SQLSourceDef, SourceDef, JoinFieldDef, NamedSourceDefs as NamedStructDefs, MalloyQueryData, DateUnit, ExtractUnit, TimestampUnit, TemporalFieldType as TimeFieldType, QueryData, QueryValue, Expr, FilterCondition, SQLSentence, FieldDef, PipeSegment, QueryFieldDef, IndexFieldDef, TurtleDef, SearchValueMapResult, SearchIndexResult, ModelDef, Query, QueryResult, QueryRunStats, NamedQuery, NamedModelObject, ExpressionType, FunctionDef, FunctionOverloadDef, FunctionParameterDef, ExpressionValueType, TypeDesc, FieldValueType, ExpressionTypeDesc, FunctionParamTypeDesc, DocumentLocation, DocumentRange, DocumentPosition, Sampling, Annotation, LeafAtomicDef, AtomicTypeDef, AtomicFieldDef, JoinedArrayDef, JoinedArrayTypeDef, RecordTypeDef, RepeatedRecordTypeDef, } from './model';
|
|
4
4
|
export { arrayEachFields, isRepeatedRecord, isSourceDef, Segment, isSamplingEnable, isSamplingPercent, isSamplingRows, expressionIsCalculation, indent, composeSQLExpr, } from './model';
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.Tag = exports.toAsyncGenerator = exports.Explore = exports.DataWriter = exports.Parse = void 0;
|
|
3
|
+
exports.CSVWriter = exports.QueryMaterializer = exports.Result = exports.PreparedResult = exports.TimestampTimeframe = exports.DateTimeframe = exports.SourceRelationship = exports.JoinRelationship = exports.MalloyError = exports.FixedConnectionMap = exports.InMemoryURLReader = exports.EmptyURLReader = exports.SingleConnectionRuntime = exports.ConnectionRuntime = exports.AtomicFieldType = exports.Runtime = exports.Malloy = exports.Model = exports.MalloyTranslator = exports.composeSQLExpr = exports.indent = exports.expressionIsCalculation = exports.isSamplingRows = exports.isSamplingPercent = exports.isSamplingEnable = exports.Segment = exports.isSourceDef = exports.isRepeatedRecord = exports.arrayEachFields = exports.Dialect = exports.spread = exports.literal = exports.variadicParam = exports.param = exports.makeParam = exports.sql = exports.maxScalar = exports.minAggregate = exports.anyExprType = exports.minScalar = exports.overload = exports.qtz = exports.arg = exports.registerDialect = exports.MySQLDialect = exports.SnowflakeDialect = exports.PostgresDialect = exports.TrinoDialect = exports.StandardSQLDialect = exports.DuckDBDialect = void 0;
|
|
4
|
+
exports.Tag = exports.toAsyncGenerator = exports.Explore = exports.DataWriter = exports.Parse = exports.JSONWriter = void 0;
|
|
5
5
|
/*
|
|
6
6
|
* Copyright 2023 Google LLC
|
|
7
7
|
*
|
|
@@ -30,6 +30,7 @@ Object.defineProperty(exports, "StandardSQLDialect", { enumerable: true, get: fu
|
|
|
30
30
|
Object.defineProperty(exports, "TrinoDialect", { enumerable: true, get: function () { return dialect_1.TrinoDialect; } });
|
|
31
31
|
Object.defineProperty(exports, "PostgresDialect", { enumerable: true, get: function () { return dialect_1.PostgresDialect; } });
|
|
32
32
|
Object.defineProperty(exports, "SnowflakeDialect", { enumerable: true, get: function () { return dialect_1.SnowflakeDialect; } });
|
|
33
|
+
Object.defineProperty(exports, "MySQLDialect", { enumerable: true, get: function () { return dialect_1.MySQLDialect; } });
|
|
33
34
|
Object.defineProperty(exports, "registerDialect", { enumerable: true, get: function () { return dialect_1.registerDialect; } });
|
|
34
35
|
Object.defineProperty(exports, "arg", { enumerable: true, get: function () { return dialect_1.arg; } });
|
|
35
36
|
Object.defineProperty(exports, "qtz", { enumerable: true, get: function () { return dialect_1.qtz; } });
|
|
@@ -1990,6 +1990,9 @@ class QueryQuery extends QueryField {
|
|
|
1990
1990
|
if ((0, malloy_types_1.isJoinedSource)(qsDef)) {
|
|
1991
1991
|
let structSQL = qs.structSourceSQL(stageWriter);
|
|
1992
1992
|
const matrixOperation = (qsDef.matrixOperation || 'left').toUpperCase();
|
|
1993
|
+
if (!this.parent.dialect.supportsFullJoin && matrixOperation === 'FULL') {
|
|
1994
|
+
throw new Error('FULL JOIN not supported');
|
|
1995
|
+
}
|
|
1993
1996
|
if (ji.makeUniqueKey) {
|
|
1994
1997
|
const passKeys = this.generateSQLPassthroughKeys(qs);
|
|
1995
1998
|
structSQL = `(SELECT ${qs.dialect.sqlGenerateUUID()} as ${qs.dialect.sqlMaybeQuoteIdentifier('__distinct_key')}, x.* ${passKeys} FROM ${structSQL} as x)`;
|
|
@@ -2634,7 +2637,7 @@ class QueryQuery extends QueryField {
|
|
|
2634
2637
|
const inputStruct = {
|
|
2635
2638
|
type: 'nest_source',
|
|
2636
2639
|
name: '~pipe~',
|
|
2637
|
-
pipeSQL: this.parent.dialect.sqlUnnestPipelineHead(repeatedResultType === 'inline_all_numbers', sourceSQLExpression),
|
|
2640
|
+
pipeSQL: this.parent.dialect.sqlUnnestPipelineHead(repeatedResultType === 'inline_all_numbers', sourceSQLExpression, getDialectFieldList(structDef)),
|
|
2638
2641
|
fields: structDef.fields,
|
|
2639
2642
|
connection: structDef.connection,
|
|
2640
2643
|
dialect: structDef.dialect,
|