@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
104 lines • 4.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeBucketBuilder = void 0;
const utils_1 = require("@timescaledb/utils");
const debug_1 = require("./debug");
const debug = (0, debug_1.debugCore)('TimeBucketBuilder');
class TimeBucketBuilder {
constructor(tableName, timeColumn, config) {
this.statements = [];
this.metricStatements = [];
this.params = [];
this.tableName = tableName;
this.timeColumn = timeColumn;
this.interval = config.interval;
this.metrics = config.metrics;
}
buildMetrics() {
this.metrics.forEach((metric, index) => {
const alias = metric.alias || `metric_${index}`;
const column = metric.column ? (0, utils_1.escapeIdentifier)(metric.column) : '*';
switch (metric.type) {
case 'count':
this.metricStatements.push(`COUNT(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'distinct_count':
this.metricStatements.push(`COUNT(DISTINCT ${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'sum':
this.metricStatements.push(`SUM(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'avg':
this.metricStatements.push(`AVG(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'min':
this.metricStatements.push(`MIN(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'max':
this.metricStatements.push(`MAX(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'first':
this.metricStatements.push(`FIRST(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
case 'last':
this.metricStatements.push(`LAST(${column}) as ${(0, utils_1.escapeIdentifier)(alias)}`);
break;
default:
throw new Error(`Unsupported metric type: ${metric.type}`);
}
});
}
buildWhere(where, paramOffset = 1) {
if (!where) {
return { sql: '', params: [] };
}
const { sql, params } = (0, utils_1.buildWhereClause)(where, paramOffset);
return { sql: ` AND ${sql}`, params };
}
build({ where, range }) {
debug(`Building time bucket query for table '${this.tableName}'`);
if (!range) {
throw new Error('TimeRange is required');
}
this.params = [];
this.statements = [];
this.metricStatements = [];
this.buildMetrics();
const tableName = (0, utils_1.escapeIdentifier)(this.tableName);
const timeColumn = (0, utils_1.escapeIdentifier)(this.timeColumn);
// First parameter is always the interval
this.params.push(this.interval);
const intervalParam = '$1';
this.params.push(range.start, range.end);
this.statements.push(`WITH time_buckets AS (`);
this.statements.push(` SELECT`);
this.statements.push(` time_bucket(${intervalParam}::interval, ${timeColumn}) AS interval,`);
this.statements.push(` ${this.metricStatements.join(',\n ')}`);
this.statements.push(` FROM ${tableName}`);
// Build WHERE clause starting from parameter index 4 (after interval and time range)
const whereClause = this.buildWhere(where, 4);
const whereStatement = ` WHERE ${timeColumn} >= $2 AND ${timeColumn} <= $3${whereClause.sql}`;
this.statements.push(whereStatement);
this.params.push(...whereClause.params);
this.statements.push(` GROUP BY interval`);
this.statements.push(` ORDER BY interval DESC`);
this.statements.push(`)`);
this.statements.push(`SELECT`);
this.statements.push(` TO_CHAR(interval, 'YYYY-MM-DD"T"HH24:MI:SS"Z"') as interval,`);
const metricAliases = this.metrics.map((metric, index) => {
const alias = metric.alias || `metric_${index}`;
const escapedAlias = (0, utils_1.escapeIdentifier)(alias);
return ` ${escapedAlias} as ${escapedAlias}`;
});
this.statements.push(metricAliases.join(',\n'));
this.statements.push(`FROM time_buckets;`);
const result = {
sql: this.statements.join('\n'),
params: this.params,
};
debug(`Time bucket query for '${this.tableName}' built\n-SQL:${result.sql}\n-Params:${this.params}`);
return result;
}
}
exports.TimeBucketBuilder = TimeBucketBuilder;
//# sourceMappingURL=time-bucket.js.map