The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/plugins/datasource/postgres/sql_part.ts

229 lines
5.3 KiB

import _ from 'lodash';
import { SqlPartDef, SqlPart, functionRenderer, suffixRenderer } from 'app/core/components/sql_part/sql_part';
var index = [];
function createPart(part): any {
var def = index[part.type];
if (!def) {
return null;
}
return new SqlPart(part, def);
}
function register(options: any) {
index[options.type] = new SqlPartDef(options);
}
function aliasRenderer(part, innerExpr) {
return innerExpr + ' AS ' + '"' + part.params[0] + '"';
}
function aggregateRenderer(part, innerExpr) {
return part.params[0] + '(' + innerExpr + ')';
}
function columnRenderer(part, innerExpr) {
return part.params[0];
}
function replaceAggregationAddStrategy(selectParts, partModel) {
var hasAlias = false;
// look for existing aggregation
for (var i = 0; i < selectParts.length; i++) {
var part = selectParts[i];
if (part.def.type === 'aggregate') {
selectParts[i] = partModel;
return;
}
if (part.def.type === 'alias') {
hasAlias = true;
}
}
// add alias if none exists yet
if (!hasAlias) {
var aliasModel = createPart({ type: 'alias', params: [selectParts[0].params[0]] });
selectParts.push(aliasModel);
}
selectParts.splice(1, 0, partModel);
}
function replaceSpecialAddStrategy(selectParts, partModel) {
var hasAlias = false;
// look for existing aggregation
for (var i = 0; i < selectParts.length; i++) {
var part = selectParts[i];
if (part.def.type === 'special') {
selectParts[i] = partModel;
return;
}
if (part.def.type === 'alias') {
hasAlias = true;
}
}
// add alias if none exists yet
if (!hasAlias) {
var aliasModel = createPart({ type: 'alias', params: [selectParts[0].params[0]] });
selectParts.push(aliasModel);
}
selectParts.splice(1, 0, partModel);
}
function addMathStrategy(selectParts, partModel) {
var partCount = selectParts.length;
if (partCount > 0) {
// if last is math, replace it
if (selectParts[partCount - 1].def.type === 'math') {
selectParts[partCount - 1] = partModel;
return;
}
// if next to last is math, replace it
if (partCount > 1 && selectParts[partCount - 2].def.type === 'math') {
selectParts[partCount - 2] = partModel;
return;
} else if (selectParts[partCount - 1].def.type === 'alias') {
// if last is alias add it before
selectParts.splice(partCount - 1, 0, partModel);
return;
}
}
selectParts.push(partModel);
}
function addAliasStrategy(selectParts, partModel) {
var partCount = selectParts.length;
if (partCount > 0) {
// if last is alias, replace it
if (selectParts[partCount - 1].def.type === 'alias') {
selectParts[partCount - 1] = partModel;
return;
}
}
selectParts.push(partModel);
}
function addColumnStrategy(selectParts, partModel, query) {
// copy all parts
var parts = _.map(selectParts, function(part: any) {
return createPart({ type: part.def.type, params: _.clone(part.params) });
});
query.selectModels.push(parts);
}
function addExpressionStrategy(selectParts, partModel, query) {
// copy all parts
var parts = _.map(selectParts, function(part: any) {
return createPart({ type: part.def.type, params: _.clone(part.params) });
});
query.selectModels.push(parts);
}
register({
type: 'column',
style: 'label',
addStrategy: addColumnStrategy,
params: [{ type: 'column', dynamicLookup: true }],
defaultParams: ['value'],
renderer: columnRenderer,
});
register({
type: 'expression',
style: 'expression',
label: 'Expr:',
addStrategy: addExpressionStrategy,
params: [
{ name: 'left', type: 'string', dynamicLookup: true },
{ name: 'op', type: 'string', dynamicLookup: true },
{ name: 'right', type: 'string', dynamicLookup: true },
],
defaultParams: ['value', '=', 'value'],
renderer: columnRenderer,
});
register({
type: 'macro',
style: 'label',
label: 'Macro:',
addStrategy: addExpressionStrategy,
params: [],
defaultParams: [],
renderer: columnRenderer,
});
register({
type: 'aggregate',
style: 'label',
addStrategy: replaceAggregationAddStrategy,
params: [{ name: 'name', type: 'string', dynamicLookup: true }],
defaultParams: ['avg'],
renderer: aggregateRenderer,
});
register({
type: 'math',
style: 'label',
addStrategy: addMathStrategy,
params: [{ name: 'expr', type: 'string' }],
defaultParams: [' / 100'],
renderer: suffixRenderer,
});
register({
type: 'alias',
style: 'label',
addStrategy: addAliasStrategy,
params: [{ name: 'name', type: 'string', quote: 'double' }],
defaultParams: ['alias'],
renderMode: 'suffix',
renderer: aliasRenderer,
});
register({
type: 'time',
style: 'function',
label: 'time',
params: [
{
name: 'interval',
type: 'interval',
options: ['$__interval', '1s', '10s', '1m', '5m', '10m', '15m', '1h'],
},
{
name: 'fill',
type: 'string',
options: ['none', 'NULL', '0'],
},
],
defaultParams: ['$__interval', 'none'],
renderer: functionRenderer,
});
register({
type: 'special',
style: 'label',
params: [
{
name: 'function',
type: 'string',
options: ['increase', 'rate'],
},
],
defaultParams: ['increase'],
addStrategy: replaceSpecialAddStrategy,
renderer: aggregateRenderer,
});
export default {
create: createPart,
};