| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| import { sqlaAutoGeneratedMetricRegex } from 'src/explore/constants'; |
| |
| export const EXPRESSION_TYPES = { |
| SIMPLE: 'SIMPLE', |
| SQL: 'SQL', |
| }; |
| |
| function inferSqlExpressionColumn(adhocMetric) { |
| if ( |
| adhocMetric.sqlExpression && |
| sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression) |
| ) { |
| const indexFirstCloseParen = adhocMetric.sqlExpression.indexOf(')'); |
| const indexPairedOpenParen = adhocMetric.sqlExpression |
| .substring(0, indexFirstCloseParen) |
| .lastIndexOf('('); |
| if (indexFirstCloseParen > 0 && indexPairedOpenParen > 0) { |
| return adhocMetric.sqlExpression.substring( |
| indexPairedOpenParen + 1, |
| indexFirstCloseParen, |
| ); |
| } |
| } |
| return null; |
| } |
| |
| function inferSqlExpressionAggregate(adhocMetric) { |
| if ( |
| adhocMetric.sqlExpression && |
| sqlaAutoGeneratedMetricRegex.test(adhocMetric.sqlExpression) |
| ) { |
| const indexFirstOpenParen = adhocMetric.sqlExpression.indexOf('('); |
| if (indexFirstOpenParen > 0) { |
| return adhocMetric.sqlExpression.substring(0, indexFirstOpenParen); |
| } |
| } |
| return null; |
| } |
| |
| export default class AdhocMetric { |
| constructor(adhocMetric) { |
| this.expressionType = adhocMetric.expressionType || EXPRESSION_TYPES.SIMPLE; |
| if (this.expressionType === EXPRESSION_TYPES.SIMPLE) { |
| // try to be clever in the case of transitioning from Sql expression back to simple expression |
| const inferredColumn = inferSqlExpressionColumn(adhocMetric); |
| this.column = |
| adhocMetric.column || |
| (inferredColumn && { column_name: inferredColumn }); |
| this.aggregate = |
| adhocMetric.aggregate || inferSqlExpressionAggregate(adhocMetric); |
| this.sqlExpression = null; |
| } else if (this.expressionType === EXPRESSION_TYPES.SQL) { |
| this.sqlExpression = adhocMetric.sqlExpression; |
| this.column = null; |
| this.aggregate = null; |
| } |
| this.isNew = !!adhocMetric.isNew; |
| this.hasCustomLabel = !!(adhocMetric.hasCustomLabel && adhocMetric.label); |
| this.label = this.hasCustomLabel |
| ? adhocMetric.label |
| : this.getDefaultLabel(); |
| |
| this.optionName = |
| adhocMetric.optionName || |
| `metric_${Math.random() |
| .toString(36) |
| .substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`; |
| } |
| |
| getDefaultLabel() { |
| const label = this.translateToSql(); |
| return label.length < 43 ? label : `${label.substring(0, 40)}...`; |
| } |
| |
| translateToSql() { |
| if (this.expressionType === EXPRESSION_TYPES.SIMPLE) { |
| const aggregate = this.aggregate || ''; |
| // eslint-disable-next-line camelcase |
| const column = this.column?.column_name |
| ? `(${this.column.column_name})` |
| : ''; |
| return aggregate + column; |
| } |
| if (this.expressionType === EXPRESSION_TYPES.SQL) { |
| return this.sqlExpression; |
| } |
| return ''; |
| } |
| |
| duplicateWith(nextFields) { |
| return new AdhocMetric({ |
| ...this, |
| // all duplicate metrics are not considered new by default |
| isNew: false, |
| // but still overriddable by nextFields |
| ...nextFields, |
| }); |
| } |
| |
| equals(adhocMetric) { |
| return ( |
| adhocMetric.label === this.label && |
| adhocMetric.expressionType === this.expressionType && |
| adhocMetric.sqlExpression === this.sqlExpression && |
| adhocMetric.aggregate === this.aggregate && |
| (adhocMetric.column && adhocMetric.column.column_name) === |
| (this.column && this.column.column_name) |
| ); |
| } |
| |
| isValid() { |
| if (this.expressionType === EXPRESSION_TYPES.SIMPLE) { |
| return !!(this.column && this.aggregate); |
| } |
| if (this.expressionType === EXPRESSION_TYPES.SQL) { |
| return !!this.sqlExpression; |
| } |
| return false; |
| } |
| |
| inferSqlExpressionAggregate() { |
| return inferSqlExpressionAggregate(this); |
| } |
| |
| inferSqlExpressionColumn() { |
| return inferSqlExpressionColumn(this); |
| } |
| } |