data-finder-ts 0.1.4 → 0.1.5
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/{chunk-4JVW4TAB.js → chunk-BGEX377Q.js} +58 -8
- package/dist/chunk-BGEX377Q.js.map +1 -0
- package/dist/chunk-BKPWV3OF.js +962 -0
- package/dist/chunk-BKPWV3OF.js.map +1 -0
- package/dist/{chunk-PMPLCEWQ.js → chunk-GPHWC533.js} +2 -2
- package/dist/{chunk-FJYA2ASS.js → chunk-KAK75RVS.js} +74 -12
- package/dist/chunk-KAK75RVS.js.map +1 -0
- package/dist/{chunk-4LNZV6EN.js → chunk-MGEL5RWM.js} +206 -78
- package/dist/chunk-MGEL5RWM.js.map +1 -0
- package/dist/chunk-PF6EJZHB.js +1015 -0
- package/dist/chunk-PF6EJZHB.js.map +1 -0
- package/dist/datafinder/attribute.cjs +537 -11
- package/dist/datafinder/attribute.cjs.map +1 -1
- package/dist/datafinder/attribute.d.cts +29 -7
- package/dist/datafinder/attribute.d.ts +29 -7
- package/dist/datafinder/attribute.js +2 -2
- package/dist/datafinder/runner.cjs +1267 -215
- package/dist/datafinder/runner.cjs.map +1 -1
- package/dist/datafinder/runner.d.cts +28 -5
- package/dist/datafinder/runner.d.ts +28 -5
- package/dist/datafinder/runner.js +6 -6
- package/dist/datafinder/sql-generator.cjs +1203 -206
- package/dist/datafinder/sql-generator.cjs.map +1 -1
- package/dist/datafinder/sql-generator.d.cts +19 -5
- package/dist/datafinder/sql-generator.d.ts +19 -5
- package/dist/datafinder/sql-generator.js +9 -5
- package/dist/datafinder/typed-attributes.cjs +693 -88
- package/dist/datafinder/typed-attributes.cjs.map +1 -1
- package/dist/datafinder/typed-attributes.d.cts +3 -242
- package/dist/datafinder/typed-attributes.d.ts +3 -242
- package/dist/datafinder/typed-attributes.js +3 -3
- package/dist/dialect-CogGPm_y.d.cts +38 -0
- package/dist/dialect-aaG1bDi5.d.ts +38 -0
- package/dist/index.cjs +1677 -408
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -5
- package/dist/index.d.ts +109 -5
- package/dist/index.js +321 -11
- package/dist/index.js.map +1 -1
- package/dist/model/milestoning.cjs +529 -0
- package/dist/model/milestoning.cjs.map +1 -1
- package/dist/model/milestoning.js +2 -2
- package/dist/model/relational.cjs +547 -16
- package/dist/model/relational.cjs.map +1 -1
- package/dist/model/relational.d.cts +421 -57
- package/dist/model/relational.d.ts +421 -57
- package/dist/model/relational.js +53 -3
- package/dist/typed-attributes-CUTf_6Ru.d.ts +328 -0
- package/dist/typed-attributes-CdWXq_78.d.cts +328 -0
- package/package.json +3 -2
- package/dist/chunk-4JVW4TAB.js.map +0 -1
- package/dist/chunk-4LNZV6EN.js.map +0 -1
- package/dist/chunk-FJYA2ASS.js.map +0 -1
- package/dist/chunk-MH4XMYVB.js +0 -696
- package/dist/chunk-MH4XMYVB.js.map +0 -1
- package/dist/chunk-UYMOE6YU.js +0 -509
- package/dist/chunk-UYMOE6YU.js.map +0 -1
- /package/dist/{chunk-PMPLCEWQ.js.map → chunk-GPHWC533.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/datafinder/dialect.ts","../src/datafinder/sql-generator.ts"],"sourcesContent":["/**\n * The SQL a query is written in. The generator writes Postgres by default; a dialect says where another database\n * differs, so the same query can be sent to DuckDB or Databricks.\n *\n * Only what differs is here. Everything the databases share (joins, CASE, window functions, COUNT(DISTINCT), LIKE ...\n * ESCAPE, `||`, typed date literals, `INTERVAL '7' DAY`, ...) is written once by the generator.\n */\nimport { DatePart, SortDirection } from '../model/relational';\n\nexport type DialectName = 'postgres' | 'duckdb' | 'databricks';\n\nexport interface SqlDialect {\n readonly name: DialectName;\n\n /** A name as an identifier, used for the names of the result's columns. */\n quoteIdentifier(name: string): string;\n\n /** A string as a literal that can never end early, whatever it holds. */\n stringLiteral(value: string): string;\n\n /**\n * ` ASC` or ` DESC`, with the null placement spelled out where the database's default differs from Postgres\n * (nulls last when ascending, first when descending), so a sort gives the same order everywhere.\n */\n orderDirection(direction: SortDirection): string;\n\n /** The type a float constant is cast to, so it comes back as a double and not a decimal. */\n readonly doubleType: string;\n\n /** The day of the week of a date or timestamp, 0 = Sunday through 6 = Saturday. */\n dayOfWeek(expression: string): string;\n\n /** Whole `unit`s from `from` to `to`; both are SQL expressions. */\n dateDiff(unit: DatePart, from: string, to: string): string;\n\n /** The values of a group joined with `separator` (an SQL literal), in the order given (each with its direction). */\n stringAgg(expression: string, separator: string, orderBy: string[]): string;\n}\n\nconst doubleQuoted = (name: string): string => '\"' + name.replaceAll('\"', '\"\"') + '\"';\nconst quoted = (value: string): string => \"'\" + value.replaceAll(\"'\", \"''\") + \"'\";\n\nconst SECONDS_PER: Partial<Record<DatePart, number>> = { [DatePart.HOUR]: 3600, [DatePart.MINUTE]: 60, [DatePart.SECOND]: 1 };\n\nexport const POSTGRES: SqlDialect = {\n name: 'postgres',\n quoteIdentifier: doubleQuoted,\n stringLiteral: quoted,\n orderDirection: direction => (direction === SortDirection.ASC ? ' ASC' : ' DESC'),\n doubleType: 'DOUBLE PRECISION',\n dayOfWeek: expression => `EXTRACT(DOW FROM ${expression})`,\n dateDiff(unit, from, to) {\n const start = `CAST(${from} AS TIMESTAMP)`;\n const end = `CAST(${to} AS TIMESTAMP)`;\n switch (unit) {\n case DatePart.DAY: return `(CAST(${to} AS DATE) - CAST(${from} AS DATE))`;\n case DatePart.MONTH:\n return `CAST(EXTRACT(YEAR FROM AGE(${end}, ${start})) * 12 + EXTRACT(MONTH FROM AGE(${end}, ${start})) AS BIGINT)`;\n case DatePart.YEAR: return `CAST(EXTRACT(YEAR FROM AGE(${end}, ${start})) AS BIGINT)`;\n default: {\n const seconds = SECONDS_PER[unit];\n if (seconds === undefined) throw new Error(`Cannot take the difference in ${unit}`);\n return `CAST(FLOOR(EXTRACT(EPOCH FROM (${end} - ${start})) / ${seconds}) AS BIGINT)`;\n }\n }\n },\n stringAgg: (expression, separator, orderBy) =>\n `STRING_AGG(${expression}, ${separator}${orderBy.length > 0 ? ' ORDER BY ' + orderBy.join(', ') : ''})`,\n};\n\nexport const DUCKDB: SqlDialect = {\n ...POSTGRES,\n name: 'duckdb',\n // DuckDB sorts nulls last whichever way the sort goes\n orderDirection: direction => (direction === SortDirection.ASC ? ' ASC' : ' DESC NULLS FIRST'),\n doubleType: 'DOUBLE',\n dateDiff: (unit, from, to) => `DATE_DIFF('${unit.toLowerCase()}', ${from}, ${to})`,\n};\n\nexport const DATABRICKS: SqlDialect = {\n name: 'databricks',\n // a double-quoted token is a string in Databricks; identifiers take backticks\n quoteIdentifier: name => '`' + name.replaceAll('`', '``') + '`',\n // a backslash starts an escape in a Databricks string literal, and a doubled quote is not one: Spark reads\n // 'it''s' as the two literals 'it' and 's' and joins them, losing the quote. A quote is escaped with a backslash.\n stringLiteral: value => \"'\" + value.replaceAll('\\\\', '\\\\\\\\').replaceAll(\"'\", \"\\\\'\") + \"'\",\n // Databricks sorts nulls first when ascending, last when descending\n orderDirection: direction => (direction === SortDirection.ASC ? ' ASC NULLS LAST' : ' DESC NULLS FIRST'),\n doubleType: 'DOUBLE',\n // DAYOFWEEK is 1 = Sunday through 7 = Saturday\n dayOfWeek: expression => `(DAYOFWEEK(${expression}) - 1)`,\n dateDiff: (unit, from, to) => `DATEDIFF(${unit}, ${from}, ${to})`,\n stringAgg: (expression, separator, orderBy) =>\n `LISTAGG(${expression}, ${separator})${orderBy.length > 0 ? ' WITHIN GROUP (ORDER BY ' + orderBy.join(', ') + ')' : ''}`,\n};\n\nconst DIALECTS: Record<DialectName, SqlDialect> = { postgres: POSTGRES, duckdb: DUCKDB, databricks: DATABRICKS };\n\n/** A dialect by name, or as given. */\nexport function dialectOf(dialect: DialectName | SqlDialect): SqlDialect {\n if (typeof dialect !== 'string') return dialect;\n const found = DIALECTS[dialect];\n if (found === undefined) throw new Error(`Unknown SQL dialect '${dialect}': one of ${Object.keys(DIALECTS).join(', ')}`);\n return found;\n}\n","import { Attribute } from './attribute';\nimport {\n RelationalOperationElement,\n Operation,\n NoOperation,\n ConstantOperation,\n StringConstantOperation,\n IntegerConstantOperation,\n FloatConstantOperation,\n DateConstantOperation,\n DateTimeConstantOperation,\n BooleanConstantOperation,\n DecimalConstantOperation,\n LogicalOperation,\n LogicalOperator,\n ComparisonOperation,\n ComparisonOperator,\n IsNullOperation,\n IsNotNullOperation,\n InOperation,\n NotInOperation,\n AggregateOperation,\n AggregateOperator,\n ScalarFunctionOperation,\n ScalarFunction,\n DateExtractOperation,\n DateArithmeticOperation,\n DateDiffOperation,\n WindowFunction,\n WindowFunctionOperation,\n WindowSpecification,\n Column,\n ColumnWithJoin,\n Table,\n JoinOperation,\n JoinTreeNodeOperation,\n SortOperation,\n SortDirection,\n DatePart,\n CountAllOperation,\n UnaryOperation,\n Alias,\n LIKE_ESCAPE,\n ExistsOperation,\n NotExistsOperation,\n SelectOperation,\n BinaryOperation,\n CaseOperation,\n ConcatOperation,\n DateTruncOperation,\n ArithmeticOperation,\n ArithmeticOperator,\n containsAggregate,\n containsAggregateOrWindow,\n} from '../model/relational';\nimport {\n MilestonedTable,\n BiTemporalColumns,\n BusinessDateAndProcessingTemporalColumns,\n MilestoningColumns,\n ProcessingTemporalColumns,\n SingleBusinessDateColumn,\n} from '../model/milestoning';\nimport { DateAttribute, DateTimeAttribute } from './typed-attributes';\nimport { DialectName, SqlDialect, dialectOf } from './dialect';\n\nclass TableAlias {\n constructor(readonly table: string, readonly alias: string) {}\n}\n\nclass TableAliasColumn extends RelationalOperationElement {\n constructor(readonly column: Column, readonly tableAlias: TableAlias) { super(); }\n}\n\nclass Join {\n constructor(\n readonly source: TableAliasColumn,\n readonly target: TableAliasColumn,\n readonly filterOp?: RelationalOperationElement,\n ) {}\n\n /** `source = target`, written with the key column first as Legend writes a join defined as key = foreign key. */\n condition(): string {\n let [first, second] = [this.source, this.target];\n if (second.column.primaryKey && !first.column.primaryKey) [first, second] = [second, first];\n return first.tableAlias.alias + '.' + first.column.name + ' = ' + second.tableAlias.alias + '.' + second.column.name;\n }\n}\n\nfunction sqlFormatDatetime(value: Date): string {\n const pad = (n: number, w = 2) => String(n).padStart(w, '0');\n return `'${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())} ${pad(value.getUTCHours())}:${pad(value.getUTCMinutes())}:${pad(value.getUTCSeconds())}'`;\n}\n\nfunction sqlFormatDate(value: Date): string {\n const pad = (n: number) => String(n).padStart(2, '0');\n return `'${value.getUTCFullYear()}-${pad(value.getUTCMonth() + 1)}-${pad(value.getUTCDate())}'`;\n}\n\nconst LOGICAL_OPERATOR_STR: Record<LogicalOperator, string> = {\n [LogicalOperator.AND]: ' AND ',\n [LogicalOperator.OR]: ' OR ',\n};\n\nconst COMPARISON_OPERATOR_STR: Record<ComparisonOperator, string> = {\n [ComparisonOperator.EQUAL]: ' = ',\n [ComparisonOperator.NOT_EQUAL]: ' <> ',\n [ComparisonOperator.LESS_THAN]: ' < ',\n [ComparisonOperator.GREATER_THAN]: ' > ',\n [ComparisonOperator.LESS_THAN_OR_EQUAL_TO]: ' <= ',\n [ComparisonOperator.GREATER_THAN_OR_EQUAL_TO]: ' >= ',\n [ComparisonOperator.LIKE]: ' LIKE ',\n [ComparisonOperator.NOT_LIKE]: ' NOT LIKE ',\n};\n\nconst AGGREGATE_SQL_NAMES: Partial<Record<AggregateOperator, string>> = {\n [AggregateOperator.AVERAGE]: 'AVG',\n};\n\n/**\n * Comparisons that are never true for a missing value. Legend guards these on an optional property with IS NOT NULL;\n * it does not guard `=` (which a missing value never matches either) or `<>`.\n */\nconst GUARDED_COMPARISONS = new Set<ComparisonOperator>([\n ComparisonOperator.LESS_THAN, ComparisonOperator.GREATER_THAN, ComparisonOperator.LESS_THAN_OR_EQUAL_TO,\n ComparisonOperator.GREATER_THAN_OR_EQUAL_TO, ComparisonOperator.LIKE,\n]);\n\nconst WINDOW_SQL_NAMES: Record<WindowFunction, string> = {\n [WindowFunction.ROW_NUMBER]: 'ROW_NUMBER',\n [WindowFunction.RANK]: 'RANK',\n [WindowFunction.DENSE_RANK]: 'DENSE_RANK',\n [WindowFunction.NTILE]: 'NTILE',\n [WindowFunction.LAG]: 'LAG',\n [WindowFunction.LEAD]: 'LEAD',\n [WindowFunction.FIRST_VALUE]: 'FIRST_VALUE',\n [WindowFunction.LAST_VALUE]: 'LAST_VALUE',\n [WindowFunction.CUME_DIST]: 'CUME_DIST',\n [WindowFunction.PERCENT_RANK]: 'PERCENT_RANK',\n};\n\nconst SCALAR_SQL_NAMES: Record<ScalarFunction, string> = {\n [ScalarFunction.ABS]: 'ABS',\n [ScalarFunction.CEILING]: 'CEILING',\n [ScalarFunction.FLOOR]: 'FLOOR',\n [ScalarFunction.MOD]: 'MOD',\n [ScalarFunction.POWER]: 'POWER',\n [ScalarFunction.SQRT]: 'SQRT',\n [ScalarFunction.ROUND]: 'ROUND',\n [ScalarFunction.UPPER]: 'UPPER',\n [ScalarFunction.LOWER]: 'LOWER',\n [ScalarFunction.TRIM]: 'TRIM',\n [ScalarFunction.LTRIM]: 'LTRIM',\n [ScalarFunction.RTRIM]: 'RTRIM',\n [ScalarFunction.LENGTH]: 'LENGTH',\n [ScalarFunction.REVERSE]: 'REVERSE',\n [ScalarFunction.LEFT]: 'LEFT',\n [ScalarFunction.RIGHT]: 'RIGHT',\n [ScalarFunction.REPEAT]: 'REPEAT',\n [ScalarFunction.REPLACE]: 'REPLACE',\n [ScalarFunction.SUBSTRING]: 'SUBSTRING',\n [ScalarFunction.COALESCE]: 'COALESCE',\n};\n\nfunction constantValueString(op: ConstantOperation, d: SqlDialect): string {\n if (op instanceof StringConstantOperation) return d.stringLiteral(op.value);\n if (op instanceof DateConstantOperation) return sqlFormatDate(op.value);\n if (op instanceof DateTimeConstantOperation) return sqlFormatDatetime(op.value);\n if (op instanceof IntegerConstantOperation) return String(op.value);\n if (op instanceof FloatConstantOperation) return Number.isInteger(op.value) && Math.abs(op.value) < 1e21 ? op.value.toFixed(1) : String(op.value); // 200.0, so it stays a float\n if (op instanceof BooleanConstantOperation) return op.value ? 'TRUE' : 'FALSE';\n if (op instanceof DecimalConstantOperation) return String(op.value);\n throw new Error('Unknown constant operation');\n}\n\n/**\n * A constant in the select list. A bare quoted literal would come back as text, so dates are typed, and a\n * bare 1.5 would come back as a DECIMAL, so a float is cast to DOUBLE.\n */\nfunction selectedConstantString(op: ConstantOperation, d: SqlDialect): string {\n if (op instanceof FloatConstantOperation) return 'CAST(' + constantValueString(op, d) + ' AS ' + d.doubleType + ')';\n if (op instanceof DateTimeConstantOperation) return 'TIMESTAMP ' + constantValueString(op, d);\n if (op instanceof DateConstantOperation) return 'DATE ' + constantValueString(op, d);\n return constantValueString(op, d);\n}\n\nfunction windowSpecToString(window: WindowSpecification, d: SqlDialect): string {\n const parts: string[] = [];\n if (window.partitionBy.length > 0) {\n parts.push('PARTITION BY ' + window.partitionBy.map(p => sqlOperationToString(p, d)).join(', '));\n }\n if (window.orderBy.length > 0) {\n parts.push('ORDER BY ' + window.orderBy.map(s =>\n sqlOperationToString(s.column, d) + d.orderDirection(s.direction),\n ).join(', '));\n }\n return 'OVER (' + parts.join(' ') + ')';\n}\n\nconst ARITHMETIC_PRECEDENCE: Record<ArithmeticOperator, number> = {\n [ArithmeticOperator.ADD]: 1,\n [ArithmeticOperator.SUBTRACT]: 1,\n [ArithmeticOperator.MULTIPLY]: 2,\n [ArithmeticOperator.DIVIDE]: 2,\n};\n\n/**\n * Whether `child` must be parenthesised as an operand of `parent`: it binds more loosely than the parent, or it\n * is the right operand of a - or / and binds equally (a - (b - c) is not a - b - c).\n */\nexport function arithmeticNeedsParentheses(parent: ArithmeticOperation, child: RelationalOperationElement, onRight: boolean): boolean {\n if (!(child instanceof ArithmeticOperation)) return false;\n const here = ARITHMETIC_PRECEDENCE[parent.operator];\n const there = ARITHMETIC_PRECEDENCE[child.operator];\n return there < here || (there === here && onRight\n && (parent.operator === ArithmeticOperator.SUBTRACT || parent.operator === ArithmeticOperator.DIVIDE));\n}\n\nfunction operandString(operation: RelationalOperationElement, d: SqlDialect): string {\n return operation instanceof ConstantOperation ? constantValueString(operation, d) : sqlOperationToString(operation, d);\n}\n\n/**\n * A condition or CASE already written as SQL, to be selected as a column. It is rendered while the query is being\n * built, where its columns can be resolved to table aliases, not when the text of the select is put together.\n */\nclass RenderedSql extends RelationalOperationElement {\n constructor(readonly sql: string) { super(); }\n}\n\nfunction isCondition(op: unknown): boolean {\n return op instanceof ComparisonOperation || op instanceof LogicalOperation || op instanceof IsNullOperation\n || op instanceof IsNotNullOperation || op instanceof InOperation || op instanceof NotInOperation\n || op instanceof ExistsOperation || op instanceof NotExistsOperation;\n}\n\nfunction sqlOperationToString(operation: RelationalOperationElement, d: SqlDialect): string {\n if (operation instanceof TableAliasColumn) {\n return operation.tableAlias.alias + '.' + operation.column.name;\n }\n if (operation instanceof WindowFunctionOperation) {\n const fn = WINDOW_SQL_NAMES[operation.func];\n const parts: string[] = [];\n if (operation.element !== null && operation.element !== undefined) {\n parts.push(sqlOperationToString(operation.element, d));\n }\n if (operation.secondArg !== undefined) parts.push(String(operation.secondArg));\n for (const arg of operation.extraArgs) {\n parts.push(typeof arg === 'string' ? d.stringLiteral(arg) : String(arg));\n }\n const sql = fn + '(' + parts.join(', ') + ')';\n return sql + (operation.window !== undefined ? ' ' + windowSpecToString(operation.window, d) : ' OVER ()');\n }\n if (operation instanceof AggregateOperation && operation.operator === AggregateOperator.COUNT_DISTINCT) {\n return 'COUNT(DISTINCT ' + sqlOperationToString(operation.element, d) + ')';\n }\n if (operation instanceof AggregateOperation && operation.operator === AggregateOperator.STRING_AGG) {\n let sql = d.stringAgg(\n sqlOperationToString(operation.element, d),\n d.stringLiteral(operation.separator ?? ''),\n operation.orderBy.map(s => sqlOperationToString(s.column, d) + d.orderDirection(s.direction)),\n );\n if (operation.window !== undefined) sql += ' ' + windowSpecToString(operation.window, d);\n return sql;\n }\n if (operation instanceof AggregateOperation) {\n const fn = AGGREGATE_SQL_NAMES[operation.operator] ?? operation.operator;\n let sql = fn + '(' + sqlOperationToString(operation.element, d) + ')';\n if (operation.window !== undefined) {\n sql += ' ' + windowSpecToString(operation.window, d);\n }\n return sql;\n }\n if (operation instanceof ScalarFunctionOperation) {\n const fn = SCALAR_SQL_NAMES[operation.func];\n const parts: string[] = [sqlOperationToString(operation.element, d)];\n if (operation.secondArg !== undefined) parts.push(String(operation.secondArg));\n for (const arg of operation.extraArgs) {\n parts.push(typeof arg === 'string' ? d.stringLiteral(arg) : String(arg));\n }\n return fn + '(' + parts.join(', ') + ')';\n }\n if (operation instanceof DateExtractOperation) {\n const element = sqlOperationToString(operation.element, d);\n return operation.part === DatePart.DOW ? d.dayOfWeek(element) : 'EXTRACT(' + operation.part + ' FROM ' + element + ')';\n }\n if (operation instanceof DateTruncOperation) {\n return \"CAST(DATE_TRUNC('\" + operation.part.toLowerCase() + \"', \" + sqlOperationToString(operation.element, d) + ') AS DATE)';\n }\n if (operation instanceof DateArithmeticOperation) {\n const op = operation.isAdd ? '+' : '-';\n return sqlOperationToString(operation.element, d) + ' ' + op + \" INTERVAL '\" + operation.n + \"' \" + operation.unit;\n }\n if (operation instanceof DateDiffOperation) {\n return d.dateDiff(operation.unit, sqlOperationToString(operation.element, d), 'TIMESTAMP ' + sqlFormatDatetime(operation.other));\n }\n if (operation instanceof CountAllOperation) return 'COUNT(*)';\n if (operation instanceof ConstantOperation) return selectedConstantString(operation, d);\n if (operation instanceof RenderedSql) return operation.sql;\n if (operation instanceof ConcatOperation) return operation.parts.map(part => operandString(part, d)).join(' || ');\n if (operation instanceof ArithmeticOperation) {\n let left = operandString(operation.left, d);\n let right = operandString(operation.right, d);\n if (arithmeticNeedsParentheses(operation, operation.left, false)) left = '(' + left + ')';\n if (arithmeticNeedsParentheses(operation, operation.right, true)) right = '(' + right + ')';\n return left + ' ' + operation.operator + ' ' + right;\n }\n if (operation instanceof Alias) {\n return sqlOperationToString(operation.element, d) + ' AS ' + d.quoteIdentifier(operation.name);\n }\n throw new TypeError('Unknown operation in sqlOperationToString: ' + operation.constructor.name);\n}\n\nfunction embeddedOf(ref: Attribute | ColumnWithJoin): Attribute | ColumnWithJoin | undefined {\n return ref instanceof Attribute ? ref.embedded() : ref.embedded;\n}\n\nfunction findColumn(operation: RelationalOperationElement): ColumnWithJoin {\n if (operation instanceof UnaryOperation) return findColumn(operation.element);\n if (operation instanceof ColumnWithJoin) return operation;\n throw new TypeError('Cannot find ColumnWithJoin in: ' + operation.constructor.name);\n}\n\nfunction openEndClause(\n endAttr: DateTimeAttribute | DateAttribute,\n value: Date,\n infiniteDatetime?: string,\n): Operation {\n const gtOp = endAttr instanceof DateTimeAttribute ? endAttr.gt(value) : endAttr.gt(value);\n if (infiniteDatetime === undefined) {\n const colRef = new ColumnWithJoin(endAttr.column(), endAttr.parent());\n return new LogicalOperation(gtOp, LogicalOperator.OR, new IsNullOperation(colRef));\n }\n return gtOp;\n}\n\n/** The operations ANDed together left to right, ignoring the missing ones; null if there are none. */\nfunction andAll(ops: (Operation | null)[]): Operation | null {\n const present = ops.filter((op): op is Operation => op !== null);\n if (present.length === 0) return null;\n return present.slice(1).reduce<Operation>((left, right) => new LogicalOperation(left, LogicalOperator.AND, right), present[0]);\n}\n\n/** The table's processing range contains the processing date. */\nfunction processingPredicate(\n mc: MilestoningColumns,\n processingDatetime: Date | null,\n joinNode?: JoinTreeNodeOperation,\n): Operation | null {\n if (!(mc instanceof ProcessingTemporalColumns || mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof BiTemporalColumns)\n || processingDatetime === null) return null;\n const startAt = new DateTimeAttribute('start_at', mc.startAtColumn.name, mc.startAtColumn.type, mc.startAtColumn.table!.qualifiedName, joinNode);\n const endAt = new DateTimeAttribute('end_at', mc.endAtColumn.name, mc.endAtColumn.type, mc.endAtColumn.table!.qualifiedName, joinNode);\n return new LogicalOperation(startAt.lte(processingDatetime), LogicalOperator.AND, openEndClause(endAt, processingDatetime, mc.infiniteDatetime));\n}\n\n/** The table's business range contains the business date, or its business date column equals it. */\nfunction businessPredicate(\n mc: MilestoningColumns,\n businessDate: Date | null,\n joinNode?: JoinTreeNodeOperation,\n): Operation | null {\n if (businessDate === null) return null;\n if (mc instanceof BiTemporalColumns) {\n const dateFrom = new DateAttribute('business_date_from', mc.businessDateFromColumn.name, mc.businessDateFromColumn.type, mc.businessDateFromColumn.table!.qualifiedName, joinNode);\n const dateTo = new DateAttribute('business_date_to', mc.businessDateToColumn.name, mc.businessDateToColumn.type, mc.businessDateToColumn.table!.qualifiedName, joinNode);\n return new LogicalOperation(dateFrom.lte(businessDate), LogicalOperator.AND, openEndClause(dateTo, businessDate, mc.infiniteDatetime));\n }\n if (mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof SingleBusinessDateColumn) {\n const businessAtt = new DateAttribute('business_date', mc.businessDateColumn.name, mc.businessDateColumn.type, mc.businessDateColumn.table!.qualifiedName, joinNode);\n return businessAtt.eq(businessDate);\n }\n return null;\n}\n\n/** The table's business range overlaps the business date range, or its business date column is within it. */\nfunction businessRangePredicate(\n mc: MilestoningColumns,\n businessDateFrom: Date | null,\n businessDateTo: Date | null,\n joinNode?: JoinTreeNodeOperation,\n): Operation | null {\n if (businessDateFrom === null || businessDateTo === null) return null;\n if (mc instanceof BiTemporalColumns) {\n const dateFrom = new DateAttribute('business_date_from', mc.businessDateFromColumn.name, mc.businessDateFromColumn.type, mc.businessDateFromColumn.table!.qualifiedName, joinNode);\n const dateTo = new DateAttribute('business_date_to', mc.businessDateToColumn.name, mc.businessDateToColumn.type, mc.businessDateToColumn.table!.qualifiedName, joinNode);\n return new LogicalOperation(dateFrom.lte(businessDateTo), LogicalOperator.AND, openEndClause(dateTo, businessDateFrom, mc.infiniteDatetime));\n }\n if (mc instanceof BusinessDateAndProcessingTemporalColumns || mc instanceof SingleBusinessDateColumn) {\n const businessAtt = new DateAttribute('business_date', mc.businessDateColumn.name, mc.businessDateColumn.type, mc.businessDateColumn.table!.qualifiedName, joinNode);\n return new LogicalOperation(businessAtt.gte(businessDateFrom), LogicalOperator.AND, businessAtt.lte(businessDateTo));\n }\n return null;\n}\n\n/** The milestoning filter for a point in time: the processing range, then the business range, ANDed together. */\nfunction buildMilestoningFilterOperation(\n businessDate: Date | null,\n processingDatetime: Date | null,\n table: MilestonedTable,\n joinNode?: JoinTreeNodeOperation,\n): Operation | null {\n const mc = table.milestoningColumns;\n return andAll([processingPredicate(mc, processingDatetime, joinNode), businessPredicate(mc, businessDate, joinNode)]);\n}\n\n/**\n * Like buildMilestoningFilterOperation but applies a business-date range filter.\n *\n * Bitemporal tables use interval overlap:\n * business_date_from_col <= businessDateTo AND business_date_to_col > businessDateFrom\n * Single-date tables:\n * business_date >= businessDateFrom AND business_date <= businessDateTo\n * Processing-date filtering is point-in-time, as in the normal path.\n */\nfunction buildMilestoningFilterOperationForDateRange(\n businessDateFrom: Date | null,\n businessDateTo: Date | null,\n processingDatetime: Date | null,\n table: MilestonedTable,\n joinNode?: JoinTreeNodeOperation,\n): Operation | null {\n const mc = table.milestoningColumns;\n return andAll([\n processingPredicate(mc, processingDatetime, joinNode),\n businessRangePredicate(mc, businessDateFrom, businessDateTo, joinNode),\n ]);\n}\n\ntype RefVisitor = (ref: Attribute | ColumnWithJoin) => void;\n\ntype NodeVisitor = (node: JoinTreeNodeOperation) => void;\n\n/**\n * Call `visit` for every Attribute/ColumnWithJoin referenced anywhere in `op`, and `visitExists` for the\n * join node of every exists()/notExists(). The latter are not attribute references, so they don't count\n * against whether other references to the same node can be satisfied by an embedded alternate.\n */\nfunction walkRefs(\n op: RelationalOperationElement | null | undefined,\n visit: RefVisitor,\n visitExists?: NodeVisitor,\n): void {\n if (op === null || op === undefined) return;\n if (op instanceof Attribute || op instanceof ColumnWithJoin) {\n visit(op);\n } else if (op instanceof ExistsOperation || op instanceof NotExistsOperation) {\n visitExists?.(op.node);\n } else if (op instanceof AggregateOperation) {\n walkRefs(op.element, visit, visitExists);\n if (op.window) walkWindowSpec(op.window, visit, visitExists);\n for (const sort of op.orderBy) walkRefs(sort, visit, visitExists);\n } else if (op instanceof WindowFunctionOperation) {\n if (op.element) walkRefs(op.element, visit, visitExists);\n if (op.window) walkWindowSpec(op.window, visit, visitExists);\n } else if (op instanceof ScalarFunctionOperation || op instanceof DateExtractOperation || op instanceof DateTruncOperation ||\n op instanceof DateArithmeticOperation || op instanceof DateDiffOperation ||\n op instanceof IsNullOperation || op instanceof IsNotNullOperation ||\n op instanceof InOperation || op instanceof NotInOperation) {\n walkRefs((op as UnaryOperation).element, visit, visitExists);\n } else if (op instanceof Alias) {\n walkRefs(op.element, visit, visitExists);\n } else if (op instanceof ConcatOperation) {\n for (const part of op.parts) walkRefs(part, visit, visitExists);\n } else if (op instanceof ArithmeticOperation) {\n walkRefs(op.left, visit, visitExists);\n walkRefs(op.right, visit, visitExists);\n } else if (op instanceof CaseOperation) {\n walkRefs(op.condition, visit, visitExists);\n walkRefs(op.then, visit, visitExists);\n walkRefs(op.fallback, visit, visitExists);\n } else if (op instanceof SortOperation) {\n walkRefs(op.column, visit, visitExists);\n } else if (op instanceof LogicalOperation || op instanceof ComparisonOperation) {\n walkRefs((op as any).left, visit, visitExists);\n walkRefs((op as any).right, visit, visitExists);\n }\n}\n\nfunction walkWindowSpec(window: WindowSpecification, visit: RefVisitor, visitExists?: NodeVisitor): void {\n for (const p of window.partitionBy) walkRefs(p, visit, visitExists);\n for (const s of window.orderBy) walkRefs(s.column, visit, visitExists);\n}\n\n/**\n * Translate property-equality filters given to a related finder (e.g. `ef.projects({ code: 'ALPHA' })`)\n * into a relational filter on the join node. `columnMap` maps property ids to [column, type, table].\n */\nfunction buildJoinFilterFromProperties(\n node: JoinTreeNodeOperation,\n filter: Record<string, unknown>,\n columnMap: Record<string, [string, string, string]>,\n): Operation {\n const ops: Operation[] = [];\n for (const [key, value] of Object.entries(filter)) {\n const entry = columnMap[key];\n if (entry === undefined) {\n throw new Error(`Unknown property '${key}' — valid properties are: ${Object.keys(columnMap).sort().join(', ')}`);\n }\n const [name, type, table] = entry;\n const col = new ColumnWithJoin(new Column(name, type, table), node);\n let constant: ConstantOperation;\n if (typeof value === 'boolean') constant = new BooleanConstantOperation(value);\n else if (typeof value === 'number') constant = Number.isInteger(value) ? new IntegerConstantOperation(value) : new FloatConstantOperation(value);\n else if (value instanceof Date) constant = type.toUpperCase() === 'DATE' ? new DateConstantOperation(value) : new DateTimeConstantOperation(value);\n else constant = new StringConstantOperation(String(value));\n ops.push(new ComparisonOperation(col, ComparisonOperator.EQUAL, constant));\n }\n return ops.reduce((acc, op) => new LogicalOperation(acc, LogicalOperator.AND, op));\n}\n\n/**\n * The nodes plus every ancestor, each once, ancestors first. The SQL generator joins a node's\n * ancestors whenever it joins the node, so each of them needs its join filter set too, not only the\n * nodes an expression refers to directly.\n */\nfunction withAncestors(nodes: Iterable<JoinTreeNodeOperation>): JoinTreeNodeOperation[] {\n const ordered = new Set<JoinTreeNodeOperation>();\n const add = (node: JoinTreeNodeOperation): void => {\n if (ordered.has(node)) return;\n if (node.parent !== undefined) add(node.parent);\n ordered.add(node);\n };\n for (const node of nodes) add(node);\n return [...ordered];\n}\n\nfunction buildQueryOperation(\n businessDate: Date | null,\n processingDatetime: Date | null,\n columns: (Attribute | RelationalOperationElement)[],\n table: Table,\n op: RelationalOperationElement,\n orderBy: SortOperation[] = [],\n groupBy: Attribute[] = [],\n limit?: number,\n businessDateTo: Date | null = null,\n distinct: boolean = false,\n offset?: number,\n having?: Operation,\n): SelectOperation {\n let filter = op;\n const milestoningFor = (t: MilestonedTable, node?: JoinTreeNodeOperation) =>\n businessDateTo !== null\n ? buildMilestoningFilterOperationForDateRange(businessDate, businessDateTo, processingDatetime, t, node)\n : buildMilestoningFilterOperation(businessDate, processingDatetime, t, node);\n\n if (table instanceof MilestonedTable) {\n const milestonedOp = milestoningFor(table);\n if (milestonedOp !== null) {\n filter = filter instanceof NoOperation\n ? milestonedOp\n : new LogicalOperation(filter, LogicalOperator.AND, milestonedOp);\n }\n }\n\n const requiredJoins = new Set<JoinTreeNodeOperation>();\n const collect: RefVisitor = ref => {\n const parent = ref instanceof Attribute ? ref.parent() : ref.parent;\n if (parent !== undefined) requiredJoins.add(parent);\n };\n const collectNode: NodeVisitor = node => requiredJoins.add(node);\n for (const col of columns) walkRefs(col, collect, collectNode);\n for (const expr of groupBy) walkRefs(expr, collect, collectNode);\n for (const sort of orderBy) walkRefs(sort, collect, collectNode);\n walkRefs(op, collect, collectNode);\n\n const joinFilters = new Map<JoinTreeNodeOperation, Operation>();\n for (const node of withAncestors(requiredJoins)) {\n let combined: Operation | undefined;\n if (Object.keys(node.join.filterKwargs).length > 0) {\n combined = buildJoinFilterFromProperties(node, node.join.filterKwargs, node.join.filterColumnMap);\n }\n if (node.join.target instanceof MilestonedTable) {\n const milestonedOp = milestoningFor(node.join.target, node);\n if (milestonedOp !== null) {\n combined = combined === undefined ? milestonedOp : new LogicalOperation(combined, LogicalOperator.AND, milestonedOp);\n }\n }\n if (combined !== undefined) joinFilters.set(node, combined);\n }\n\n return new SelectOperation(columns, filter, orderBy, groupBy, limit, table, joinFilters, distinct, offset, having);\n}\n\n/**\n * Whether `child` must be parenthesised where it is an operand of `parent`.\n *\n * A logical operation nested in one with a different operator is parenthesised: OR inside AND would\n * otherwise change meaning, and AND inside OR is easier to read. The same operator needs none, since\n * AND and OR are associative, so a AND (b AND c) is a AND b AND c.\n */\nexport function needsParentheses(parent: LogicalOperation, child: RelationalOperationElement): boolean {\n return child instanceof LogicalOperation && child.operator !== parent.operator;\n}\n\n/** Whether a value is read through a to-many association, so it repeats the row it is read for. */\nfunction reachesToMany(op: RelationalOperationElement): boolean {\n if (op instanceof ColumnWithJoin) {\n for (let node = op.parent; node !== undefined; node = node.parent) if (node.many) return true;\n return false;\n }\n if (op instanceof UnaryOperation || op instanceof Alias) return reachesToMany(op.element);\n if (op instanceof BinaryOperation) return reachesToMany(op.left) || reachesToMany(op.right);\n return false;\n}\n\n/** A column with any alias around it taken off. */\nfunction unaliased(op: unknown): unknown {\n return op instanceof Alias ? unaliased(op.element) : op;\n}\n\nclass SQLQueryGenerator {\n constructor(private readonly _dialect: SqlDialect) {}\n\n private _select: Alias[] = [];\n private _from: Set<TableAlias> = new Set();\n private _join: Join[] = [];\n private _groupByParts: string[] = [];\n private _having = '';\n private _orderByParts: string[] = [];\n private _where = '';\n private _limit?: number;\n private _distinct = false;\n private _offset?: number;\n private _tableAliasIncr = 0;\n private _tableAliasesByTable = new Map<unknown, TableAlias>();\n private _addedJoinIds = new Set<JoinTreeNodeOperation>();\n private _rootTable?: Table;\n private _elidableNodes = new Set<JoinTreeNodeOperation>();\n private _joinFilters: ReadonlyMap<JoinTreeNodeOperation, Operation> = new Map();\n private _guardOptional = true;\n\n generate(select: SelectOperation): void {\n this._rootTable = select.table;\n this._elidableNodes = this._computeElidableNodes(select);\n this._joinFilters = select.joinFilters;\n if (this._rootTable !== undefined) {\n this._from.add(this._tableAliasForTable(this._rootTable.qualifiedName, this._rootTable.qualifiedName));\n }\n this.processSelect(select.display);\n this._where = this.buildFilter(select.filter);\n const groupByJoins = new Map<JoinTreeNodeOperation, JoinTreeNodeOperation>();\n for (const expr of select.groupBy) {\n this._collectRequiredJoins(expr, groupByJoins);\n }\n for (const node of groupByJoins.values()) {\n this._addJoin(node);\n }\n this._groupByParts = this._groupByPartsFor(select);\n this._having = '';\n if (select.having !== undefined) {\n const havingJoins = new Map<JoinTreeNodeOperation, JoinTreeNodeOperation>();\n this._collectRequiredJoins(select.having, havingJoins);\n for (const node of havingJoins.values()) this._addJoin(node);\n // HAVING filters the grouped result, which Legend does not guard: it is a filter on projected columns\n this._guardOptional = false;\n try {\n this._having = this.buildFilter(select.having);\n } finally {\n this._guardOptional = true;\n }\n }\n this._orderByParts = select.orderBy.map(s =>\n this._sortExpression(s.column) + this._dialect.orderDirection(s.direction),\n );\n this._limit = select.limit;\n this._distinct = select.distinct;\n this._offset = select.offset;\n }\n\n /**\n * The GROUP BY of a query: the grouping it was given, else the grouping its columns imply.\n *\n * Columns that are not aggregated are what the aggregates are computed for, so a query that selects both is\n * grouped by those columns (as a DataFrame's `groupby(columns).agg(...)` does). An aggregate read through a\n * to-many association is computed for each row of the root table, as Legend does, so the root's primary key\n * is grouped by too. A query that selects only aggregates over the root's own columns is not grouped: the\n * aggregate covers every row. A constant needs no grouping: a bare\n * `GROUP BY 7` would be a column position.\n */\n private _groupByPartsFor(select: SelectOperation): string[] {\n if (select.groupBy.length > 0) return select.groupBy.map(a => this._attrToColString(a as Attribute));\n const aggregates = select.display.filter(containsAggregate);\n if (aggregates.length === 0) return [];\n const perRoot = select.table !== undefined && aggregates.some(reachesToMany);\n const keys = perRoot ? select.table!.columns.filter(c => c.primaryKey).map(c => this._columnToString(c)) : [];\n const grouped = select.display\n .map((column, i) => ({ column, shown: this._select[i] }))\n .filter(({ column }) => !containsAggregateOrWindow(column) && !(unaliased(column) instanceof ConstantOperation))\n .map(({ shown }) => sqlOperationToString(shown.element, this._dialect));\n return [...new Set([...keys, ...grouped])];\n }\n\n /** What a sort orders by: a column, or an expression such as an aggregate. */\n private _sortExpression(expression: RelationalOperationElement): string {\n if (expression instanceof ColumnWithJoin || expression instanceof Attribute) return this.buildFilter(expression);\n return sqlOperationToString(this._rewriteOperation(expression), this._dialect);\n }\n\n private _columnToString(column: Column): string {\n return this._tableAliasForTable(column.owner!, column.owner!).alias + '.' + column.name;\n }\n\n private _attrToColString(attr: Attribute): string {\n const { column, parent } = this._resolve(attr);\n const ta = this._tableAliasForTable(column.owner!, parent ?? column.owner!);\n return ta.alias + '.' + column.name;\n }\n\n private _collectRequiredJoins(op: RelationalOperationElement | null | undefined, out: Map<JoinTreeNodeOperation, JoinTreeNodeOperation>): void {\n walkRefs(op, ref => {\n const { parent } = this._resolve(ref);\n if (parent !== undefined) out.set(parent, parent);\n });\n }\n\n /**\n * Determine upfront which join nodes can be satisfied entirely by embedded (join-less) alternates:\n * a node is elidable when every reference to it has an embedded alternate. A reference without one\n * (e.g. a milestoning column) keeps the join for every reference to that node.\n */\n private _computeElidableNodes(select: SelectOperation): Set<JoinTreeNodeOperation> {\n const refsByNode = new Map<JoinTreeNodeOperation, (Attribute | ColumnWithJoin)[]>();\n const record = (ref: Attribute | ColumnWithJoin) => {\n const parent = ref instanceof Attribute ? ref.parent() : ref.parent;\n if (parent === undefined) return;\n const refs = refsByNode.get(parent);\n if (refs) refs.push(ref); else refsByNode.set(parent, [ref]);\n };\n for (const col of select.display) walkRefs(col, record);\n for (const expr of select.groupBy) walkRefs(expr, record);\n for (const sort of select.orderBy) walkRefs(sort, record);\n walkRefs(select.filter, record);\n\n const elidable = new Set<JoinTreeNodeOperation>();\n for (const [node, refs] of refsByNode) {\n if (refs.every(ref => embeddedOf(ref) !== undefined)) elidable.add(node);\n }\n return elidable;\n }\n\n /** The (column, parent) a reference should resolve to, substituting its embedded alternate when its join is elided. */\n private _resolve(ref: Attribute | ColumnWithJoin): { column: Column; parent?: JoinTreeNodeOperation } {\n const column = ref instanceof Attribute ? ref.column() : ref.column;\n const parent = ref instanceof Attribute ? ref.parent() : ref.parent;\n if (parent !== undefined && this._elidableNodes.has(parent)) {\n const embedded = embeddedOf(ref);\n if (embedded !== undefined) return this._resolve(embedded);\n }\n return { column, parent };\n }\n\n /** Whether the value `op` reads can be missing, in the join or embedded form that is used for it. */\n private _resolveOptional(op: ColumnWithJoin): boolean {\n if (op.parent !== undefined && this._elidableNodes.has(op.parent) && op.embedded !== undefined) {\n return this._resolveOptional(op.embedded);\n }\n return op.optional;\n }\n\n private _rewriteWindowSpec(window: WindowSpecification): WindowSpecification {\n const partitionBy = window.partitionBy.map(p => this._rewriteOperation(p));\n const orderBy = window.orderBy.map(s => new SortOperation(this._rewriteOperation(s.column) as ColumnWithJoin, s.direction));\n return new WindowSpecification(partitionBy, orderBy);\n }\n\n private _rewriteOperation(op: RelationalOperationElement): RelationalOperationElement {\n if (op instanceof Attribute || op instanceof ColumnWithJoin) {\n const { column, parent } = this._resolve(op);\n return new TableAliasColumn(column, this._tableAliasForTable(column.owner!, parent ?? column.owner!));\n }\n if (op instanceof Column) {\n const ta = this._tableAliasForTable(op.owner!, op.owner!);\n return new TableAliasColumn(op, ta);\n }\n if (op instanceof AggregateOperation) {\n return new AggregateOperation(\n this._rewriteOperation(op.element), op.operator, op.displayName,\n op.window ? this._rewriteWindowSpec(op.window) : undefined,\n op.separator, op.orderBy.map(s => new SortOperation(this._rewriteOperation(s.column), s.direction)),\n );\n }\n if (op instanceof CaseOperation) return new RenderedSql(this._caseSql(op));\n if (isCondition(op)) return new RenderedSql(this.buildFilter(op as Operation)); // a condition inside an expression, such as the argument of an aggregate\n if (op instanceof ConcatOperation) return new ConcatOperation(op.parts.map(part => this._rewriteOperation(part)), op.displayName);\n if (op instanceof ArithmeticOperation) {\n return new ArithmeticOperation(this._rewriteOperation(op.left), op.operator, this._rewriteOperation(op.right), op.displayName);\n }\n if (op instanceof WindowFunctionOperation) {\n const el = op.element ? this._rewriteOperation(op.element) : null;\n return new WindowFunctionOperation(el, op.func, op.displayName, op.secondArg, [...op.extraArgs],\n op.window ? this._rewriteWindowSpec(op.window) : undefined);\n }\n if (op instanceof ScalarFunctionOperation) {\n return new ScalarFunctionOperation(this._rewriteOperation(op.element), op.func, op.displayName, op.secondArg, op.extraArgs);\n }\n if (op instanceof DateExtractOperation) {\n return new DateExtractOperation(this._rewriteOperation(op.element), op.part, op.displayName);\n }\n if (op instanceof DateTruncOperation) {\n return new DateTruncOperation(this._rewriteOperation(op.element), op.part, op.displayName);\n }\n if (op instanceof DateArithmeticOperation) {\n return new DateArithmeticOperation(this._rewriteOperation(op.element), op.n, op.unit, op.isAdd, op.displayName);\n }\n if (op instanceof DateDiffOperation) {\n return new DateDiffOperation(this._rewriteOperation(op.element), (op as DateDiffOperation).other, (op as DateDiffOperation).unit, op.displayName);\n }\n return op;\n }\n\n /** The CASE written out now: its condition can only be rendered while the query is being built. */\n private _caseSql(op: CaseOperation): string {\n const branch = (value: RelationalOperationElement): string =>\n value instanceof ConstantOperation ? constantValueString(value, this._dialect) : sqlOperationToString(this._rewriteOperation(value), this._dialect);\n let sql = 'CASE WHEN ' + this.buildFilter(op.condition) + ' THEN ' + branch(op.then);\n if (op.fallback !== undefined) sql += ' ELSE ' + branch(op.fallback);\n return sql + ' END';\n }\n\n private processSelect(cols: (Attribute | RelationalOperationElement)[]): void {\n const requiredJoins = new Map<JoinTreeNodeOperation, JoinTreeNodeOperation>();\n\n for (const col of cols) {\n this._collectRequiredJoins(col, requiredJoins);\n }\n for (const node of requiredJoins.values()) {\n this._addJoin(node);\n }\n\n for (const col of cols) this._selectColumn(col);\n }\n\n /** Add one column to the select list. An alias reads the column it wraps, then names the entry. */\n private _selectColumn(col: Attribute | RelationalOperationElement): void {\n if (col instanceof Alias) {\n this._selectColumn(col.element);\n const read = this._select.pop()!;\n this._select.push(new Alias(read.element, col.name));\n } else if (col instanceof Attribute) {\n const { column, parent: node } = this._resolve(col);\n let ta: TableAlias;\n if (node !== undefined) {\n ta = this._tableAliasForTable(column.owner!, node);\n } else {\n ta = this._tableAliasForTable(column.owner!, column.owner!);\n this._from.add(ta);\n }\n this._select.push(new Alias(new TableAliasColumn(column, ta), col.displayName()));\n } else if (col instanceof WindowFunctionOperation) {\n const rewritten = this._rewriteOperation(col) as WindowFunctionOperation;\n let alias: string;\n if (col.displayName) {\n alias = col.displayName;\n } else if ([WindowFunction.ROW_NUMBER, WindowFunction.RANK, WindowFunction.DENSE_RANK].includes(col.func)) {\n alias = col.func.replace(/_/g, ' ').replace(/\\b\\w/g, c => c.toUpperCase());\n } else if (col.element) {\n alias = col.func + ' ' + findColumn(col).column.name;\n } else {\n alias = col.func;\n }\n this._select.push(new Alias(rewritten, alias));\n } else if (col instanceof AggregateOperation && !(col.element instanceof ColumnWithJoin)) {\n // an aggregate of an expression: rewritten as a whole, so every column in it is resolved\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? 'Expression'));\n } else if (col instanceof AggregateOperation) {\n const colNested = this._resolve(findColumn(col));\n const node = colNested.parent;\n let ta: TableAlias;\n if (node !== undefined) {\n ta = this._tableAliasForTable(colNested.column.owner!, node);\n } else {\n ta = this._tableAliasForTable(colNested.column.owner!, colNested.column.owner!);\n this._from.add(ta);\n }\n const alias = col.displayName ?? col.operator + ' ' + findColumn(col).column.name;\n const rewrittenAgg = new AggregateOperation(\n new TableAliasColumn(colNested.column, ta), col.operator, undefined,\n col.window ? this._rewriteWindowSpec(col.window) : undefined,\n col.separator, col.orderBy.map(s => new SortOperation(this._rewriteOperation(s.column), s.direction)),\n );\n this._select.push(new Alias(rewrittenAgg, alias));\n } else if (col instanceof ScalarFunctionOperation) {\n // rewritten as a whole, so a function of a function keeps every step\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? col.func + ' ' + findColumn(col).column.name));\n } else if (col instanceof DateExtractOperation || col instanceof DateArithmeticOperation || col instanceof DateDiffOperation) {\n const colNested = this._resolve(findColumn(col as RelationalOperationElement));\n const node = colNested.parent;\n let ta: TableAlias;\n if (node !== undefined) {\n ta = this._tableAliasForTable(colNested.column.owner!, node);\n } else {\n ta = this._tableAliasForTable(colNested.column.owner!, colNested.column.owner!);\n this._from.add(ta);\n }\n const alias = (col as DateExtractOperation).displayName ?? findColumn(col as RelationalOperationElement).column.name;\n let aliasedOp: RelationalOperationElement;\n if (col instanceof DateExtractOperation) {\n aliasedOp = new DateExtractOperation(new TableAliasColumn(colNested.column, ta), col.part);\n } else if (col instanceof DateArithmeticOperation) {\n aliasedOp = new DateArithmeticOperation(new TableAliasColumn(colNested.column, ta), col.n, col.unit, col.isAdd);\n } else {\n aliasedOp = new DateDiffOperation(new TableAliasColumn(colNested.column, ta), (col as DateDiffOperation).other, (col as DateDiffOperation).unit);\n }\n this._select.push(new Alias(aliasedOp, alias));\n } else if (col instanceof CaseOperation) {\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? 'Expression'));\n } else if (col instanceof ConcatOperation) {\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? 'Expression'));\n } else if (col instanceof ArithmeticOperation) {\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? 'Expression'));\n } else if (col instanceof DateTruncOperation) {\n this._select.push(new Alias(this._rewriteOperation(col), col.displayName ?? findColumn(col).column.name));\n } else if (isCondition(col)) {\n this._select.push(new Alias(new RenderedSql(this.buildFilter(col)), 'Expression'));\n } else if (col instanceof ConstantOperation) {\n this._select.push(new Alias(col, 'Constant'));\n } else if (col instanceof CountAllOperation) {\n if (col.table !== '') this._from.add(this._tableAliasForTable(col.table, col.table));\n this._select.push(new Alias(col, 'Count'));\n }\n }\n\n private _addJoin(node: JoinTreeNodeOperation): void {\n if (this._addedJoinIds.has(node)) return;\n if (node.parent !== undefined) this._addJoin(node.parent);\n this._addedJoinIds.add(node);\n\n const join = node.join;\n const left = join.left;\n const srcTa = this._tableAliasForTable(left.owner!, node.parent ?? left.owner!);\n if (node.parent === undefined) this._from.add(srcTa);\n const sc = new TableAliasColumn(left, srcTa);\n const right = join.right;\n const tc = new TableAliasColumn(right, this._tableAliasForTable(right.owner!, node));\n const queryFilter = this._joinFilters.get(node);\n const filterOp = join.filter !== undefined && queryFilter !== undefined\n ? new LogicalOperation(join.filter as Operation, LogicalOperator.AND, queryFilter)\n : join.filter ?? queryFilter;\n this._join.push(new Join(sc, tc, filterOp));\n }\n\n buildFilter(op: RelationalOperationElement): string {\n if (op instanceof NoOperation) return '';\n if (op instanceof ExistsOperation) {\n const col = op.node.join.right;\n return this.buildFilter(new ColumnWithJoin(col, op.node)) + ' IS NOT NULL';\n }\n if (op instanceof NotExistsOperation) {\n const col = op.node.join.right;\n return this.buildFilter(new ColumnWithJoin(col, op.node)) + ' IS NULL';\n }\n if (op instanceof InOperation) {\n return this.buildFilter(op.element) + ' IN (' + op.values.map(value => constantValueString(value, this._dialect)).join(', ') + ')';\n }\n if (op instanceof NotInOperation) {\n const column = this.buildFilter(op.element);\n const sql = column + ' NOT IN (' + op.values.map(value => constantValueString(value, this._dialect)).join(', ') + ')';\n // NULL NOT IN (...) is not true in SQL, so a nullable column has to match its NULLs explicitly\n if (op.element instanceof ColumnWithJoin && this._resolve(op.element).column.nullable) {\n return '(' + sql + ' OR ' + column + ' IS NULL)';\n }\n return sql;\n }\n if (op instanceof IsNotNullOperation) return this.buildFilter(op.element) + ' IS NOT NULL';\n if (op instanceof IsNullOperation) return this.buildFilter(op.element) + ' IS NULL';\n if (op instanceof LogicalOperation) {\n let left = this.buildFilter(op.left);\n let right = this.buildFilter(op.right);\n if (needsParentheses(op, op.left)) left = '(' + left + ')';\n if (needsParentheses(op, op.right)) right = '(' + right + ')';\n return left + LOGICAL_OPERATOR_STR[op.operator] + right;\n }\n if (op instanceof ComparisonOperation) {\n let sql = this.buildFilter(op.left) + COMPARISON_OPERATOR_STR[op.operator] + this.buildFilter(op.right);\n if ((op.operator === ComparisonOperator.LIKE || op.operator === ComparisonOperator.NOT_LIKE)\n && op.right instanceof StringConstantOperation\n && (op.right.value.includes(LIKE_ESCAPE) || op.right.value.includes('\\\\'))) {\n // the pattern has a literal %, _ or escape character in it, or a backslash, which Postgres and Databricks\n // would otherwise take as LIKE's own escape\n sql += \" ESCAPE '\" + LIKE_ESCAPE + \"'\";\n }\n if (this._guardOptional && GUARDED_COMPARISONS.has(op.operator) && op.left instanceof ColumnWithJoin\n && this._resolveOptional(op.left)) {\n // as in Legend, an ordering or pattern comparison on an optional property says it needs a value\n sql = '(' + this.buildFilter(op.left) + ' IS NOT NULL AND ' + sql + ')';\n }\n return sql;\n }\n if (op instanceof ConstantOperation) return constantValueString(op, this._dialect);\n if (op instanceof ScalarFunctionOperation || op instanceof ArithmeticOperation || op instanceof ConcatOperation\n || op instanceof DateTruncOperation || op instanceof AggregateOperation || op instanceof CountAllOperation) {\n // an expression compared in a filter needs its columns' joins, then is written as in a select list\n const required = new Map<JoinTreeNodeOperation, JoinTreeNodeOperation>();\n this._collectRequiredJoins(op, required);\n for (const node of required.values()) this._addJoin(node);\n return sqlOperationToString(this._rewriteOperation(op), this._dialect);\n }\n if (op instanceof ColumnWithJoin) {\n const { column, parent: node } = this._resolve(op);\n let ta: TableAlias;\n if (node !== undefined) {\n ta = this._tableAliasForTable(column.owner!, node);\n this._addJoin(node);\n } else {\n ta = this._tableAliasForTable(column.owner!, column.owner!);\n }\n return ta.alias + '.' + column.name;\n }\n if (op instanceof Column) {\n const ta = this._tableAliasForTable(op.owner!, op.owner!);\n return ta.alias + '.' + op.name;\n }\n throw new Error('Unknown operation in buildFilter: ' + op.constructor.name);\n }\n\n private _tableAliasForTable(table: string, key: unknown): TableAlias {\n if (this._tableAliasesByTable.has(key)) {\n return this._tableAliasesByTable.get(key)!;\n }\n const ta = new TableAlias(table, 't' + this._tableAliasIncr++);\n this._tableAliasesByTable.set(key, ta);\n return ta;\n }\n\n buildQueryString(): string {\n const joins = this._join.map(j =>\n ' LEFT OUTER JOIN ' + j.target.tableAlias.table + ' AS ' + j.target.tableAlias.alias +\n ' ON (' + j.condition() +\n (j.filterOp ? ' AND ' + this.buildFilter(j.filterOp) : '') + ')',\n );\n\n return (this._distinct ? 'SELECT DISTINCT ' : 'SELECT ') + this._select.map(ca => sqlOperationToString(ca, this._dialect)).join(',') +\n ' FROM ' + Array.from(this._from).map(ta => ta.table + ' AS ' + ta.alias).join(',') +\n joins.join('') +\n this._buildWhere() +\n this._buildGroupBy() +\n this._buildHaving() +\n this._buildOrderBy() +\n this._buildLimit() +\n this._buildOffset();\n }\n\n private _buildWhere(): string {\n return this._where.length > 0 ? ' WHERE ' + this._where : '';\n }\n private _buildGroupBy(): string {\n return this._groupByParts.length > 0 ? ' GROUP BY ' + this._groupByParts.join(', ') : '';\n }\n private _buildHaving(): string {\n return this._having.length > 0 ? ' HAVING ' + this._having : '';\n }\n private _buildOrderBy(): string {\n return this._orderByParts.length > 0 ? ' ORDER BY ' + this._orderByParts.join(', ') : '';\n }\n private _buildOffset(): string {\n return this._offset !== undefined ? ' OFFSET ' + this._offset : '';\n }\n\n private _buildLimit(): string {\n return this._limit !== undefined ? ' LIMIT ' + this._limit : '';\n }\n}\n\nexport function selectSqlToString(selectOperation: SelectOperation, dialect: DialectName | SqlDialect = 'postgres'): string {\n const qg = new SQLQueryGenerator(dialectOf(dialect));\n qg.generate(selectOperation);\n return qg.buildQueryString();\n}\n\nexport function toSql(\n businessDate: Date | null,\n processingDatetime: Date | null,\n columns: (Attribute | RelationalOperationElement)[],\n table: Table,\n op: RelationalOperationElement,\n orderBy: SortOperation[] = [],\n groupBy: Attribute[] = [],\n limit?: number,\n businessDateTo: Date | null = null,\n distinct: boolean = false,\n offset?: number,\n having?: Operation,\n dialect: DialectName | SqlDialect = 'postgres',\n): string {\n const selectOp = buildQueryOperation(businessDate, processingDatetime, columns, table, op, orderBy, groupBy, limit, businessDateTo, distinct, offset, having);\n return selectSqlToString(selectOp, dialect);\n}\n\nexport { buildQueryOperation };\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Table
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PF6EJZHB.js";
|
|
4
4
|
|
|
5
5
|
// src/model/milestoning.ts
|
|
6
6
|
var MilestoningColumns = class {
|
|
@@ -87,4 +87,4 @@ export {
|
|
|
87
87
|
BiTemporalColumns,
|
|
88
88
|
MilestonedTable
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
90
|
+
//# sourceMappingURL=chunk-GPHWC533.js.map
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
toSql
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BKPWV3OF.js";
|
|
4
4
|
import {
|
|
5
|
+
ColumnWithJoin,
|
|
6
|
+
DATE_ONLY_PATTERN,
|
|
7
|
+
DateOnly,
|
|
5
8
|
NoOperation
|
|
6
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PF6EJZHB.js";
|
|
7
10
|
|
|
8
11
|
// src/datafinder/runner.ts
|
|
9
12
|
var DEFAULT_TIMEOUT_MS = 6e4;
|
|
@@ -26,6 +29,18 @@ function getRunner() {
|
|
|
26
29
|
if (!_runner) throw new Error("No query runner registered. Call registerRunner() first.");
|
|
27
30
|
return _runner;
|
|
28
31
|
}
|
|
32
|
+
var expressionIds = /* @__PURE__ */ new WeakMap();
|
|
33
|
+
var nextExpressionId = 1;
|
|
34
|
+
function sortTarget(sort) {
|
|
35
|
+
const column = sort.column;
|
|
36
|
+
if (!(column instanceof ColumnWithJoin)) {
|
|
37
|
+
if (!expressionIds.has(column)) expressionIds.set(column, nextExpressionId++);
|
|
38
|
+
return JSON.stringify(["expression", expressionIds.get(column)]);
|
|
39
|
+
}
|
|
40
|
+
const joins = [];
|
|
41
|
+
for (let node = column.parent; node !== void 0; node = node.parent) joins.push(node.join.name);
|
|
42
|
+
return JSON.stringify([column.column.owner, column.column.name, joins]);
|
|
43
|
+
}
|
|
29
44
|
var FinderResult = class {
|
|
30
45
|
constructor(_businessDate, _processingDatetime, _columns, _table, _op, _businessDateTo = null) {
|
|
31
46
|
this._businessDate = _businessDate;
|
|
@@ -44,12 +59,20 @@ var FinderResult = class {
|
|
|
44
59
|
_orderBy = [];
|
|
45
60
|
_groupBy = [];
|
|
46
61
|
_limit;
|
|
62
|
+
_distinct = false;
|
|
63
|
+
_offset;
|
|
64
|
+
_having;
|
|
47
65
|
_timeoutMs = DEFAULT_TIMEOUT_MS;
|
|
48
|
-
|
|
49
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Order the rows. Calls accumulate: the sorts of the latest call take priority and earlier ones order the
|
|
68
|
+
* rows it leaves tied, as in a chain of `sortBy` calls. Sorting a column again replaces its earlier direction.
|
|
69
|
+
*/
|
|
70
|
+
orderBy(...sorts) {
|
|
71
|
+
const resorted = new Set(sorts.map(sortTarget));
|
|
72
|
+
this._orderBy = [...sorts, ...this._orderBy.filter((s) => !resorted.has(sortTarget(s)))];
|
|
50
73
|
return this;
|
|
51
74
|
}
|
|
52
|
-
|
|
75
|
+
groupBy(...attrs) {
|
|
53
76
|
this._groupBy = attrs;
|
|
54
77
|
return this;
|
|
55
78
|
}
|
|
@@ -57,12 +80,40 @@ var FinderResult = class {
|
|
|
57
80
|
this._limit = n;
|
|
58
81
|
return this;
|
|
59
82
|
}
|
|
83
|
+
/** Skip the first `n` rows. Sort the rows first: without an order, which rows are first is not defined. */
|
|
84
|
+
offset(n) {
|
|
85
|
+
if (!Number.isInteger(n) || n < 0) throw new Error("offset cannot be negative");
|
|
86
|
+
this._offset = n;
|
|
87
|
+
return this;
|
|
88
|
+
}
|
|
89
|
+
/** Rows `start` up to but not including `stop`, counting from 0: `offset(start).limit(stop - start)`. */
|
|
90
|
+
slice(start, stop) {
|
|
91
|
+
if (!Number.isInteger(start) || !Number.isInteger(stop) || start < 0 || stop < start) {
|
|
92
|
+
throw new Error("slice needs 0 <= start <= stop");
|
|
93
|
+
}
|
|
94
|
+
return this.offset(start).limit(stop - start);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Keep the groups for which every condition holds: `HAVING`. A condition tests an aggregate or a grouping column:
|
|
98
|
+
* `f.findAll(null, null, [f.category(), countAll()]).groupBy(f.category()).having(countAll().gt(1))`.
|
|
99
|
+
* Calls accumulate, as `and` does.
|
|
100
|
+
*/
|
|
101
|
+
having(...conditions) {
|
|
102
|
+
for (const condition of conditions) this._having = this._having === void 0 ? condition : this._having.and(condition);
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
/** Return each distinct row once: `SELECT DISTINCT`. A sort on a distinct query has to use a selected column. */
|
|
106
|
+
distinct() {
|
|
107
|
+
this._distinct = true;
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
60
110
|
/** Abort the query and throw QueryTimeoutError if it runs longer than `milliseconds` (default 60000). */
|
|
61
111
|
timeout(milliseconds) {
|
|
62
112
|
this._timeoutMs = milliseconds;
|
|
63
113
|
return this;
|
|
64
114
|
}
|
|
65
|
-
toSql()
|
|
115
|
+
/** The query as SQL, in Postgres unless a dialect is given: `toSql('databricks')`. Nothing is run. */
|
|
116
|
+
toSql(dialect = "postgres") {
|
|
66
117
|
return toSql(
|
|
67
118
|
this._businessDate,
|
|
68
119
|
this._processingDatetime,
|
|
@@ -72,7 +123,11 @@ var FinderResult = class {
|
|
|
72
123
|
this._orderBy,
|
|
73
124
|
this._groupBy,
|
|
74
125
|
this._limit,
|
|
75
|
-
this._businessDateTo
|
|
126
|
+
this._businessDateTo,
|
|
127
|
+
this._distinct,
|
|
128
|
+
this._offset,
|
|
129
|
+
this._having,
|
|
130
|
+
dialect
|
|
76
131
|
);
|
|
77
132
|
}
|
|
78
133
|
async toRows() {
|
|
@@ -86,15 +141,22 @@ var FinderResult = class {
|
|
|
86
141
|
this._groupBy,
|
|
87
142
|
this._limit,
|
|
88
143
|
this._timeoutMs,
|
|
89
|
-
this._businessDateTo
|
|
144
|
+
this._businessDateTo,
|
|
145
|
+
this._distinct,
|
|
146
|
+
this._offset,
|
|
147
|
+
this._having
|
|
90
148
|
);
|
|
91
149
|
}
|
|
92
150
|
};
|
|
151
|
+
function convertProcessingDate(value) {
|
|
152
|
+
if (typeof value === "string" && DATE_ONLY_PATTERN.test(value)) return new DateOnly(value + "T00:00:00Z");
|
|
153
|
+
return convertDate(value);
|
|
154
|
+
}
|
|
93
155
|
function convertDate(value) {
|
|
94
156
|
if (value === null) return null;
|
|
95
157
|
if (value instanceof Date) return value;
|
|
96
158
|
let normalized = value;
|
|
97
|
-
if (
|
|
159
|
+
if (DATE_ONLY_PATTERN.test(value)) normalized = value + "T00:00:00Z";
|
|
98
160
|
else if (/^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(value)) normalized = value.replace(" ", "T") + "Z";
|
|
99
161
|
const d = new Date(normalized);
|
|
100
162
|
if (isNaN(d.getTime())) throw new Error(`Cannot parse date: ${value}`);
|
|
@@ -103,7 +165,7 @@ function convertDate(value) {
|
|
|
103
165
|
function convertInputsAndSelect(businessDate, processingDatetime, columns, table, op = new NoOperation()) {
|
|
104
166
|
return new FinderResult(
|
|
105
167
|
convertDate(businessDate),
|
|
106
|
-
|
|
168
|
+
convertProcessingDate(processingDatetime),
|
|
107
169
|
columns,
|
|
108
170
|
table,
|
|
109
171
|
op
|
|
@@ -115,7 +177,7 @@ function convertInputsAndSelectForDateRange(businessDateFrom, businessDateTo, pr
|
|
|
115
177
|
if (processingDatetime == null) throw new Error("processingValidAt is required for findForDateRange");
|
|
116
178
|
return new FinderResult(
|
|
117
179
|
convertDate(businessDateFrom),
|
|
118
|
-
|
|
180
|
+
convertProcessingDate(processingDatetime),
|
|
119
181
|
columns,
|
|
120
182
|
table,
|
|
121
183
|
op,
|
|
@@ -133,4 +195,4 @@ export {
|
|
|
133
195
|
convertInputsAndSelect,
|
|
134
196
|
convertInputsAndSelectForDateRange
|
|
135
197
|
};
|
|
136
|
-
//# sourceMappingURL=chunk-
|
|
198
|
+
//# sourceMappingURL=chunk-KAK75RVS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/datafinder/runner.ts"],"sourcesContent":["import { Attribute } from './attribute';\nimport { toSql } from './sql-generator';\nimport { DialectName, SqlDialect } from './dialect';\nimport {\n Table,\n Operation,\n SortOperation,\n NoOperation,\n RelationalOperationElement,\n ColumnWithJoin,\n DateOnly,\n DATE_ONLY_PATTERN,\n} from '../model/relational';\n\nexport type Row = unknown[];\n\nexport const DEFAULT_TIMEOUT_MS = 60_000;\n\n/** Thrown by a QueryRunner when a query runs longer than the timeout set on its FinderResult. */\nexport class QueryTimeoutError extends Error {\n constructor(readonly timeoutMs: number) {\n super(`Query exceeded ${timeoutMs}ms timeout`);\n this.name = 'QueryTimeoutError';\n }\n}\n\n/** Minimum interface satisfied by both Table (SQL) and GraphQLQuery (GraphQL). */\nexport interface QueryTarget {\n readonly name: string;\n}\n\nexport interface QueryRunner {\n /** The SQL a runner that executes SQL sends: `toSql()` writes it for this dialect. Postgres when absent. */\n readonly dialect?: DialectName | SqlDialect;\n\n select(\n businessDate: Date | null,\n processingDatetime: Date | null,\n columns: (Attribute | RelationalOperationElement)[],\n table: QueryTarget,\n op: RelationalOperationElement,\n orderBy?: SortOperation[],\n groupBy?: Attribute[],\n limit?: number,\n timeoutMs?: number,\n businessDateTo?: Date | null,\n distinct?: boolean,\n offset?: number,\n having?: Operation,\n ): Promise<Row[]>;\n}\n\nlet _runner: QueryRunner | null = null;\n\nexport function registerRunner(runner: QueryRunner): void { _runner = runner; }\nexport function clearRunner(): void { _runner = null; }\nexport function getRunner(): QueryRunner {\n if (!_runner) throw new Error('No query runner registered. Call registerRunner() first.');\n return _runner;\n}\n\nconst expressionIds = new WeakMap<object, number>();\nlet nextExpressionId = 1;\n\n/**\n * What a sort orders by: a column and the joins to reach it. Any other expression, such as an aggregate, is its\n * own target, so sorting by an expression again adds a sort.\n */\nfunction sortTarget(sort: SortOperation): string {\n const column = sort.column;\n if (!(column instanceof ColumnWithJoin)) {\n if (!expressionIds.has(column)) expressionIds.set(column, nextExpressionId++);\n return JSON.stringify(['expression', expressionIds.get(column)]);\n }\n const joins: string[] = [];\n for (let node = column.parent; node !== undefined; node = node.parent) joins.push(node.join.name);\n return JSON.stringify([column.column.owner, column.column.name, joins]);\n}\n\nexport class FinderResult {\n private _orderBy: SortOperation[] = [];\n private _groupBy: Attribute[] = [];\n private _limit?: number;\n private _distinct = false;\n private _offset?: number;\n private _having?: Operation;\n private _timeoutMs: number = DEFAULT_TIMEOUT_MS;\n\n constructor(\n private readonly _businessDate: Date | null,\n private readonly _processingDatetime: Date | null,\n private readonly _columns: (Attribute | RelationalOperationElement)[],\n private readonly _table: QueryTarget,\n private readonly _op: RelationalOperationElement,\n private readonly _businessDateTo: Date | null = null,\n ) {}\n\n /**\n * Order the rows. Calls accumulate: the sorts of the latest call take priority and earlier ones order the\n * rows it leaves tied, as in a chain of `sortBy` calls. Sorting a column again replaces its earlier direction.\n */\n orderBy(...sorts: SortOperation[]): this {\n const resorted = new Set(sorts.map(sortTarget));\n this._orderBy = [...sorts, ...this._orderBy.filter(s => !resorted.has(sortTarget(s)))];\n return this;\n }\n\n groupBy(...attrs: Attribute[]): this {\n this._groupBy = attrs;\n return this;\n }\n\n limit(n: number): this {\n this._limit = n;\n return this;\n }\n\n /** Skip the first `n` rows. Sort the rows first: without an order, which rows are first is not defined. */\n offset(n: number): this {\n if (!Number.isInteger(n) || n < 0) throw new Error('offset cannot be negative');\n this._offset = n;\n return this;\n }\n\n /** Rows `start` up to but not including `stop`, counting from 0: `offset(start).limit(stop - start)`. */\n slice(start: number, stop: number): this {\n if (!Number.isInteger(start) || !Number.isInteger(stop) || start < 0 || stop < start) {\n throw new Error('slice needs 0 <= start <= stop');\n }\n return this.offset(start).limit(stop - start);\n }\n\n /**\n * Keep the groups for which every condition holds: `HAVING`. A condition tests an aggregate or a grouping column:\n * `f.findAll(null, null, [f.category(), countAll()]).groupBy(f.category()).having(countAll().gt(1))`.\n * Calls accumulate, as `and` does.\n */\n having(...conditions: Operation[]): this {\n for (const condition of conditions) this._having = this._having === undefined ? condition : this._having.and(condition) as Operation;\n return this;\n }\n\n /** Return each distinct row once: `SELECT DISTINCT`. A sort on a distinct query has to use a selected column. */\n distinct(): this {\n this._distinct = true;\n return this;\n }\n\n /** Abort the query and throw QueryTimeoutError if it runs longer than `milliseconds` (default 60000). */\n timeout(milliseconds: number): this {\n this._timeoutMs = milliseconds;\n return this;\n }\n\n /** The query as SQL, in Postgres unless a dialect is given: `toSql('databricks')`. Nothing is run. */\n toSql(dialect: DialectName | SqlDialect = 'postgres'): string {\n return toSql(\n this._businessDate,\n this._processingDatetime,\n this._columns,\n this._table as Table,\n this._op,\n this._orderBy,\n this._groupBy,\n this._limit,\n this._businessDateTo,\n this._distinct,\n this._offset,\n this._having,\n dialect,\n );\n }\n\n async toRows(): Promise<Row[]> {\n return getRunner().select(\n this._businessDate,\n this._processingDatetime,\n this._columns,\n this._table,\n this._op,\n this._orderBy,\n this._groupBy,\n this._limit,\n this._timeoutMs,\n this._businessDateTo,\n this._distinct,\n this._offset,\n this._having,\n );\n }\n}\n\n/** A processing date input keeps the precision it was given: a date stays a date, a timestamp a timestamp. */\nfunction convertProcessingDate(value: Date | string | null): Date | null {\n if (typeof value === 'string' && DATE_ONLY_PATTERN.test(value)) return new DateOnly(value + 'T00:00:00Z');\n return convertDate(value);\n}\n\nfunction convertDate(value: Date | string | null): Date | null {\n if (value === null) return null;\n if (value instanceof Date) return value;\n // Zone-less strings (YYYY-MM-DD, or YYYY-MM-DD HH:MM[:SS]) are read as UTC, matching how\n // dates are formatted into SQL, so the value doesn't shift with the machine's timezone.\n let normalized = value;\n if (DATE_ONLY_PATTERN.test(value)) normalized = value + 'T00:00:00Z';\n else if (/^\\d{4}-\\d{2}-\\d{2}[ T]\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?$/.test(value)) normalized = value.replace(' ', 'T') + 'Z';\n const d = new Date(normalized);\n if (isNaN(d.getTime())) throw new Error(`Cannot parse date: ${value}`);\n return d;\n}\n\nexport function convertInputsAndSelect(\n businessDate: Date | string | null,\n processingDatetime: Date | string | null,\n columns: (Attribute | RelationalOperationElement)[],\n table: QueryTarget,\n op: RelationalOperationElement = new NoOperation(),\n): FinderResult {\n return new FinderResult(\n convertDate(businessDate),\n convertProcessingDate(processingDatetime),\n columns,\n table,\n op,\n );\n}\n\nexport function convertInputsAndSelectForDateRange(\n businessDateFrom: Date | string,\n businessDateTo: Date | string,\n processingDatetime: Date | string,\n columns: (Attribute | RelationalOperationElement)[],\n table: QueryTarget,\n op: RelationalOperationElement = new NoOperation(),\n): FinderResult {\n if (businessDateFrom == null) throw new Error('businessDateFrom is required for findForDateRange');\n if (businessDateTo == null) throw new Error('businessDateTo is required for findForDateRange');\n if (processingDatetime == null) throw new Error('processingValidAt is required for findForDateRange');\n return new FinderResult(\n convertDate(businessDateFrom),\n convertProcessingDate(processingDatetime),\n columns,\n table,\n op,\n convertDate(businessDateTo),\n );\n}\n"],"mappings":"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","names":[]}
|