@malloydata/malloy 0.0.434 → 0.0.436
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/foundation/build_targets.d.ts +5 -6
- package/dist/api/foundation/build_targets.js +74 -6
- package/dist/api/foundation/compile.d.ts +0 -1
- package/dist/api/foundation/compile.js +0 -3
- package/dist/api/foundation/core.d.ts +16 -4
- package/dist/api/foundation/core.js +23 -23
- package/dist/api/foundation/index.d.ts +1 -1
- package/dist/api/foundation/runtime.d.ts +21 -3
- package/dist/api/foundation/runtime.js +45 -54
- package/dist/api/foundation/types.d.ts +43 -4
- package/dist/connection/dbmeta.d.ts +29 -0
- package/dist/connection/dbmeta.js +46 -0
- package/dist/connection/index.d.ts +1 -0
- package/dist/connection/index.js +1 -0
- package/dist/dialect/databricks/databricks.d.ts +11 -12
- package/dist/dialect/databricks/databricks.js +24 -36
- package/dist/dialect/dialect.d.ts +70 -171
- package/dist/dialect/dialect.js +123 -92
- package/dist/dialect/dialect_map.js +2 -0
- package/dist/dialect/duckdb/duckdb.d.ts +2 -2
- package/dist/dialect/duckdb/duckdb.js +1 -1
- package/dist/dialect/index.d.ts +3 -2
- package/dist/dialect/index.js +4 -2
- package/dist/dialect/mysql/mysql.d.ts +11 -12
- package/dist/dialect/mysql/mysql.js +20 -32
- package/dist/dialect/pg_impl.d.ts +9 -10
- package/dist/dialect/pg_impl.js +27 -73
- package/dist/dialect/postgres/postgres.d.ts +4 -4
- package/dist/dialect/postgres/postgres.js +4 -12
- package/dist/dialect/snowflake/snowflake.d.ts +11 -13
- package/dist/dialect/snowflake/snowflake.js +30 -82
- package/dist/dialect/sqlserver/dialect_functions.d.ts +2 -0
- package/dist/dialect/sqlserver/dialect_functions.js +42 -0
- package/dist/dialect/sqlserver/function_overrides.d.ts +2 -0
- package/dist/dialect/sqlserver/function_overrides.js +55 -0
- package/dist/dialect/sqlserver/index.d.ts +1 -0
- package/dist/dialect/sqlserver/index.js +22 -0
- package/dist/dialect/sqlserver/sqlserver.d.ts +101 -0
- package/dist/dialect/sqlserver/sqlserver.js +537 -0
- package/dist/dialect/sqlserver/windows_zones.d.ts +1 -0
- package/dist/dialect/sqlserver/windows_zones.js +613 -0
- package/dist/dialect/standardsql/standardsql.d.ts +11 -16
- package/dist/dialect/standardsql/standardsql.js +22 -73
- package/dist/dialect/trino/trino.d.ts +16 -18
- package/dist/dialect/trino/trino.js +127 -181
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -4
- package/dist/lang/ast/expressions/boolean-value.d.ts +24 -0
- package/dist/lang/ast/expressions/boolean-value.js +41 -0
- package/dist/lang/ast/expressions/case.js +7 -0
- package/dist/lang/ast/expressions/expr-alternation-tree.js +11 -0
- package/dist/lang/ast/expressions/expr-cast.js +5 -0
- package/dist/lang/ast/expressions/expr-coalesce.js +4 -0
- package/dist/lang/ast/expressions/expr-func.js +13 -2
- package/dist/lang/ast/expressions/expr-minus.js +5 -2
- package/dist/lang/ast/expressions/expr-null.js +4 -0
- package/dist/lang/ast/expressions/pick-when.js +7 -0
- package/dist/lang/ast/field-space/index-field-space.js +13 -1
- package/dist/lang/ast/field-space/query-spaces.js +11 -0
- package/dist/lang/ast/query-builders/reduce-builder.js +1 -1
- package/dist/lang/ast/query-items/field-declaration.d.ts +5 -0
- package/dist/lang/ast/query-items/field-declaration.js +22 -16
- package/dist/lang/ast/query-items/field-references.d.ts +6 -0
- package/dist/lang/ast/query-items/field-references.js +23 -0
- package/dist/lang/ast/query-properties/filters.js +3 -1
- package/dist/lang/ast/source-elements/named-source.js +0 -2
- package/dist/lang/ast/source-elements/sql-source.js +0 -3
- package/dist/lang/ast/source-elements/table-source.js +1 -2
- package/dist/lang/ast/statements/import-statement.js +17 -0
- package/dist/lang/ast/types/expression-def.js +17 -2
- package/dist/lang/ast/types/malloy-element.d.ts +24 -8
- package/dist/lang/ast/types/malloy-element.js +63 -44
- package/dist/lang/ast/view-elements/reference-view.js +4 -0
- package/dist/lang/ast/view-elements/refine-utils.js +1 -0
- package/dist/lang/composite-source-utils.js +10 -17
- package/dist/lang/parse-log.d.ts +12 -0
- package/dist/lang/parse-log.js +2 -0
- package/dist/lang/parse-malloy.d.ts +17 -2
- package/dist/lang/parse-malloy.js +48 -14
- package/dist/lang/parse-tree-walkers/find-external-references.d.ts +3 -3
- package/dist/lang/parse-tree-walkers/find-external-references.js +17 -16
- package/dist/lang/test/test-translator.d.ts +11 -1
- package/dist/lang/test/test-translator.js +51 -3
- package/dist/model/expression_compiler.js +9 -8
- package/dist/model/filter_compilers.js +13 -12
- package/dist/model/given_binding.d.ts +8 -0
- package/dist/model/given_binding.js +13 -0
- package/dist/model/index.d.ts +1 -1
- package/dist/model/index.js +2 -1
- package/dist/model/query_query.d.ts +3 -1
- package/dist/model/query_query.js +157 -139
- package/dist/model/source_def_utils.d.ts +7 -1
- package/dist/model/source_def_utils.js +20 -0
- package/dist/model/sql_compiled.d.ts +19 -20
- package/dist/model/sql_compiled.js +29 -17
- package/dist/test/index.js +16 -8
- package/dist/test/matchers.d.ts +1 -1
- package/dist/test/matchers.js +1 -1
- package/dist/test/test-models.js +6 -13
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/femto-config.motly +13 -1
- package/package.json +7 -5
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright Contributors to the Malloy project
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.dbmetaProperty = exports.DBMETA_ROUTE = void 0;
|
|
8
|
+
exports.dbmetaAnnotations = dbmetaAnnotations;
|
|
9
|
+
const malloy_tag_1 = require("@malloydata/malloy-tag");
|
|
10
|
+
/**
|
|
11
|
+
* The annotation route a connection writes database metadata to:
|
|
12
|
+
* `#(dbmeta) description="..."`.
|
|
13
|
+
*/
|
|
14
|
+
exports.DBMETA_ROUTE = 'dbmeta';
|
|
15
|
+
const DBMETA_LOCATION = {
|
|
16
|
+
url: `internal://${exports.DBMETA_ROUTE}`,
|
|
17
|
+
range: { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* The connection property that turns on database metadata. Connections that
|
|
21
|
+
* support it register this definition, so the option has the same name and
|
|
22
|
+
* meaning on every backend. Off unless set.
|
|
23
|
+
*/
|
|
24
|
+
exports.dbmetaProperty = {
|
|
25
|
+
name: 'dbmeta',
|
|
26
|
+
displayName: 'Database Metadata',
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
optional: true,
|
|
29
|
+
advanced: true,
|
|
30
|
+
description: 'Copy table and column descriptions from the database onto the schema, ' +
|
|
31
|
+
'as #(dbmeta) description annotations.',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The `#(dbmeta)` annotation for a table or column, as a fragment to spread
|
|
35
|
+
* into its field or table def: `{annotations}`, or `{}` when there is nothing
|
|
36
|
+
* to say.
|
|
37
|
+
*/
|
|
38
|
+
function dbmetaAnnotations(meta) {
|
|
39
|
+
var _a;
|
|
40
|
+
const description = (_a = meta.description) === null || _a === void 0 ? void 0 : _a.trim();
|
|
41
|
+
if (!description)
|
|
42
|
+
return {};
|
|
43
|
+
const text = `#(${exports.DBMETA_ROUTE}) description=${(0, malloy_tag_1.quoteString)(description)}\n`;
|
|
44
|
+
return { annotations: { notes: [{ text, at: DBMETA_LOCATION }] } };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=dbmeta.js.map
|
package/dist/connection/index.js
CHANGED
|
@@ -17,4 +17,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./types"), exports);
|
|
18
18
|
__exportStar(require("./base_connection"), exports);
|
|
19
19
|
__exportStar(require("./registry"), exports);
|
|
20
|
+
__exportStar(require("./dbmeta"), exports);
|
|
20
21
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { Sampling, MeasureTimeExpr, RegexMatchExpr,
|
|
2
|
-
import type { BooleanTypeSupport, CompiledOrderBy, DialectFieldList, FieldReferenceType, LateralJoinExpression, OrderByClauseType, OrderByRequest, QueryInfo } from '../dialect';
|
|
1
|
+
import type { Sampling, MeasureTimeExpr, RegexMatchExpr, TypecastExpr, BasicAtomicTypeDef, AtomicTypeDef, ArrayLiteralNode, RecordLiteralNode, ATimestampTypeDef, TimestampUnit, ExtractUnit } from '../../model/malloy_types';
|
|
2
|
+
import type { CivilTime, BooleanTypeSupport, CompiledOrderBy, DialectFieldList, FieldReferenceType, LateralJoinExpression, OrderByClauseType, OrderByRequest, QueryInfo } from '../dialect';
|
|
3
3
|
import { Dialect } from '../dialect';
|
|
4
4
|
import type { DialectFunctionOverloadDef } from '../functions';
|
|
5
5
|
export declare class DatabricksDialect extends Dialect {
|
|
@@ -66,18 +66,17 @@ export declare class DatabricksDialect extends Dialect {
|
|
|
66
66
|
sqlSelectAliasAsStruct(alias: string, fieldList: DialectFieldList): string;
|
|
67
67
|
sqlCreateTableAsSelect(tableName: string, sql: string): string;
|
|
68
68
|
sqlNowExpr(): string;
|
|
69
|
-
sqlConvertToCivilTime(expr: string, timezone: string, _typeDef:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
|
|
69
|
+
sqlConvertToCivilTime(expr: string, timezone: string, _typeDef: ATimestampTypeDef): string;
|
|
70
|
+
sqlConvertFromCivilTime(expr: string, timezone: string, _destTypeDef: ATimestampTypeDef): string;
|
|
71
|
+
sqlTruncate(expr: string, unit: TimestampUnit, _civilType: CivilTime): string;
|
|
72
|
+
sqlOffsetTime(expr: string, op: '+' | '-', magnitude: string, unit: TimestampUnit, _civilType: CivilTime): string;
|
|
73
|
+
sqlCivilExtract(expr: string, units: ExtractUnit, _civilType: CivilTime): string;
|
|
74
|
+
sqlCivilToDate(expr: string): string;
|
|
75
|
+
sqlDateToCivil(expr: string): string;
|
|
76
|
+
sqlCast(_qi: QueryInfo, cast: TypecastExpr): string;
|
|
78
77
|
sqlRegexpMatch(df: RegexMatchExpr): string;
|
|
79
78
|
sqlDateLiteral(_qi: QueryInfo, literal: string): string;
|
|
80
|
-
|
|
79
|
+
sqlCivilLiteral(literal: string): string;
|
|
81
80
|
sqlTimestamptzLiteral(_qi: QueryInfo, _literal: string, _timezone: string): string;
|
|
82
81
|
sqlMeasureTimeExpr(df: MeasureTimeExpr): string;
|
|
83
82
|
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|
|
@@ -300,19 +300,19 @@ class DatabricksDialect extends dialect_1.Dialect {
|
|
|
300
300
|
sqlNowExpr() {
|
|
301
301
|
return 'CURRENT_TIMESTAMP()';
|
|
302
302
|
}
|
|
303
|
+
// Civil time is a TIMESTAMP whose reading in the session zone, UTC, is
|
|
304
|
+
// the civil time
|
|
303
305
|
sqlConvertToCivilTime(expr, timezone, _typeDef) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
sql: `FROM_UTC_TIMESTAMP(${expr}, ${this.sqlTimezoneLiteral(timezone)})`,
|
|
308
|
-
typeDef: { type: 'timestamp' },
|
|
309
|
-
};
|
|
306
|
+
return timezone === 'UTC'
|
|
307
|
+
? expr
|
|
308
|
+
: `FROM_UTC_TIMESTAMP(${expr}, ${this.sqlTimezoneLiteral(timezone)})`;
|
|
310
309
|
}
|
|
311
310
|
sqlConvertFromCivilTime(expr, timezone, _destTypeDef) {
|
|
312
|
-
|
|
313
|
-
|
|
311
|
+
return timezone === 'UTC'
|
|
312
|
+
? expr
|
|
313
|
+
: `TO_UTC_TIMESTAMP(${expr}, ${this.sqlTimezoneLiteral(timezone)})`;
|
|
314
314
|
}
|
|
315
|
-
sqlTruncate(expr, unit,
|
|
315
|
+
sqlTruncate(expr, unit, _civilType) {
|
|
316
316
|
// Databricks DATE_TRUNC starts weeks on Monday; Malloy wants Sunday.
|
|
317
317
|
// Add 1 day before truncating, subtract 1 day after.
|
|
318
318
|
if (unit === 'week') {
|
|
@@ -320,7 +320,7 @@ class DatabricksDialect extends dialect_1.Dialect {
|
|
|
320
320
|
}
|
|
321
321
|
return `DATE_TRUNC('${unit}', ${expr})`;
|
|
322
322
|
}
|
|
323
|
-
sqlOffsetTime(expr, op, magnitude, unit,
|
|
323
|
+
sqlOffsetTime(expr, op, magnitude, unit, _civilType) {
|
|
324
324
|
// Use TIMESTAMPADD which accepts expressions for magnitude,
|
|
325
325
|
// unlike INTERVAL which only accepts literals in Databricks.
|
|
326
326
|
let offsetUnit = unit.toUpperCase();
|
|
@@ -336,31 +336,23 @@ class DatabricksDialect extends dialect_1.Dialect {
|
|
|
336
336
|
const n = op === '+' ? offsetMag : `-(${offsetMag})`;
|
|
337
337
|
return `TIMESTAMPADD(${offsetUnit}, ${n}, ${expr})`;
|
|
338
338
|
}
|
|
339
|
-
|
|
340
|
-
const
|
|
341
|
-
|
|
342
|
-
if (malloy_types_1.TD.isTimestamp(te.e.typeDef)) {
|
|
343
|
-
const tz = (0, dialect_1.qtz)(qi);
|
|
344
|
-
if (tz) {
|
|
345
|
-
extractFrom = `FROM_UTC_TIMESTAMP(${extractFrom}, ${this.sqlTimezoneLiteral(tz)})`;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
if (extractionMap[te.units]) {
|
|
339
|
+
sqlCivilExtract(expr, units, _civilType) {
|
|
340
|
+
const extractUnits = extractionMap[units];
|
|
341
|
+
if (extractUnits) {
|
|
349
342
|
// DAYOFWEEK, DAYOFYEAR are functions
|
|
350
|
-
return `${
|
|
343
|
+
return `${extractUnits}(${expr})`;
|
|
351
344
|
}
|
|
352
|
-
return `EXTRACT(${units} FROM ${
|
|
345
|
+
return `EXTRACT(${units} FROM ${expr})`;
|
|
346
|
+
}
|
|
347
|
+
sqlCivilToDate(expr) {
|
|
348
|
+
return `CAST(${expr} AS DATE)`;
|
|
349
|
+
}
|
|
350
|
+
sqlDateToCivil(expr) {
|
|
351
|
+
return `CAST(${expr} AS TIMESTAMP)`;
|
|
353
352
|
}
|
|
354
|
-
sqlCast(
|
|
353
|
+
sqlCast(_qi, cast) {
|
|
355
354
|
const srcSQL = cast.e.sql || 'internal-error-in-sql-generation';
|
|
356
|
-
const {
|
|
357
|
-
const tz = (0, dialect_1.qtz)(qi);
|
|
358
|
-
if (op === 'timestamp::date' && tz) {
|
|
359
|
-
return `CAST(FROM_UTC_TIMESTAMP(${srcSQL}, ${this.sqlTimezoneLiteral(tz)}) AS DATE)`;
|
|
360
|
-
}
|
|
361
|
-
else if (op === 'date::timestamp' && tz) {
|
|
362
|
-
return `TO_UTC_TIMESTAMP(CAST(${srcSQL} AS TIMESTAMP_NTZ), ${this.sqlTimezoneLiteral(tz)})`;
|
|
363
|
-
}
|
|
355
|
+
const { srcTypeDef, dstTypeDef, dstSQLType } = this.sqlCastPrep(cast);
|
|
364
356
|
if (!malloy_types_1.TD.eq(srcTypeDef, dstTypeDef)) {
|
|
365
357
|
if (cast.safe) {
|
|
366
358
|
return `TRY_CAST(${srcSQL} AS ${dstSQLType})`;
|
|
@@ -378,11 +370,7 @@ class DatabricksDialect extends dialect_1.Dialect {
|
|
|
378
370
|
sqlDateLiteral(_qi, literal) {
|
|
379
371
|
return `DATE '${literal}'`;
|
|
380
372
|
}
|
|
381
|
-
|
|
382
|
-
const tz = timezone || (0, dialect_1.qtz)(qi);
|
|
383
|
-
if (tz) {
|
|
384
|
-
return `TO_UTC_TIMESTAMP(TIMESTAMP_NTZ '${literal}', ${this.sqlTimezoneLiteral(tz)})`;
|
|
385
|
-
}
|
|
373
|
+
sqlCivilLiteral(literal) {
|
|
386
374
|
return `TIMESTAMP '${literal}'`;
|
|
387
375
|
}
|
|
388
376
|
sqlTimestamptzLiteral(_qi, _literal, _timezone) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Expr, Sampling, AtomicTypeDef, MeasureTimeExpr, TimeExtractExpr, TypecastExpr, RegexMatchExpr, TimeLiteralExpr, RecordLiteralNode, ArrayLiteralNode, BasicAtomicTypeDef, OrderBy, TimestampUnit, ATimestampTypeDef, TimeExpr, TemporalFieldType } from '../model/malloy_types';
|
|
1
|
+
import type { Expr, Sampling, AtomicTypeDef, MeasureTimeExpr, TimeExtractExpr, TypecastExpr, RegexMatchExpr, TimeLiteralExpr, RecordLiteralNode, ArrayLiteralNode, BasicAtomicTypeDef, OrderBy, TimestampUnit, ATimestampTypeDef, TimeExpr, TemporalFieldType, ExtractUnit } from '../model/malloy_types';
|
|
2
2
|
import type { DialectFunctionOverloadDef } from './functions';
|
|
3
3
|
import type { ValidateTablePathResult } from './table-path';
|
|
4
4
|
/**
|
|
@@ -68,10 +68,26 @@ export interface QueryInfo {
|
|
|
68
68
|
queryTimezone?: string;
|
|
69
69
|
systemTimezone?: string;
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* The two kinds of civil time: a calendar date, and a date with a time of
|
|
73
|
+
* day. Neither has a zone.
|
|
74
|
+
*/
|
|
75
|
+
export declare const CivilTime: {
|
|
76
|
+
readonly Date: "date";
|
|
77
|
+
readonly DateAndTime: "date_and_time";
|
|
78
|
+
};
|
|
79
|
+
export type CivilTime = (typeof CivilTime)[keyof typeof CivilTime];
|
|
80
|
+
/** Add or subtract `magnitude` units of time */
|
|
81
|
+
export interface TimeOffset {
|
|
82
|
+
op: '+' | '-';
|
|
83
|
+
magnitude: string;
|
|
84
|
+
unit: TimestampUnit;
|
|
85
|
+
}
|
|
71
86
|
export type FieldReferenceType = 'table' | 'nest source' | 'array[scalar]' | 'array[record]' | 'record';
|
|
72
87
|
export declare const dayIndex: number;
|
|
73
88
|
export declare function inDays(units: string): boolean;
|
|
74
|
-
|
|
89
|
+
/** The query time zone, or UTC when the query has none. */
|
|
90
|
+
export declare function queryZone(qi: QueryInfo): string;
|
|
75
91
|
/**
|
|
76
92
|
* The per-element condition for an aggregate turtle (sqlAggregateTurtle). On
|
|
77
93
|
* the normal path it gates each row by its group_set (and a projection's own
|
|
@@ -83,6 +99,7 @@ export declare function qtz(qi: QueryInfo): string | undefined;
|
|
|
83
99
|
*/
|
|
84
100
|
export declare function turtleGroupSetCondition(groupSet: number | undefined, filterSQL: string | undefined): string | undefined;
|
|
85
101
|
export type OrderByClauseType = 'output_name' | 'ordinal' | 'expression';
|
|
102
|
+
export type GroupByClauseType = 'ordinal' | 'expression';
|
|
86
103
|
export type OrderByRequest = 'query' | 'turtle' | 'analytical';
|
|
87
104
|
export type BooleanTypeSupport = 'supported' | 'simulated' | 'none';
|
|
88
105
|
/**
|
|
@@ -115,6 +132,14 @@ export declare abstract class Dialect {
|
|
|
115
132
|
abstract supportsSafeCast: boolean;
|
|
116
133
|
abstract supportsNesting: boolean;
|
|
117
134
|
abstract experimental: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* What the compiler consults, not `experimental` itself. The test harness
|
|
137
|
+
* calls `acceptExperimental()` on the dialect under test so the shared
|
|
138
|
+
* suites can run on an experimental dialect without every test enabling it.
|
|
139
|
+
*/
|
|
140
|
+
private experimentalAccepted;
|
|
141
|
+
isExperimental(): boolean;
|
|
142
|
+
acceptExperimental(): void;
|
|
118
143
|
cantPartitionWindowFunctionsOnExpressions: boolean;
|
|
119
144
|
sqlLateralJoinBag(_expressions: LateralJoinExpression[]): string;
|
|
120
145
|
supportsPipelinesInViews: boolean;
|
|
@@ -123,6 +148,9 @@ export declare abstract class Dialect {
|
|
|
123
148
|
hasTimestamptz: boolean;
|
|
124
149
|
readsNestedData: boolean;
|
|
125
150
|
orderByClause: OrderByClauseType;
|
|
151
|
+
groupByClause: GroupByClauseType;
|
|
152
|
+
/** The ordering and row limit which end a SELECT stage */
|
|
153
|
+
sqlOrderByLimit(orderTerms: string[], limit: number | undefined): string;
|
|
126
154
|
nullMatchesFunctionSignature: boolean;
|
|
127
155
|
supportsSelectReplace: boolean;
|
|
128
156
|
supportsBigIntPrecision: boolean;
|
|
@@ -140,6 +168,7 @@ export declare abstract class Dialect {
|
|
|
140
168
|
compoundObjectInSchema: boolean;
|
|
141
169
|
booleanType: BooleanTypeSupport;
|
|
142
170
|
likeEscape: boolean;
|
|
171
|
+
likeExtraWildcards: string[];
|
|
143
172
|
/**
|
|
144
173
|
* Mappings from integer value ranges to Malloy number types.
|
|
145
174
|
*
|
|
@@ -270,175 +299,43 @@ export declare abstract class Dialect {
|
|
|
270
299
|
sqlLiteralNumber(literal: string): string;
|
|
271
300
|
ignoreInProject(_fieldName: string): boolean;
|
|
272
301
|
abstract sqlNowExpr(): string;
|
|
273
|
-
abstract sqlTimeExtractExpr(qi: QueryInfo, xFrom: TimeExtractExpr): string;
|
|
274
302
|
abstract sqlMeasureTimeExpr(e: MeasureTimeExpr): string;
|
|
275
303
|
/**
|
|
276
|
-
* Generate SQL for
|
|
277
|
-
*
|
|
278
|
-
* Most casts are simple: `CAST(expr AS type)` or `TRY_CAST(expr AS type)` for safe casts.
|
|
279
|
-
*
|
|
280
|
-
* However, when a query timezone is set, casts between temporal types (date, timestamp, timestamptz)
|
|
281
|
-
* require special handling to ensure correct timezone semantics:
|
|
282
|
-
*
|
|
283
|
-
* **Timezone-Aware Cast Semantics:**
|
|
284
|
-
*
|
|
285
|
-
* 1. **TIMESTAMP → DATE**:
|
|
286
|
-
* - TIMESTAMP represents UTC wall clock
|
|
287
|
-
* - Convert to query timezone, then extract date
|
|
288
|
-
* - Example: TIMESTAMP '2020-02-20 00:00:00' with tz 'America/Mexico_City' → '2020-02-19'
|
|
289
|
-
*
|
|
290
|
-
* 2. **TIMESTAMPTZ → DATE**:
|
|
291
|
-
* - TIMESTAMPTZ represents absolute instant
|
|
292
|
-
* - Convert to query timezone, then extract date
|
|
293
|
-
* - Example: TIMESTAMPTZ '2020-02-20 00:00:00 UTC' with tz 'America/Mexico_City' → '2020-02-19'
|
|
294
|
-
*
|
|
295
|
-
* 3. **DATE → TIMESTAMP**:
|
|
296
|
-
* - DATE represents civil date
|
|
297
|
-
* - Interpret as midnight in query timezone, return UTC wall clock
|
|
298
|
-
* - Example: DATE '2020-02-20' with tz 'America/Mexico_City' → TIMESTAMP '2020-02-20 06:00:00' (UTC)
|
|
299
|
-
*
|
|
300
|
-
* 4. **DATE → TIMESTAMPTZ**:
|
|
301
|
-
* - DATE represents civil date
|
|
302
|
-
* - Interpret as midnight in query timezone, create instant
|
|
303
|
-
* - Example: DATE '2020-02-20' with tz 'America/Mexico_City' → instant at 2020-02-20 06:00:00 UTC
|
|
304
|
-
*
|
|
305
|
-
* 5. **TIMESTAMPTZ → TIMESTAMP**:
|
|
306
|
-
* - TIMESTAMPTZ represents absolute instant
|
|
307
|
-
* - Extract wall clock in query timezone, return as TIMESTAMP
|
|
308
|
-
* - Example: TIMESTAMPTZ '2020-02-20 00:00:00 UTC' with tz 'America/Mexico_City' → TIMESTAMP '2020-02-19 18:00:00'
|
|
309
|
-
*
|
|
310
|
-
* 6. **TIMESTAMP → TIMESTAMPTZ**:
|
|
311
|
-
* - TIMESTAMP represents UTC wall clock
|
|
312
|
-
* - Interpret as being in query timezone
|
|
313
|
-
* - Example: TIMESTAMP '2020-02-20 00:00:00' with tz 'America/Mexico_City' → instant at 2020-02-20 06:00:00 UTC
|
|
314
|
-
*
|
|
315
|
-
* **Implementation Notes:**
|
|
316
|
-
*
|
|
317
|
-
* - Dialects without timestamptz support (MySQL, BigQuery, StandardSQL) only need cases 1-3
|
|
318
|
-
* - Without query timezone, most casts are simple `CAST(expr AS type)`
|
|
319
|
-
*
|
|
320
|
-
* @param qi - Query info containing timezone and other context
|
|
321
|
-
* @param cast - The typecast expression to generate SQL for
|
|
322
|
-
* @returns SQL string for the cast operation
|
|
304
|
+
* Generate SQL for a cast. Casts between date, timestamp and timestamptz
|
|
305
|
+
* never reach here; they are made by sqlTimeCast.
|
|
323
306
|
*/
|
|
324
307
|
abstract sqlCast(qi: QueryInfo, cast: TypecastExpr): string;
|
|
325
308
|
abstract sqlRegexpMatch(df: RegexMatchExpr): string;
|
|
309
|
+
/** The civil time which `timezone` shows at the instant `expr`. */
|
|
310
|
+
abstract sqlConvertToCivilTime(expr: string, timezone: string, typeDef: ATimestampTypeDef): string;
|
|
326
311
|
/**
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
* Each dialect selects its own SQL type to represent civil time (e.g., plain TIMESTAMP,
|
|
330
|
-
* TIMESTAMP WITH TIME ZONE, or DATETIME). The civil space is where timezone-aware
|
|
331
|
-
* truncation and interval arithmetic happen. Operations like sqlTruncate and sqlOffsetTime
|
|
332
|
-
* are aware of the civil space and work correctly within it.
|
|
333
|
-
*
|
|
334
|
-
* @param expr The SQL expression for the Malloy timestamp (plain or timestamptz)
|
|
335
|
-
* @param timezone The target timezone for civil operations
|
|
336
|
-
* @param typeDef The Malloy type of the input expression
|
|
337
|
-
* @returns Object with SQL expression and the SQL type it evaluates to (the civil type)
|
|
338
|
-
*/
|
|
339
|
-
abstract sqlConvertToCivilTime(expr: string, timezone: string, typeDef: AtomicTypeDef): {
|
|
340
|
-
sql: string;
|
|
341
|
-
typeDef: AtomicTypeDef;
|
|
342
|
-
};
|
|
343
|
-
/**
|
|
344
|
-
* Converts from civil time back to a Malloy timestamp type.
|
|
345
|
-
*
|
|
346
|
-
* This is the inverse of sqlConvertToCivilTime. Takes a value in the dialect's
|
|
347
|
-
* civil space and converts it back to either a plain timestamp (UTC) or a
|
|
348
|
-
* timestamptz, depending on the destination type.
|
|
349
|
-
*
|
|
350
|
-
* @param expr The SQL expression in civil time
|
|
351
|
-
* @param timezone The timezone of the civil time
|
|
352
|
-
* @param destTypeDef The destination Malloy timestamp type (plain or timestamptz)
|
|
353
|
-
* @returns SQL expression representing the Malloy timestamp
|
|
312
|
+
* The instant at which `timezone` shows the civil time `expr`, as a
|
|
313
|
+
* value of `destTypeDef`.
|
|
354
314
|
*/
|
|
355
315
|
abstract sqlConvertFromCivilTime(expr: string, timezone: string, destTypeDef: ATimestampTypeDef): string;
|
|
316
|
+
/** The start of the unit containing `expr`. A week starts on Sunday. */
|
|
317
|
+
abstract sqlTruncate(expr: string, unit: TimestampUnit, civilType: CivilTime): string;
|
|
318
|
+
abstract sqlOffsetTime(expr: string, op: '+' | '-', magnitude: string, unit: TimestampUnit, civilType: CivilTime): string;
|
|
319
|
+
/** One field of `expr`. A day_of_week counts from 1 on Sunday. */
|
|
320
|
+
abstract sqlCivilExtract(expr: string, units: ExtractUnit, civilType: CivilTime): string;
|
|
321
|
+
/** The date part of the civil time `expr`. */
|
|
322
|
+
abstract sqlCivilToDate(expr: string): string;
|
|
323
|
+
/** Midnight at the start of the date `expr`, as civil time. */
|
|
324
|
+
abstract sqlDateToCivil(expr: string): string;
|
|
325
|
+
/** The civil time written as `literal`, 'YYYY-MM-DD HH:MM:SS'. */
|
|
326
|
+
abstract sqlCivilLiteral(literal: string): string;
|
|
327
|
+
sqlTimeExtractExpr(qi: QueryInfo, from: TimeExtractExpr): string;
|
|
356
328
|
/**
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
* @param expr The SQL expression to truncate
|
|
360
|
-
* @param unit The unit to truncate to (year, month, day, hour, etc.)
|
|
361
|
-
* @param typeDef The Malloy type of the expression (date, timestamp, etc.)
|
|
362
|
-
* @param inCivilTime If true, the expression is already in civil (local) time and should not
|
|
363
|
-
* be converted. If false, may need timezone conversion for timestamps.
|
|
364
|
-
* @param timezone Optional timezone for the operation. Only provided when timezone-aware
|
|
365
|
-
* truncation is needed but inCivilTime is false.
|
|
366
|
-
* @returns SQL expression representing the truncated time
|
|
367
|
-
*/
|
|
368
|
-
abstract sqlTruncate(expr: string, unit: TimestampUnit, typeDef: AtomicTypeDef, inCivilTime: boolean, timezone?: string): string;
|
|
369
|
-
/**
|
|
370
|
-
* Adds or subtracts a time interval from a time expression.
|
|
371
|
-
*
|
|
372
|
-
* @param expr The SQL expression to offset
|
|
373
|
-
* @param op The operation: '+' for addition, '-' for subtraction
|
|
374
|
-
* @param magnitude The SQL expression for the interval magnitude (e.g., '6', '(delta_val)')
|
|
375
|
-
* @param unit The interval unit (year, month, day, hour, etc.)
|
|
376
|
-
* @param typeDef The Malloy type of the expression (date, timestamp, etc.)
|
|
377
|
-
* @param inCivilTime If true, the expression is already in civil (local) time and should not
|
|
378
|
-
* be converted. If false, may need timezone conversion for timestamps.
|
|
379
|
-
* @param timezone Optional timezone for the operation. Only provided when timezone-aware
|
|
380
|
-
* offset is needed but inCivilTime is false.
|
|
381
|
-
* @returns SQL expression representing the offset time
|
|
382
|
-
*/
|
|
383
|
-
abstract sqlOffsetTime(expr: string, op: '+' | '-', magnitude: string, unit: TimestampUnit, typeDef: AtomicTypeDef, inCivilTime: boolean, timezone?: string): string;
|
|
384
|
-
/**
|
|
385
|
-
* Determines whether a truncation and/or offset operation needs to be performed in
|
|
386
|
-
* civil (local) time, and if so, which timezone to use.
|
|
387
|
-
*
|
|
388
|
-
* Calendar-based operations (day, week, month, quarter, year) typically need civil time
|
|
389
|
-
* computation because these units can cross DST boundaries, changing the UTC offset.
|
|
390
|
-
*
|
|
391
|
-
* Default implementation:
|
|
392
|
-
* - Returns true for timestamps with truncation or calendar-unit offsets
|
|
393
|
-
* - Uses the query timezone from QueryInfo, or 'UTC' if none specified
|
|
394
|
-
* - Returns false for dates or sub-day offsets (hour, minute, second)
|
|
395
|
-
*
|
|
396
|
-
* Dialects can override this if they have different rules about which operations
|
|
397
|
-
* require civil time computation.
|
|
398
|
-
*
|
|
399
|
-
* @param typeDef The Malloy type of the base expression
|
|
400
|
-
* @param truncateTo The truncation unit, if any
|
|
401
|
-
* @param offsetUnit The offset unit, if any
|
|
402
|
-
* @param qi Query information including timezone settings
|
|
403
|
-
* @returns Object with `needed` boolean and optional `tz` string
|
|
329
|
+
* Truncation and/or offset, the offset applied after the truncation.
|
|
330
|
+
* Doing both in one pass converts to and from civil time only once.
|
|
404
331
|
*/
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
tz: string | undefined;
|
|
408
|
-
};
|
|
332
|
+
sqlTruncAndOffset(baseExpr: TimeExpr, qi: QueryInfo, truncateTo?: TimestampUnit, offset?: TimeOffset): string;
|
|
333
|
+
private civilTruncAndOffset;
|
|
409
334
|
/**
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
* Much of the complexity has to do with getting timezone values set up so that
|
|
414
|
-
* they will truncate/offset in the query timezone instead of UTC.
|
|
415
|
-
*
|
|
416
|
-
* The intention is that this implementation will work for all dialects, and all
|
|
417
|
-
* the dialect peculiarities are handled with the new primitives introduced to
|
|
418
|
-
* support this function:
|
|
419
|
-
* - needsCivilTimeComputation: Determines if operation needs civil time
|
|
420
|
-
* - sqlConvertToCivilTime/sqlConvertFromCivilTime: Timezone conversion
|
|
421
|
-
* - sqlTruncate: Truncation operation
|
|
422
|
-
* - sqlOffsetTime: Interval arithmetic
|
|
423
|
-
*
|
|
424
|
-
* OFFSET TIMESTAMP BEHAVIOR:
|
|
425
|
-
* - Plain timestamps (offset=false): Always return plain TIMESTAMP in UTC
|
|
426
|
-
* - Offset timestamps (offset=true):
|
|
427
|
-
* - Simple path: Operate in native embedded timezone, return TIMESTAMPTZ
|
|
428
|
-
* - Civil path: Convert to query timezone (preserving instant), operate there,
|
|
429
|
-
* return TIMESTAMPTZ in query timezone via sqlConvertFromCivilTime
|
|
430
|
-
* - BigQuery/MySQL: No offset timestamp support, this logic never runs
|
|
431
|
-
*
|
|
432
|
-
* @param baseExpr The time expression to operate on (already compiled, with .sql populated)
|
|
433
|
-
* @param qi Query information including timezone
|
|
434
|
-
* @param truncateTo Optional truncation unit (year, month, day, etc.)
|
|
435
|
-
* @param offset Optional offset to apply (after truncation if both present)
|
|
335
|
+
* A cast between date, timestamp and timestamptz, or undefined for any
|
|
336
|
+
* other cast.
|
|
436
337
|
*/
|
|
437
|
-
|
|
438
|
-
op: '+' | '-';
|
|
439
|
-
magnitude: string;
|
|
440
|
-
unit: TimestampUnit;
|
|
441
|
-
}): string;
|
|
338
|
+
sqlTimeCast(qi: QueryInfo, cast: TypecastExpr): string | undefined;
|
|
442
339
|
/**
|
|
443
340
|
* Generate SQL for a DATE literal.
|
|
444
341
|
* @param literal - The date string in format 'YYYY-MM-DD'
|
|
@@ -446,18 +343,10 @@ export declare abstract class Dialect {
|
|
|
446
343
|
*/
|
|
447
344
|
abstract sqlDateLiteral(qi: QueryInfo, literal: string): string;
|
|
448
345
|
/**
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
* @param timezone - Optional timezone name (e.g., 'America/Los_Angeles')
|
|
452
|
-
* - If undefined: Create plain timestamp literal from the literal string
|
|
453
|
-
* - If defined: The literal string represents a civil time in the given timezone.
|
|
454
|
-
* Convert it to a plain timestamp (typically by interpreting as timestamptz
|
|
455
|
-
* in that timezone, then casting to plain timestamp). This happens when:
|
|
456
|
-
* 1. A constant with timezone is used (constants don't have dialect context)
|
|
457
|
-
* 2. A literal with timezone is used in a dialect that doesn't support offset timestamps
|
|
458
|
-
* @returns SQL that produces a plain TIMESTAMP value
|
|
346
|
+
* The timestamp at which `timezone`, or the query time zone when there is
|
|
347
|
+
* none, shows the civil time `literal`.
|
|
459
348
|
*/
|
|
460
|
-
|
|
349
|
+
sqlTimestampLiteral(qi: QueryInfo, literal: string, timezone: string | undefined): string;
|
|
461
350
|
/**
|
|
462
351
|
* Generate SQL for an offset TIMESTAMP literal (TIMESTAMP WITH TIME ZONE).
|
|
463
352
|
* Only called for dialects where hasOffsetTimestamp = true.
|
|
@@ -503,7 +392,7 @@ export declare abstract class Dialect {
|
|
|
503
392
|
exprToSQL(qi: QueryInfo, df: Expr): string | undefined;
|
|
504
393
|
sqlSumDistinct(_key: string, _value: string, _funcName: string): string;
|
|
505
394
|
sqlAggDistinct(_key: string, _values: string[], _func: (valNames: string[]) => string): string;
|
|
506
|
-
sqlSampleTable(tableSQL: string, sample: Sampling | undefined): string;
|
|
395
|
+
sqlSampleTable(tableSQL: string, sample: Sampling | undefined, _onBaseTable?: boolean): string;
|
|
507
396
|
/**
|
|
508
397
|
* MySQL is NULLs first, all other dialects have a way to make NULLs last.
|
|
509
398
|
* isBaseOrdering is a hack to allow the MySQL dialect to partially implement
|
|
@@ -535,6 +424,16 @@ export declare abstract class Dialect {
|
|
|
535
424
|
* SQL to generate to get a boolean value for a boolean expression
|
|
536
425
|
*/
|
|
537
426
|
sqlBoolean(bv: boolean): string;
|
|
427
|
+
/**
|
|
428
|
+
* Malloy's `not`: of NULL, true. A dialect with booleanType 'none' has no
|
|
429
|
+
* boolean value for COALESCE to return, so the test is written as a
|
|
430
|
+
* condition.
|
|
431
|
+
*/
|
|
432
|
+
sqlNot(condition: string): string;
|
|
433
|
+
/**
|
|
434
|
+
* A condition Malloy defines as true when SQL says NULL: `!=` and `!~`
|
|
435
|
+
*/
|
|
436
|
+
sqlNullIsTrue(condition: string): string;
|
|
538
437
|
/**
|
|
539
438
|
* What a boolean value looks like in a query result
|
|
540
439
|
*/
|