UNPKG

@timescaledb/core

Version:

The `@timescaledb/core` package provides fundamental building blocks for working with TimescaleDB in TypeScript/JavaScript applications. It includes SQL query builders and utilities for managing hypertables, continuous aggregates, compression, and other T

143 lines 6.22 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RollupBuilder = void 0; const utils_1 = require("@timescaledb/utils"); const candlestick_1 = require("./candlestick"); const debug_1 = require("./debug"); const debug = (0, debug_1.debugCore)('RollupBuilder'); class RollupInspectBuilder { constructor(config) { this.config = config; } build() { debug(`Building inspect query for rollup '${this.config.rollupOptions.name}'`); if (!this.config || !this.config.rollupOptions) { throw new Error('Invalid rollup configuration 1'); } const sourceView = (0, utils_1.escapeLiteral)(this.config.rollupOptions.sourceView); const rollupView = (0, utils_1.escapeLiteral)(this.config.rollupOptions.name); const result = ` SELECT EXISTS ( SELECT FROM information_schema.views WHERE table_schema = 'public' AND table_name = ${sourceView} ) as source_view_exists, EXISTS ( SELECT FROM information_schema.views WHERE table_schema = 'public' AND table_name = ${rollupView} ) as rollup_view_exists; `; debug(`Inspect query '${this.config.rollupOptions.name}' built:\n${result}`); return result; } } class RollupUpBuilder { constructor(config) { this.config = config; this.statements = []; } buildRollupSelect(metadata) { const selectStatements = []; const bucketInterval = (0, utils_1.escapeLiteral)(this.config.rollupOptions.bucketInterval); const bucketColumnSource = (0, utils_1.escapeIdentifier)(this.config.rollupOptions.bucketColumn.source || 'bucket'); const bucketColumnTarget = (0, utils_1.escapeIdentifier)(this.config.rollupOptions.bucketColumn.target || 'bucket'); selectStatements.push(`time_bucket(${bucketInterval}::interval, ${bucketColumnSource}) AS ${bucketColumnTarget}`); const groupColumns = this.config.continuousAggregateOptions.group_columns || []; for (const column of groupColumns) { const escapedColumn = (0, utils_1.escapeIdentifier)(column); selectStatements.push(`${escapedColumn} as ${escapedColumn}`); } if (metadata.candlestick) { const rollupSql = candlestick_1.CandlestickBuilder.generateSQL(metadata.candlestick, true); if (rollupSql) { selectStatements.push(rollupSql); } } const rollupSelects = metadata.rollupRules.map((rule) => { const sourceColumn = (0, utils_1.escapeIdentifier)(rule.sourceColumn); const targetColumn = (0, utils_1.escapeIdentifier)(rule.targetColumn || 'bucket'); if (rule.aggregateType) { switch (rule.aggregateType) { case 'sum': return `sum(${sourceColumn}) as ${targetColumn}`; case 'avg': return `avg(${sourceColumn}) as ${targetColumn}`; default: return `rollup(${sourceColumn}) as ${targetColumn}`; } } return `${rule.rollupFn || 'rollup'}(${sourceColumn}) as ${targetColumn}`; }); selectStatements.push(...rollupSelects); const sourceView = (0, utils_1.escapeIdentifier)(this.config.rollupOptions.sourceView); const groupByCols = ['1', ...groupColumns.map((c) => (0, utils_1.escapeIdentifier)(c))]; const groupByClause = groupByCols.join(', '); const result = ` SELECT ${selectStatements.join(',\n ')} FROM ${sourceView} GROUP BY ${groupByClause}${this.config.rollupOptions.materializedOnly ? ' WITH ' : ' WITH NO '}DATA; `; return result; } build(metadata) { debug('Building rollup query'); const _metadata = metadata || { rollupRules: this.config.rollupOptions.rollupRules || [] }; const viewName = (0, utils_1.escapeIdentifier)(this.config.rollupOptions.name); this.statements.push(`CREATE MATERIALIZED VIEW ${viewName} WITH (timescaledb.continuous) AS ${this.buildRollupSelect(_metadata)}`); debug(`Rollup query built:\n${this.statements.join('\n')}`); return this.statements.join('\n'); } getRefreshPolicy() { if (!this.config.rollupOptions.refresh_policy) return null; debug('Building refresh policy query'); const policy = this.config.rollupOptions.refresh_policy; const viewName = (0, utils_1.escapeLiteral)(this.config.rollupOptions.name); const result = `SELECT add_continuous_aggregate_policy(${viewName}, start_offset => INTERVAL ${(0, utils_1.escapeLiteral)(policy.start_offset)}, end_offset => INTERVAL ${(0, utils_1.escapeLiteral)(policy.end_offset)}, schedule_interval => INTERVAL ${(0, utils_1.escapeLiteral)(policy.schedule_interval)} );`; debug(`Refresh policy query built:\n${result}`); return result; } } class RollupDownBuilder { constructor(config) { this.config = config; } build() { debug('Building down query'); const statements = []; const viewName = this.config.rollupOptions.name; if (this.config.continuousAggregateOptions.refresh_policy) { statements.push(`SELECT remove_continuous_aggregate_policy(${(0, utils_1.escapeLiteral)(viewName)}, if_exists => true);`); } statements.push(`DROP MATERIALIZED VIEW IF EXISTS ${(0, utils_1.escapeIdentifier)(viewName)};`); debug(`Down query built:\n${statements.join('\n')}`); return statements; } } class RollupBuilder { constructor(config) { this.config = config; if (!config || !config.rollupOptions) { throw new Error('Invalid rollup configuration 2'); } } up() { return new RollupUpBuilder(this.config); } down() { return new RollupDownBuilder(this.config); } inspect() { return new RollupInspectBuilder(this.config); } } exports.RollupBuilder = RollupBuilder; //# sourceMappingURL=rollup.js.map