mirror of https://github.com/apache/druid.git
Web console: update DQT to version 0.17 (#13323)
* update to DQT 17 * update licenses * after npm i
This commit is contained in:
parent
d1a4de022a
commit
f6aca21e82
|
@ -5683,7 +5683,7 @@ license_category: binary
|
|||
module: web-console
|
||||
license_name: Apache License version 2.0
|
||||
copyright: Imply Data
|
||||
version: 0.16.1
|
||||
version: 0.17.1
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlTableRef } from 'druid-query-toolkit';
|
||||
import { T } from 'druid-query-toolkit';
|
||||
import * as playwright from 'playwright-chromium';
|
||||
|
||||
import { DatasourcesOverview } from './component/datasources/overview';
|
||||
|
@ -167,7 +167,7 @@ async function validateDatasourceStatus(page: playwright.Page, datasourceName: s
|
|||
|
||||
async function validateQuery(page: playwright.Page, datasourceName: string) {
|
||||
const queryOverview = new QueryOverview(page, UNIFIED_CONSOLE_URL);
|
||||
const query = `SELECT * FROM ${SqlTableRef.create(datasourceName)} ORDER BY __time`;
|
||||
const query = `SELECT * FROM ${T(datasourceName)} ORDER BY __time`;
|
||||
const results = await queryOverview.runQuery(query);
|
||||
expect(results).toBeDefined();
|
||||
expect(results.length).toBeGreaterThan(0);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
"d3-axis": "^2.1.0",
|
||||
"d3-scale": "^3.3.0",
|
||||
"d3-selection": "^2.0.0",
|
||||
"druid-query-toolkit": "^0.16.1",
|
||||
"druid-query-toolkit": "^0.17.1",
|
||||
"file-saver": "^2.0.2",
|
||||
"follow-redirects": "^1.14.7",
|
||||
"fontsource-open-sans": "^3.0.9",
|
||||
|
@ -8967,9 +8967,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/druid-query-toolkit": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.16.1.tgz",
|
||||
"integrity": "sha512-HiovpGh1m2QTvexBX1AvQAz5ONc9sChazL0hsXl0qEvHcIQ69pksJZWXZOStBI2T9fJAXQpSUVB4DUSdE6UXmQ==",
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.1.tgz",
|
||||
"integrity": "sha512-uXybPbUgY5fKMRSduPKSTLHQ8zhfvGT2/jWl+fPIXruFjFnZTDp8YPkJtYq1LzSCvEfgKLw1vwBtNhyUY/CdVg==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.3.1"
|
||||
},
|
||||
|
@ -34591,9 +34591,9 @@
|
|||
}
|
||||
},
|
||||
"druid-query-toolkit": {
|
||||
"version": "0.16.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.16.1.tgz",
|
||||
"integrity": "sha512-HiovpGh1m2QTvexBX1AvQAz5ONc9sChazL0hsXl0qEvHcIQ69pksJZWXZOStBI2T9fJAXQpSUVB4DUSdE6UXmQ==",
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.17.1.tgz",
|
||||
"integrity": "sha512-uXybPbUgY5fKMRSduPKSTLHQ8zhfvGT2/jWl+fPIXruFjFnZTDp8YPkJtYq1LzSCvEfgKLw1vwBtNhyUY/CdVg==",
|
||||
"requires": {
|
||||
"tslib": "^2.3.1"
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
"d3-axis": "^2.1.0",
|
||||
"d3-scale": "^3.3.0",
|
||||
"d3-selection": "^2.0.0",
|
||||
"druid-query-toolkit": "^0.16.1",
|
||||
"druid-query-toolkit": "^0.17.1",
|
||||
"file-saver": "^2.0.2",
|
||||
"follow-redirects": "^1.14.7",
|
||||
"fontsource-open-sans": "^3.0.9",
|
||||
|
|
|
@ -19,13 +19,14 @@
|
|||
import { Menu, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import {
|
||||
C,
|
||||
Column,
|
||||
L,
|
||||
SqlComparison,
|
||||
SqlExpression,
|
||||
SqlLiteral,
|
||||
SqlQuery,
|
||||
SqlRecord,
|
||||
SqlRef,
|
||||
trimString,
|
||||
} from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
@ -36,7 +37,7 @@ function sqlLiteralForColumnValue(column: Column, value: unknown): SqlLiteral |
|
|||
if (column.sqlType === 'TIMESTAMP') {
|
||||
const asDate = new Date(value as any);
|
||||
if (!isNaN(asDate.valueOf())) {
|
||||
return SqlLiteral.create(asDate);
|
||||
return L(asDate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,14 +113,14 @@ export function CellFilterMenu(props: CellFilterMenuProps) {
|
|||
let ex: SqlExpression | undefined;
|
||||
let having = false;
|
||||
if (query.hasStarInSelect()) {
|
||||
ex = SqlRef.column(column.name);
|
||||
ex = C(column.name);
|
||||
} else {
|
||||
const selectValue = query.getSelectExpressionForIndex(headerIndex);
|
||||
if (selectValue) {
|
||||
const outputName = selectValue.getOutputName();
|
||||
having = query.isAggregateSelectIndex(headerIndex);
|
||||
if (having && outputName) {
|
||||
ex = SqlRef.column(outputName);
|
||||
ex = C(outputName);
|
||||
} else {
|
||||
ex = selectValue.getUnderlyingExpression();
|
||||
}
|
||||
|
@ -133,11 +134,11 @@ export function CellFilterMenu(props: CellFilterMenuProps) {
|
|||
icon={IconNames.FILTER}
|
||||
text={`${having ? 'Having' : 'Filter on'}: ${prettyPrintSql(clause)}`}
|
||||
onClick={() => {
|
||||
const column = clause.getUsedColumns()[0];
|
||||
const columnName = clause.getUsedColumnNames()[0];
|
||||
onQueryAction(
|
||||
having
|
||||
? q => q.removeFromHaving(column).addHaving(clause)
|
||||
: q => q.removeColumnFromWhere(column).addWhere(clause),
|
||||
? q => q.removeFromHaving(columnName).addHaving(clause)
|
||||
: q => q.removeColumnFromWhere(columnName).addWhere(clause),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
@ -151,7 +152,7 @@ export function CellFilterMenu(props: CellFilterMenuProps) {
|
|||
const currentClauses =
|
||||
currentFilterExpression
|
||||
?.decomposeViaAnd()
|
||||
?.filter(ex => String(ex.getUsedColumns()) === column.name) || [];
|
||||
?.filter(ex => String(ex.getUsedColumnNames()) === column.name) || [];
|
||||
|
||||
const updatedClause =
|
||||
currentClauses.length === 1 && val ? addToClause(currentClauses[0], val) : undefined;
|
||||
|
@ -160,7 +161,7 @@ export function CellFilterMenu(props: CellFilterMenuProps) {
|
|||
const jsonColumn = column.nativeType === 'COMPLEX<json>';
|
||||
return (
|
||||
<Menu>
|
||||
{ex?.getFirstColumn() && val && !jsonColumn && (
|
||||
{ex?.getFirstColumnName() && val && !jsonColumn && (
|
||||
<>
|
||||
{updatedClause && filterOnMenuItem(updatedClause)}
|
||||
{filterOnMenuItem(ex.equal(val))}
|
||||
|
@ -177,7 +178,7 @@ export function CellFilterMenu(props: CellFilterMenuProps) {
|
|||
</Menu>
|
||||
);
|
||||
} else {
|
||||
const ref = SqlRef.column(column.name);
|
||||
const ref = C(column.name);
|
||||
const stringValue = stringifyValue(value);
|
||||
const trimmedValue = trimString(stringValue, 50);
|
||||
return (
|
||||
|
|
|
@ -66,8 +66,8 @@ export const RecordTablePane = React.memo(function RecordTablePane(props: Record
|
|||
if (!parsedQuery || !parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) return false;
|
||||
|
||||
return (
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumn(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumn(header)
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumnName(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumnName(header)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlLiteral } from 'druid-query-toolkit';
|
||||
import { L } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
|
||||
|
@ -44,7 +44,7 @@ export const DatasourceColumnsTable = React.memo(function DatasourceColumnsTable
|
|||
processQuery: async (datasourceId: string) => {
|
||||
return await queryDruidSql<ColumnMetadata>({
|
||||
query: `SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = ${SqlLiteral.create(datasourceId)}`,
|
||||
WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = ${L(datasourceId)}`,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { QueryResult, QueryRunner, SqlTableRef } from 'druid-query-toolkit';
|
||||
import { QueryResult, QueryRunner, T } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { Loader, RecordTablePane } from '../../../components';
|
||||
|
@ -42,7 +42,7 @@ export const DatasourcePreviewPane = React.memo(function DatasourcePreviewPane(
|
|||
let result: QueryResult;
|
||||
try {
|
||||
result = await queryRunner.runQuery({
|
||||
query: `SELECT * FROM ${SqlTableRef.create(datasource)}`,
|
||||
query: `SELECT * FROM ${T(datasource)}`,
|
||||
extraQueryContext: { sqlOuterLimit: 100 },
|
||||
cancelToken,
|
||||
});
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlRef } from 'druid-query-toolkit';
|
||||
import { N } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
|
||||
|
@ -43,7 +43,7 @@ export const LookupValuesTable = React.memo(function LookupValuesTable(
|
|||
const [entriesState] = useQueryManager<string, LookupRow[]>({
|
||||
processQuery: async (lookupId: string) => {
|
||||
return await queryDruidSql<LookupRow>({
|
||||
query: `SELECT "k", "v" FROM ${SqlRef.column(lookupId, 'lookup')} LIMIT 5000`,
|
||||
query: `SELECT "k", "v" FROM ${N('lookup').table(lookupId)} LIMIT 5000`,
|
||||
});
|
||||
},
|
||||
initQuery: props.lookupId,
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
C,
|
||||
F,
|
||||
filterMap,
|
||||
L,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlLiteral,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlStar,
|
||||
} from 'druid-query-toolkit';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
@ -120,9 +122,9 @@ export function summarizeExternalConfig(externalConfig: ExternalConfig): string
|
|||
export function externalConfigToTableExpression(config: ExternalConfig): SqlExpression {
|
||||
return SqlExpression.parse(`TABLE(
|
||||
EXTERN(
|
||||
${SqlLiteral.create(JSONBig.stringify(config.inputSource))},
|
||||
${SqlLiteral.create(JSONBig.stringify(config.inputFormat))},
|
||||
${SqlLiteral.create(JSONBig.stringify(config.signature))}
|
||||
${L(JSONBig.stringify(config.inputSource))},
|
||||
${L(JSONBig.stringify(config.inputFormat))},
|
||||
${L(JSONBig.stringify(config.signature))}
|
||||
)
|
||||
)`);
|
||||
}
|
||||
|
@ -135,11 +137,8 @@ export function externalConfigToInitDimensions(
|
|||
return (timeExpression ? [timeExpression.as('__time')] : [])
|
||||
.concat(
|
||||
filterMap(config.signature, ({ name }, i) => {
|
||||
if (timeExpression && timeExpression.containsColumn(name)) return;
|
||||
return SqlRef.column(name).applyIf(
|
||||
isArrays[i],
|
||||
ex => SqlFunction.simple('MV_TO_ARRAY', [ex]).as(name) as any,
|
||||
);
|
||||
if (timeExpression && timeExpression.containsColumnName(name)) return;
|
||||
return C(name).applyIf(isArrays[i], ex => F('MV_TO_ARRAY', ex).as(name) as any);
|
||||
}),
|
||||
)
|
||||
.slice(0, MULTI_STAGE_QUERY_MAX_COLUMNS);
|
||||
|
|
|
@ -23,8 +23,8 @@ import {
|
|||
SqlPartitionedByClause,
|
||||
SqlQuery,
|
||||
SqlReplaceClause,
|
||||
SqlTableRef,
|
||||
SqlWithPart,
|
||||
T,
|
||||
} from 'druid-query-toolkit';
|
||||
|
||||
import { filterMap, oneOf } from '../../utils';
|
||||
|
@ -150,10 +150,10 @@ export function fitIngestQueryPattern(query: SqlQuery): IngestQueryPattern {
|
|||
let overwriteWhere: SqlExpression | undefined;
|
||||
if (query.insertClause) {
|
||||
mode = 'insert';
|
||||
destinationTableName = query.insertClause.table.getTable();
|
||||
destinationTableName = query.insertClause.table.getName();
|
||||
} else if (query.replaceClause) {
|
||||
mode = 'replace';
|
||||
destinationTableName = query.replaceClause.table.getTable();
|
||||
destinationTableName = query.replaceClause.table.getName();
|
||||
overwriteWhere = query.replaceClause.whereClause?.expression;
|
||||
} else {
|
||||
throw new Error(`Must have an INSERT or REPLACE clause`);
|
||||
|
@ -251,7 +251,7 @@ export function ingestQueryPatternToQuery(
|
|||
partitionedBy,
|
||||
clusteredBy,
|
||||
} = ingestQueryPattern;
|
||||
return SqlQuery.from(SqlTableRef.create(mainExternalName))
|
||||
return SqlQuery.from(T(mainExternalName))
|
||||
.applyIf(!preview, q =>
|
||||
mode === 'insert'
|
||||
? q.changeInsertIntoTable(destinationTableName)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlExpression, SqlQuery, SqlTableRef, SqlValues, SqlWithQuery } from 'druid-query-toolkit';
|
||||
import { SqlExpression, SqlQuery, SqlValues, SqlWithQuery, T } from 'druid-query-toolkit';
|
||||
import Hjson from 'hjson';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
||||
|
@ -71,7 +71,7 @@ export class WorkbenchQueryPart {
|
|||
);
|
||||
if (!fragmentQuery) return;
|
||||
|
||||
return fragmentQuery.getIngestTable()?.getTable();
|
||||
return fragmentQuery.getIngestTable()?.getName();
|
||||
}
|
||||
|
||||
public readonly id: string;
|
||||
|
@ -179,7 +179,7 @@ export class WorkbenchQueryPart {
|
|||
public getIngestDatasource(): string | undefined {
|
||||
const { queryString, parsedQuery } = this;
|
||||
if (parsedQuery) {
|
||||
return parsedQuery.getIngestTable()?.getTable();
|
||||
return parsedQuery.getIngestTable()?.getName();
|
||||
}
|
||||
|
||||
if (this.isJsonLike()) return;
|
||||
|
@ -241,7 +241,7 @@ export class WorkbenchQueryPart {
|
|||
|
||||
public toWithPart(): string {
|
||||
const { queryName, queryString } = this;
|
||||
return `${SqlTableRef.create(queryName || 'q')} AS (\n${queryString}\n)`;
|
||||
return `${T(queryName || 'q')} AS (\n${queryString}\n)`;
|
||||
}
|
||||
|
||||
public duplicate(): WorkbenchQueryPart {
|
||||
|
|
|
@ -17,16 +17,16 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
C,
|
||||
F,
|
||||
SqlClusteredByClause,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlLiteral,
|
||||
SqlOrderByClause,
|
||||
SqlOrderByExpression,
|
||||
SqlPartitionedByClause,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlTableRef,
|
||||
SqlTable,
|
||||
} from 'druid-query-toolkit';
|
||||
import Hjson from 'hjson';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
@ -201,10 +201,7 @@ export class WorkbenchQuery {
|
|||
let partitionedByExpression = partitionedByClause.expression;
|
||||
if (partitionedByExpression) {
|
||||
if (partitionedByExpression instanceof SqlLiteral) {
|
||||
partitionedByExpression = SqlFunction.floor(
|
||||
SqlRef.column('__time'),
|
||||
partitionedByExpression,
|
||||
);
|
||||
partitionedByExpression = F.floor(C('__time'), partitionedByExpression);
|
||||
}
|
||||
orderByExpressions.push(SqlOrderByExpression.create(partitionedByExpression));
|
||||
}
|
||||
|
@ -451,8 +448,8 @@ export class WorkbenchQuery {
|
|||
const parsedQuery = this.getParsedQuery();
|
||||
if (parsedQuery) {
|
||||
const fromExpression = parsedQuery.getFirstFromExpression();
|
||||
if (fromExpression instanceof SqlTableRef) {
|
||||
const firstTable = fromExpression.getTable();
|
||||
if (fromExpression instanceof SqlTable) {
|
||||
const firstTable = fromExpression.getName();
|
||||
ret = ret.changeQueryParts(
|
||||
this.queryParts.map(queryPart =>
|
||||
queryPart.queryName === firstTable ? queryPart.addPreviewLimit() : queryPart,
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import { AxiosResponse, CancelToken } from 'axios';
|
||||
import { SqlLiteral } from 'druid-query-toolkit';
|
||||
import { L } from 'druid-query-toolkit';
|
||||
|
||||
import { Execution, QueryContext } from '../../druid-models';
|
||||
import { Api } from '../../singletons';
|
||||
|
@ -227,7 +227,7 @@ export async function updateExecutionWithDatasourceExistsIfNeeded(
|
|||
COUNT(*) AS num_segments,
|
||||
COUNT(*) FILTER (WHERE is_published = 1 AND is_available = 0) AS loading_segments
|
||||
FROM sys.segments
|
||||
WHERE datasource = ${SqlLiteral.create(execution.destination.dataSource)} AND is_overshadowed = 0`,
|
||||
WHERE datasource = ${L(execution.destination.dataSource)} AND is_overshadowed = 0`,
|
||||
});
|
||||
|
||||
const numSegments: number = deepGet(segmentCheck, '0.num_segments') || 0;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { RefName, SqlExpression, SqlLiteral, SqlRef, SqlTableRef } from 'druid-query-toolkit';
|
||||
import { C, L, RefName, SqlExpression, T } from 'druid-query-toolkit';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
||||
import {
|
||||
|
@ -38,10 +38,10 @@ export function getSpecDatasourceName(spec: IngestionSpec): string {
|
|||
function convertFilter(filter: any): SqlExpression {
|
||||
switch (filter.type) {
|
||||
case 'selector':
|
||||
return SqlRef.column(filter.dimension).equal(filter.value);
|
||||
return C(filter.dimension).equal(filter.value);
|
||||
|
||||
case 'in':
|
||||
return SqlRef.column(filter.dimension).in(filter.values);
|
||||
return C(filter.dimension).in(filter.values);
|
||||
|
||||
case 'not':
|
||||
return convertFilter(filter.field).not();
|
||||
|
@ -57,7 +57,7 @@ function convertFilter(filter: any): SqlExpression {
|
|||
}
|
||||
}
|
||||
|
||||
const SOURCE_REF = SqlTableRef.create('source');
|
||||
const SOURCE_TABLE = T('source');
|
||||
|
||||
export function convertSpecToSql(spec: any): QueryWithContext {
|
||||
if (!oneOf(spec.type, 'index_parallel', 'index', 'index_hadoop')) {
|
||||
|
@ -108,8 +108,8 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
}
|
||||
|
||||
let timeExpression: string;
|
||||
const column = timestampSpec.column || 'timestamp';
|
||||
const columnRef = SqlRef.column(column);
|
||||
const timestampColumnName = timestampSpec.column || 'timestamp';
|
||||
const timestampColumn = C(timestampColumnName);
|
||||
const format = timestampSpec.format || 'auto';
|
||||
const timeTransform = transforms.find(t => t.name === '__time');
|
||||
if (timeTransform) {
|
||||
|
@ -117,46 +117,44 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
} else {
|
||||
switch (format) {
|
||||
case 'auto':
|
||||
columns.unshift({ name: column, type: 'string' });
|
||||
timeExpression = `CASE WHEN CAST(${columnRef} AS BIGINT) > 0 THEN MILLIS_TO_TIMESTAMP(CAST(${columnRef} AS BIGINT)) ELSE TIME_PARSE(${columnRef}) END`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'string' });
|
||||
timeExpression = `CASE WHEN CAST(${timestampColumn} AS BIGINT) > 0 THEN MILLIS_TO_TIMESTAMP(CAST(${timestampColumn} AS BIGINT)) ELSE TIME_PARSE(${timestampColumn}) END`;
|
||||
break;
|
||||
|
||||
case 'iso':
|
||||
columns.unshift({ name: column, type: 'string' });
|
||||
timeExpression = `TIME_PARSE(${columnRef})`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'string' });
|
||||
timeExpression = `TIME_PARSE(${timestampColumn})`;
|
||||
break;
|
||||
|
||||
case 'posix':
|
||||
columns.unshift({ name: column, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${columnRef} * 1000)`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${timestampColumn} * 1000)`;
|
||||
break;
|
||||
|
||||
case 'millis':
|
||||
columns.unshift({ name: column, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${columnRef})`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${timestampColumn})`;
|
||||
break;
|
||||
|
||||
case 'micro':
|
||||
columns.unshift({ name: column, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${columnRef} / 1000)`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${timestampColumn} / 1000)`;
|
||||
break;
|
||||
|
||||
case 'nano':
|
||||
columns.unshift({ name: column, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${columnRef} / 1000000)`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'long' });
|
||||
timeExpression = `MILLIS_TO_TIMESTAMP(${timestampColumn} / 1000000)`;
|
||||
break;
|
||||
|
||||
default:
|
||||
columns.unshift({ name: column, type: 'string' });
|
||||
timeExpression = `TIME_PARSE(${columnRef}, ${SqlLiteral.create(format)})`;
|
||||
columns.unshift({ name: timestampColumnName, type: 'string' });
|
||||
timeExpression = `TIME_PARSE(${timestampColumn}, ${L(format)})`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (timestampSpec.missingValue) {
|
||||
timeExpression = `COALESCE(${timeExpression}, TIME_PARSE(${SqlLiteral.create(
|
||||
timestampSpec.missingValue,
|
||||
)}))`;
|
||||
timeExpression = `COALESCE(${timeExpression}, TIME_PARSE(${L(timestampSpec.missingValue)}))`;
|
||||
}
|
||||
|
||||
timeExpression = convertQueryGranularity(
|
||||
|
@ -180,17 +178,17 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
if (typeof dataSource !== 'string') throw new Error(`spec.dataSchema.dataSource is not a string`);
|
||||
|
||||
if (deepGet(spec, 'spec.ioConfig.appendToExisting')) {
|
||||
lines.push(`INSERT INTO ${SqlTableRef.create(dataSource)}`);
|
||||
lines.push(`INSERT INTO ${T(dataSource)}`);
|
||||
} else {
|
||||
const overwrite = deepGet(spec, 'spec.ioConfig.dropExisting')
|
||||
? 'WHERE ' +
|
||||
SqlExpression.fromTimeRefAndInterval(
|
||||
SqlRef.column('__time'),
|
||||
SqlExpression.fromTimeExpressionAndInterval(
|
||||
C('__time'),
|
||||
deepGet(spec, 'spec.dataSchema.granularitySpec.intervals'),
|
||||
)
|
||||
: 'ALL';
|
||||
|
||||
lines.push(`REPLACE INTO ${SqlTableRef.create(dataSource)} OVERWRITE ${overwrite}`);
|
||||
lines.push(`REPLACE INTO ${T(dataSource)} OVERWRITE ${overwrite}`);
|
||||
}
|
||||
|
||||
let inputSource: any;
|
||||
|
@ -220,27 +218,24 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
|
||||
if (inputSource.type === 'druid') {
|
||||
lines.push(
|
||||
`WITH ${SOURCE_REF} AS (`,
|
||||
`WITH ${SOURCE_TABLE} AS (`,
|
||||
` SELECT *`,
|
||||
` FROM ${SqlTableRef.create(inputSource.dataSource)}`,
|
||||
` WHERE ${SqlExpression.fromTimeRefAndInterval(
|
||||
SqlRef.column('__time'),
|
||||
inputSource.interval,
|
||||
)}`,
|
||||
` FROM ${T(inputSource.dataSource)}`,
|
||||
` WHERE ${SqlExpression.fromTimeExpressionAndInterval(C('__time'), inputSource.interval)}`,
|
||||
')',
|
||||
);
|
||||
} else {
|
||||
lines.push(
|
||||
`WITH ${SOURCE_REF} AS (SELECT * FROM TABLE(`,
|
||||
`WITH ${SOURCE_TABLE} AS (SELECT * FROM TABLE(`,
|
||||
` EXTERN(`,
|
||||
` ${SqlLiteral.create(JSONBig.stringify(inputSource))},`,
|
||||
` ${L(JSONBig.stringify(inputSource))},`,
|
||||
);
|
||||
|
||||
const inputFormat = deepGet(spec, 'spec.ioConfig.inputFormat');
|
||||
if (!inputFormat) throw new Error(`spec.ioConfig.inputFormat is not defined`);
|
||||
lines.push(
|
||||
` ${SqlLiteral.create(JSONBig.stringify(inputFormat))},`,
|
||||
` ${SqlLiteral.create(JSONBig.stringify(columns))}`,
|
||||
` ${L(JSONBig.stringify(inputFormat))},`,
|
||||
` ${L(JSONBig.stringify(columns))}`,
|
||||
` )`,
|
||||
`))`,
|
||||
);
|
||||
|
@ -264,7 +259,7 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
const relevantTransform = transforms.find(t => t.name === dimensionName);
|
||||
return ` ${
|
||||
relevantTransform ? `REWRITE_[${relevantTransform.expression}]_TO_SQL AS ` : ''
|
||||
}${SqlRef.column(dimensionName)},${
|
||||
}${C(dimensionName)},${
|
||||
relevantTransform ? ` --:ISSUE: Transform for dimension could not be converted` : ''
|
||||
}`;
|
||||
}),
|
||||
|
@ -282,7 +277,7 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
.replace(/,(\s+--)/, '$1');
|
||||
|
||||
lines.push(selectExpressions.join('\n'));
|
||||
lines.push(`FROM ${SOURCE_REF}`);
|
||||
lines.push(`FROM ${SOURCE_TABLE}`);
|
||||
|
||||
const filter = deepGet(spec, 'spec.dataSchema.transformSpec.filter');
|
||||
if (filter) {
|
||||
|
@ -316,7 +311,7 @@ export function convertSpecToSql(spec: any): QueryWithContext {
|
|||
partitionsSpec.partitionDimensions ||
|
||||
(partitionsSpec.partitionDimension ? [partitionsSpec.partitionDimension] : undefined);
|
||||
if (Array.isArray(partitionDimensions)) {
|
||||
lines.push(`CLUSTERED BY ${partitionDimensions.map(d => SqlRef.column(d)).join(', ')}`);
|
||||
lines.push(`CLUSTERED BY ${partitionDimensions.map(d => C(d)).join(', ')}`);
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -397,56 +392,56 @@ function metricSpecToSqlExpression(metricSpec: MetricSpec): string | undefined {
|
|||
}
|
||||
|
||||
if (!metricSpec.fieldName) return;
|
||||
const ref = SqlRef.column(metricSpec.fieldName);
|
||||
const column = C(metricSpec.fieldName);
|
||||
|
||||
switch (metricSpec.type) {
|
||||
case 'longSum':
|
||||
case 'floatSum':
|
||||
case 'doubleSum':
|
||||
return `SUM(${ref})`;
|
||||
return `SUM(${column})`;
|
||||
|
||||
case 'longMin':
|
||||
case 'floatMin':
|
||||
case 'doubleMin':
|
||||
return `MIN(${ref})`;
|
||||
return `MIN(${column})`;
|
||||
|
||||
case 'longMax':
|
||||
case 'floatMax':
|
||||
case 'doubleMax':
|
||||
return `MAX(${ref})`;
|
||||
return `MAX(${column})`;
|
||||
|
||||
case 'doubleFirst':
|
||||
case 'floatFirst':
|
||||
case 'longFirst':
|
||||
return `EARLIEST(${ref})`;
|
||||
return `EARLIEST(${column})`;
|
||||
|
||||
case 'stringFirst':
|
||||
return `EARLIEST(${ref}, ${SqlLiteral.create(metricSpec.maxStringBytes || 128)})`;
|
||||
return `EARLIEST(${column}, ${L(metricSpec.maxStringBytes || 128)})`;
|
||||
|
||||
case 'doubleLast':
|
||||
case 'floatLast':
|
||||
case 'longLast':
|
||||
return `LATEST(${ref})`;
|
||||
return `LATEST(${column})`;
|
||||
|
||||
case 'stringLast':
|
||||
return `LATEST(${ref}, ${SqlLiteral.create(metricSpec.maxStringBytes || 128)})`;
|
||||
return `LATEST(${column}, ${L(metricSpec.maxStringBytes || 128)})`;
|
||||
|
||||
case 'thetaSketch':
|
||||
return `APPROX_COUNT_DISTINCT_DS_THETA(${ref}${extraArgs([metricSpec.size, 16384])})`;
|
||||
return `APPROX_COUNT_DISTINCT_DS_THETA(${column}${extraArgs([metricSpec.size, 16384])})`;
|
||||
|
||||
case 'HLLSketchBuild':
|
||||
case 'HLLSketchMerge':
|
||||
return `APPROX_COUNT_DISTINCT_DS_HLL(${ref}${extraArgs(
|
||||
return `APPROX_COUNT_DISTINCT_DS_HLL(${column}${extraArgs(
|
||||
[metricSpec.lgK, 12],
|
||||
[metricSpec.tgtHllType, 'HLL_4'],
|
||||
)})`;
|
||||
|
||||
case 'quantilesDoublesSketch':
|
||||
// For consistency with the above this should be APPROX_QUANTILE_DS but that requires a post agg so it does not work quite right.
|
||||
return `DS_QUANTILES_SKETCH(${ref}${extraArgs([metricSpec.k, 128])})`;
|
||||
return `DS_QUANTILES_SKETCH(${column}${extraArgs([metricSpec.k, 128])})`;
|
||||
|
||||
case 'hyperUnique':
|
||||
return `APPROX_COUNT_DISTINCT_BUILTIN(${ref})`;
|
||||
return `APPROX_COUNT_DISTINCT_BUILTIN(${column})`;
|
||||
|
||||
default:
|
||||
// The following things are (knowingly) not supported:
|
||||
|
@ -464,5 +459,5 @@ function extraArgs(...thingAndDefaults: [any, any?][]): string {
|
|||
}
|
||||
|
||||
if (!thingAndDefaults.length) return '';
|
||||
return ', ' + thingAndDefaults.map(([x, def]) => SqlLiteral.create(x ?? def)).join(', ');
|
||||
return ', ' + thingAndDefaults.map(([x, def]) => L(x ?? def)).join(', ');
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import { IconName } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlRef } from 'druid-query-toolkit';
|
||||
import { C, F, SqlExpression } from 'druid-query-toolkit';
|
||||
import { Filter } from 'react-table';
|
||||
|
||||
import { addOrUpdate, caseInsensitiveContains } from '../utils';
|
||||
|
@ -142,24 +142,21 @@ export function sqlQueryCustomTableFilter(filter: Filter): SqlExpression | undef
|
|||
const modeAndNeedle = parseFilterModeAndNeedle(filter);
|
||||
if (!modeAndNeedle) return;
|
||||
const { mode, needle } = modeAndNeedle;
|
||||
const column = SqlRef.column(filter.id);
|
||||
const needleLiteral = SqlLiteral.create(needle);
|
||||
const column = C(filter.id);
|
||||
switch (mode) {
|
||||
case '=':
|
||||
return column.equal(needleLiteral);
|
||||
return column.equal(needle);
|
||||
|
||||
case '!=':
|
||||
return column.unequal(needleLiteral);
|
||||
return column.unequal(needle);
|
||||
|
||||
case '<=':
|
||||
return column.lessThanOrEqual(needleLiteral);
|
||||
return column.lessThanOrEqual(needle);
|
||||
|
||||
case '>=':
|
||||
return column.greaterThanOrEqual(needleLiteral);
|
||||
return column.greaterThanOrEqual(needle);
|
||||
|
||||
default:
|
||||
return SqlFunction.simple('LOWER', [column]).like(
|
||||
SqlLiteral.create(`%${needle.toLowerCase()}%`),
|
||||
);
|
||||
return F('LOWER', column).like(`%${needle.toLowerCase()}%`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
*/
|
||||
|
||||
import axios, { AxiosResponse } from 'axios';
|
||||
import { SqlRef } from 'druid-query-toolkit';
|
||||
import { C } from 'druid-query-toolkit';
|
||||
|
||||
import { Api } from '../singletons';
|
||||
|
||||
|
@ -309,6 +309,6 @@ export interface QueryExplanation {
|
|||
|
||||
export function formatSignature(queryExplanation: QueryExplanation): string {
|
||||
return queryExplanation.signature
|
||||
.map(({ name, type }) => `${SqlRef.columnWithoutQuotes(name)}::${type}`)
|
||||
.map(({ name, type }) => `${C.optionalQuotes(name)}::${type}`)
|
||||
.join(', ');
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlBase, SqlLiteral, SqlQuery } from 'druid-query-toolkit';
|
||||
import { L, SqlBase, SqlQuery } from 'druid-query-toolkit';
|
||||
|
||||
export const EMPTY_LITERAL = SqlLiteral.create('');
|
||||
export const EMPTY_LITERAL = L('');
|
||||
|
||||
const CRAZY_STRING = '$.X.@.X.$';
|
||||
const DOT_DOT_DOT_LITERAL = SqlLiteral.create('...');
|
||||
const DOT_DOT_DOT_LITERAL = L('...');
|
||||
|
||||
export function prettyPrintSql(b: SqlBase): string {
|
||||
return b
|
||||
|
@ -44,14 +44,7 @@ export interface RowColumn {
|
|||
}
|
||||
|
||||
export function findEmptyLiteralPosition(query: SqlQuery): RowColumn | undefined {
|
||||
const subQueryString = query
|
||||
.walk(b => {
|
||||
if (b === EMPTY_LITERAL) {
|
||||
return SqlLiteral.create(CRAZY_STRING);
|
||||
}
|
||||
return b;
|
||||
})
|
||||
.toString();
|
||||
const subQueryString = query.walk(b => (b === EMPTY_LITERAL ? L(CRAZY_STRING) : b)).toString();
|
||||
|
||||
const crazyIndex = subQueryString.indexOf(CRAZY_STRING);
|
||||
if (crazyIndex < 0) return;
|
||||
|
|
|
@ -17,18 +17,18 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
C,
|
||||
Column,
|
||||
F,
|
||||
L,
|
||||
LiteralValue,
|
||||
QueryResult,
|
||||
RefName,
|
||||
SqlAlias,
|
||||
SqlColumnList,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlLiteral,
|
||||
SqlQuery,
|
||||
SqlRecord,
|
||||
SqlRef,
|
||||
SqlValues,
|
||||
} from 'druid-query-toolkit';
|
||||
|
||||
|
@ -50,13 +50,13 @@ export function sampleDataToQuery(sample: QueryResult): SqlQuery {
|
|||
SqlRecord.create(
|
||||
row.map((r, i) => {
|
||||
if (header[i].nativeType === 'COMPLEX<json>') {
|
||||
return SqlLiteral.create(JSON.stringify(r));
|
||||
return L(JSON.stringify(r));
|
||||
} else if (Array.isArray(r)) {
|
||||
arrayIndexes[i] = true;
|
||||
return SqlLiteral.create(r.join(SAMPLE_ARRAY_SEPARATOR));
|
||||
return L(r.join(SAMPLE_ARRAY_SEPARATOR));
|
||||
} else {
|
||||
// Avoid actually using NULL literals as they create havc in the VALUES type system and throw errors.
|
||||
return SqlLiteral.create(r == null ? nullForColumn(header[i]) : r);
|
||||
// Avoid actually using NULL literals as they create havoc in the VALUES type system and throw errors.
|
||||
return L(r == null ? nullForColumn(header[i]) : r);
|
||||
}
|
||||
}),
|
||||
),
|
||||
|
@ -67,11 +67,11 @@ export function sampleDataToQuery(sample: QueryResult): SqlQuery {
|
|||
}),
|
||||
).changeSelectExpressions(
|
||||
header.map((h, i) => {
|
||||
let ex: SqlExpression = SqlRef.column(`c${i}`);
|
||||
let ex: SqlExpression = C(`c${i}`);
|
||||
if (h.nativeType === 'COMPLEX<json>') {
|
||||
ex = SqlFunction.simple('PARSE_JSON', [ex]);
|
||||
ex = F('PARSE_JSON', ex);
|
||||
} else if (arrayIndexes[i]) {
|
||||
ex = SqlFunction.simple('STRING_TO_MV', [ex, SqlLiteral.create(SAMPLE_ARRAY_SEPARATOR)]);
|
||||
ex = F('STRING_TO_MV', ex, SAMPLE_ARRAY_SEPARATOR);
|
||||
} else if (h.sqlType) {
|
||||
ex = ex.cast(h.sqlType);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlRef, SqlStar } from 'druid-query-toolkit';
|
||||
import { SqlColumn, SqlExpression, SqlFunction, SqlLiteral, SqlStar } from 'druid-query-toolkit';
|
||||
|
||||
export function timeFormatToSql(timeFormat: string): SqlExpression | undefined {
|
||||
switch (timeFormat) {
|
||||
|
@ -54,7 +54,7 @@ export function convertToGroupByExpression(ex: SqlExpression): SqlExpression | u
|
|||
if (interestingArgs.length !== 1) return;
|
||||
|
||||
const newEx = interestingArgs[0];
|
||||
if (newEx instanceof SqlRef) return newEx;
|
||||
if (newEx instanceof SqlColumn) return newEx;
|
||||
|
||||
return newEx.as((ex.getOutputName() || 'grouped').replace(/^[a-z]+_/i, ''));
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { FormGroup, InputGroup, Intent, MenuItem, Switch } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import classNames from 'classnames';
|
||||
import { SqlQuery, SqlTableRef } from 'druid-query-toolkit';
|
||||
import { SqlQuery, T } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
import ReactTable, { Filter } from 'react-table';
|
||||
|
||||
|
@ -830,8 +830,7 @@ ORDER BY 1`;
|
|||
goToActions.push({
|
||||
icon: IconNames.APPLICATION,
|
||||
title: 'Query with SQL',
|
||||
onAction: () =>
|
||||
goToQuery({ queryString: SqlQuery.create(SqlTableRef.create(datasource)).toString() }),
|
||||
onAction: () => goToQuery({ queryString: SqlQuery.create(T(datasource)).toString() }),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { Button, ButtonGroup, Intent, Label, MenuItem, Switch } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import classNames from 'classnames';
|
||||
import { SqlComparison, SqlExpression, SqlLiteral, SqlRef } from 'druid-query-toolkit';
|
||||
import { C, L, SqlComparison, SqlExpression } from 'druid-query-toolkit';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
import React from 'react';
|
||||
import ReactTable, { Filter } from 'react-table';
|
||||
|
@ -125,7 +125,7 @@ const tableColumns: Record<CapabilitiesMode, string[]> = {
|
|||
};
|
||||
|
||||
function formatRangeDimensionValue(dimension: any, value: any): string {
|
||||
return `${SqlRef.column(String(dimension))}=${SqlLiteral.create(String(value))}`;
|
||||
return `${C(String(dimension))}=${L(String(value))}`;
|
||||
}
|
||||
|
||||
export interface SegmentsViewProps {
|
||||
|
@ -281,20 +281,23 @@ END AS "time_span"`,
|
|||
// Creates filters like `shard_spec LIKE '%"type":"numbered"%'`
|
||||
const modeAndNeedle = parseFilterModeAndNeedle(f);
|
||||
if (!modeAndNeedle) return;
|
||||
const shardSpecRef = SqlRef.column('shard_spec');
|
||||
const shardSpecColumn = C('shard_spec');
|
||||
switch (modeAndNeedle.mode) {
|
||||
case '=':
|
||||
return SqlComparison.like(shardSpecRef, `%"type":"${modeAndNeedle.needle}"%`);
|
||||
return SqlComparison.like(shardSpecColumn, `%"type":"${modeAndNeedle.needle}"%`);
|
||||
|
||||
case '!=':
|
||||
return SqlComparison.notLike(shardSpecRef, `%"type":"${modeAndNeedle.needle}"%`);
|
||||
return SqlComparison.notLike(
|
||||
shardSpecColumn,
|
||||
`%"type":"${modeAndNeedle.needle}"%`,
|
||||
);
|
||||
|
||||
default:
|
||||
return SqlComparison.like(shardSpecRef, `%"type":"${modeAndNeedle.needle}%`);
|
||||
return SqlComparison.like(shardSpecColumn, `%"type":"${modeAndNeedle.needle}%`);
|
||||
}
|
||||
} else if (f.id.startsWith('is_')) {
|
||||
if (f.value === 'all') return;
|
||||
return SqlRef.column(f.id).equal(f.value === 'true' ? 1 : 0);
|
||||
return C(f.id).equal(f.value === 'true' ? 1 : 0);
|
||||
} else {
|
||||
return sqlQueryCustomTableFilter(f);
|
||||
}
|
||||
|
@ -335,7 +338,7 @@ END AS "time_span"`,
|
|||
queryParts.push(
|
||||
'ORDER BY ' +
|
||||
sorted
|
||||
.map((sort: any) => `${SqlRef.column(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
||||
.map((sort: any) => `${C(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
||||
.join(', '),
|
||||
);
|
||||
}
|
||||
|
@ -352,7 +355,7 @@ END AS "time_span"`,
|
|||
queryParts.push(
|
||||
'ORDER BY ' +
|
||||
sorted
|
||||
.map((sort: any) => `${SqlRef.column(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
||||
.map((sort: any) => `${C(sort.id)} ${sort.desc ? 'DESC' : 'ASC'}`)
|
||||
.join(', '),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { Button, FormGroup, Menu, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import { QueryResult, SqlExpression, SqlFunction } from 'druid-query-toolkit';
|
||||
import { F, QueryResult, SqlExpression } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { possibleDruidFormatForValues, TIME_COLUMN } from '../../../druid-models';
|
||||
|
@ -49,7 +49,7 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
|
||||
const expression = queryResult.sqlQuery?.getSelectExpressionForIndex(headerIndex);
|
||||
|
||||
if (sqlQuery.getEffectiveWhereExpression().containsColumn(header)) {
|
||||
if (sqlQuery.getEffectiveWhereExpression().containsColumnName(header)) {
|
||||
removeFilterButton = (
|
||||
<Button
|
||||
icon={IconNames.FILTER_REMOVE}
|
||||
|
@ -147,7 +147,6 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
};
|
||||
|
||||
const underlyingSelectExpression = expression.getUnderlyingExpression();
|
||||
|
||||
convertButton = (
|
||||
<Popover2
|
||||
content={
|
||||
|
@ -159,9 +158,7 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to SUM(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('SUM', [underlyingSelectExpression]).as(
|
||||
`sum_${header}`,
|
||||
),
|
||||
F('SUM', underlyingSelectExpression).as(`sum_${header}`),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -169,9 +166,7 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to MIN(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('MIN', [underlyingSelectExpression]).as(
|
||||
`min_${header}`,
|
||||
),
|
||||
F('MIN', underlyingSelectExpression).as(`min_${header}`),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -179,9 +174,7 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to MAX(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('MAX', [underlyingSelectExpression]).as(
|
||||
`max_${header}`,
|
||||
),
|
||||
F('MAX', underlyingSelectExpression).as(`max_${header}`),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -189,15 +182,9 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to SUM(...), MIN(...), and MAX(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('SUM', [underlyingSelectExpression]).as(
|
||||
`sum_${header}`,
|
||||
),
|
||||
SqlFunction.simple('MIN', [underlyingSelectExpression]).as(
|
||||
`min_${header}`,
|
||||
),
|
||||
SqlFunction.simple('MAX', [underlyingSelectExpression]).as(
|
||||
`max_${header}`,
|
||||
),
|
||||
F('SUM', underlyingSelectExpression).as(`sum_${header}`),
|
||||
F('MIN', underlyingSelectExpression).as(`min_${header}`),
|
||||
F('MAX', underlyingSelectExpression).as(`max_${header}`),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -207,9 +194,9 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to APPROX_COUNT_DISTINCT_DS_HLL(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('APPROX_COUNT_DISTINCT_DS_HLL', [
|
||||
underlyingSelectExpression,
|
||||
]).as(`unique_${header}`),
|
||||
F('APPROX_COUNT_DISTINCT_DS_HLL', underlyingSelectExpression).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -217,9 +204,9 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to APPROX_COUNT_DISTINCT_DS_THETA(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('APPROX_COUNT_DISTINCT_DS_THETA', [
|
||||
underlyingSelectExpression,
|
||||
]).as(`unique_${header}`),
|
||||
F('APPROX_COUNT_DISTINCT_DS_THETA', underlyingSelectExpression).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
@ -227,9 +214,9 @@ export const ColumnActions = React.memo(function ExpressionEditor(props: ColumnA
|
|||
text="Convert to APPROX_COUNT_DISTINCT_BUILTIN(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate([
|
||||
SqlFunction.simple('APPROX_COUNT_DISTINCT_BUILTIN', [
|
||||
underlyingSelectExpression,
|
||||
]).as(`unique_${header}`),
|
||||
F('APPROX_COUNT_DISTINCT_BUILTIN', underlyingSelectExpression).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
]);
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { Button, Classes, Dialog, Intent } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import classNames from 'classnames';
|
||||
import { SqlTableRef } from 'druid-query-toolkit';
|
||||
import { T } from 'druid-query-toolkit';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Execution, QueryWithContext } from '../../../druid-models';
|
||||
|
@ -117,7 +117,7 @@ export const IngestionProgressDialog = React.memo(function IngestionProgressDial
|
|||
onClick={() => {
|
||||
if (!insertResultState.data) return;
|
||||
goToQuery({
|
||||
queryString: `SELECT * FROM ${SqlTableRef.create(
|
||||
queryString: `SELECT * FROM ${T(
|
||||
insertResultState.data.getIngestDatasource()!,
|
||||
)}`,
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import { Icon } from '@blueprintjs/core';
|
||||
import classNames from 'classnames';
|
||||
import { Column, QueryResult, SqlRef } from 'druid-query-toolkit';
|
||||
import { Column, QueryResult, SqlColumn } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { columnToIcon } from '../../../../../utils';
|
||||
|
@ -60,7 +60,7 @@ export const ExpressionEntry = function ExpressionEntry(props: ExpressionEntryPr
|
|||
{expression.getOutputName() || 'EXPR?'}
|
||||
<span className="type-name">{` :: ${column.nativeType}`}</span>
|
||||
</div>
|
||||
{!(expression instanceof SqlRef) && (
|
||||
{!(expression instanceof SqlColumn) && (
|
||||
<div className="expression">
|
||||
{expression.getUnderlyingExpression().prettify({ keywordCasing: 'preserve' }).toString()}
|
||||
</div>
|
||||
|
|
|
@ -76,8 +76,8 @@ export const PreviewTable = React.memo(function PreviewTable(props: PreviewTable
|
|||
if (!parsedQuery || !parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) return false;
|
||||
|
||||
return (
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumn(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumn(header)
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumnName(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumnName(header)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import { Button, Callout, Intent, Tag } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { CancelToken } from 'axios';
|
||||
import { QueryResult, SqlExpression, SqlFunction, SqlQuery } from 'druid-query-toolkit';
|
||||
import { F, QueryResult, SqlExpression, SqlFunction, SqlQuery } from 'druid-query-toolkit';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { Execution } from '../../../../druid-models';
|
||||
|
@ -47,8 +47,8 @@ function expressionCastToString(ex: SqlExpression): SqlExpression {
|
|||
return CAST_AS_VARCHAR_TEMPLATE.fillPlaceholders([ex]);
|
||||
}
|
||||
|
||||
function countDistinct(ex: SqlExpression): SqlExpression {
|
||||
return SqlFunction.simple('APPROX_COUNT_DISTINCT_DS_HLL', [ex]);
|
||||
function approxCountDistinct(ex: SqlExpression): SqlExpression {
|
||||
return F('APPROX_COUNT_DISTINCT_DS_HLL', ex);
|
||||
}
|
||||
|
||||
function within(a: number, b: number, percent: number): boolean {
|
||||
|
@ -159,13 +159,13 @@ export const RollupAnalysisPane = React.memo(function RollupAnalysisPane(
|
|||
|
||||
const expressionPairs: SqlExpression[] = deep
|
||||
? pairs(expressions.length).map(([i, j]) =>
|
||||
countDistinct(SqlFunction.simple('CONCAT', [groupedAsStrings[i], groupedAsStrings[j]])),
|
||||
approxCountDistinct(F('CONCAT', groupedAsStrings[i], groupedAsStrings[j])),
|
||||
)
|
||||
: [];
|
||||
|
||||
const queryString = seedQuery
|
||||
.changeSelectExpressions(groupedAsStrings.map(countDistinct).concat(expressionPairs))
|
||||
.addSelect(countDistinct(SqlFunction.simple('CONCAT', groupedAsStrings)), {
|
||||
.changeSelectExpressions(groupedAsStrings.map(approxCountDistinct).concat(expressionPairs))
|
||||
.addSelect(approxCountDistinct(SqlFunction.simple('CONCAT', groupedAsStrings)), {
|
||||
insertIndex: 0,
|
||||
})
|
||||
.addSelect(SqlFunction.COUNT_STAR, { insertIndex: 0 })
|
||||
|
|
|
@ -32,14 +32,7 @@ import { IconNames } from '@blueprintjs/icons';
|
|||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import classNames from 'classnames';
|
||||
import { select, selectAll } from 'd3-selection';
|
||||
import {
|
||||
QueryResult,
|
||||
QueryRunner,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
} from 'druid-query-toolkit';
|
||||
import { C, F, QueryResult, QueryRunner, SqlExpression, SqlQuery } from 'druid-query-toolkit';
|
||||
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { ClearableInput, LearnMore, Loader } from '../../../components';
|
||||
|
@ -361,10 +354,9 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
|
|||
...ingestQueryPattern,
|
||||
dimensions: without(ingestQueryPattern.dimensions, countExpression),
|
||||
metrics: [
|
||||
(countExpression
|
||||
? SqlFunction.simple('SUM', [countExpression.getUnderlyingExpression()])
|
||||
: SqlFunction.COUNT_STAR
|
||||
).as(countExpression?.getOutputName() || 'count'),
|
||||
(countExpression ? F.sum(countExpression.getUnderlyingExpression()) : F.count()).as(
|
||||
countExpression?.getOutputName() || 'count',
|
||||
),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
@ -460,8 +452,8 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
|
|||
const unusedColumns = ingestQueryPattern
|
||||
? ingestQueryPattern.mainExternalConfig.signature.filter(
|
||||
({ name }) =>
|
||||
!ingestQueryPattern.dimensions.some(d => d.containsColumn(name)) &&
|
||||
!ingestQueryPattern.metrics?.some(m => m.containsColumn(name)),
|
||||
!ingestQueryPattern.dimensions.some(d => d.containsColumnName(name)) &&
|
||||
!ingestQueryPattern.metrics?.some(m => m.containsColumnName(name)),
|
||||
)
|
||||
: [];
|
||||
|
||||
|
@ -714,7 +706,7 @@ export const SchemaStep = function SchemaStep(props: SchemaStepProps) {
|
|||
onClick={() => {
|
||||
handleQueryAction(q =>
|
||||
q.addSelect(
|
||||
SqlRef.column(column.name),
|
||||
C(column.name),
|
||||
ingestQueryPattern.metrics
|
||||
? { insertIndex: 'last-grouping', addToGroupBy: 'end' }
|
||||
: {},
|
||||
|
|
|
@ -107,7 +107,7 @@ export const SqlDataLoaderView = React.memo(function SqlDataLoaderView(
|
|||
onDone={async () => {
|
||||
const ingestDatasource = SqlQuery.parse(content.queryString)
|
||||
.getIngestTable()
|
||||
?.getTable();
|
||||
?.getName();
|
||||
|
||||
if (!ingestDatasource) {
|
||||
AppToaster.show({ message: `Must have an ingest datasource`, intent: Intent.DANGER });
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
|
||||
import { MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlQuery, SqlRef } from 'druid-query-toolkit';
|
||||
import { C, F, L, SqlExpression, SqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { prettyPrintSql } from '../../../../../utils';
|
||||
|
||||
const NINE_THOUSAND = SqlLiteral.create(9000);
|
||||
const NINE_THOUSAND = L(9000);
|
||||
|
||||
export interface NumberMenuItemsProps {
|
||||
table: string;
|
||||
|
@ -36,7 +36,6 @@ export interface NumberMenuItemsProps {
|
|||
export const NumberMenuItems = React.memo(function NumberMenuItems(props: NumberMenuItemsProps) {
|
||||
function renderFilterMenu(): JSX.Element {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function filterMenuItem(clause: SqlExpression) {
|
||||
return (
|
||||
|
@ -49,17 +48,18 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.FILTER} text="Filter">
|
||||
{filterMenuItem(ref.greaterThan(NINE_THOUSAND))}
|
||||
{filterMenuItem(ref.lessThanOrEqual(NINE_THOUSAND))}
|
||||
{filterMenuItem(column.greaterThan(NINE_THOUSAND))}
|
||||
{filterMenuItem(column.lessThanOrEqual(NINE_THOUSAND))}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumn(columnName)) return;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumnName(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -75,7 +75,6 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
function renderGroupByMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function groupByMenuItem(ex: SqlExpression, alias?: string) {
|
||||
return (
|
||||
|
@ -94,13 +93,11 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text="Group by">
|
||||
{groupByMenuItem(ref)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TRUNC', [ref, SqlLiteral.create(-1)]),
|
||||
`${columnName}_truncated`,
|
||||
)}
|
||||
{groupByMenuItem(column)}
|
||||
{groupByMenuItem(F('TRUNC', column, -1), `${columnName}_truncated`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
@ -124,7 +121,6 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function aggregateMenuItem(ex: SqlExpression, alias: string) {
|
||||
return (
|
||||
|
@ -137,17 +133,15 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text="Aggregate">
|
||||
{aggregateMenuItem(SqlFunction.simple('SUM', [ref]), `sum_${columnName}`)}
|
||||
{aggregateMenuItem(SqlFunction.simple('MIN', [ref]), `min_${columnName}`)}
|
||||
{aggregateMenuItem(SqlFunction.simple('MAX', [ref]), `max_${columnName}`)}
|
||||
{aggregateMenuItem(SqlFunction.simple('AVG', [ref]), `avg_${columnName}`)}
|
||||
{aggregateMenuItem(
|
||||
SqlFunction.simple('APPROX_QUANTILE', [ref, SqlLiteral.create(0.98)]),
|
||||
`p98_${columnName}`,
|
||||
)}
|
||||
{aggregateMenuItem(SqlFunction.simple('LATEST', [ref]), `latest_${columnName}`)}
|
||||
{aggregateMenuItem(F('SUM', column), `sum_${columnName}`)}
|
||||
{aggregateMenuItem(F('MIN', column), `min_${columnName}`)}
|
||||
{aggregateMenuItem(F('MAX', column), `max_${columnName}`)}
|
||||
{aggregateMenuItem(F('AVG', column), `avg_${columnName}`)}
|
||||
{aggregateMenuItem(F('APPROX_QUANTILE', column, 0.98), `p98_${columnName}`)}
|
||||
{aggregateMenuItem(F('LATEST', column), `latest_${columnName}`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,15 +18,7 @@
|
|||
|
||||
import { MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import {
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlJoinPart,
|
||||
SqlLiteral,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlTableRef,
|
||||
} from 'druid-query-toolkit';
|
||||
import { C, F, N, SqlExpression, SqlJoinPart, SqlQuery, T } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { EMPTY_LITERAL, prettyPrintSql } from '../../../../../utils';
|
||||
|
@ -43,7 +35,6 @@ export interface StringMenuItemsProps {
|
|||
export const StringMenuItems = React.memo(function StringMenuItems(props: StringMenuItemsProps) {
|
||||
function renderFilterMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function filterMenuItem(clause: SqlExpression, run = true) {
|
||||
return (
|
||||
|
@ -56,19 +47,20 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.FILTER} text="Filter">
|
||||
{filterMenuItem(ref.isNotNull())}
|
||||
{filterMenuItem(ref.equal(EMPTY_LITERAL), false)}
|
||||
{filterMenuItem(ref.like(EMPTY_LITERAL), false)}
|
||||
{filterMenuItem(SqlFunction.simple('REGEXP_LIKE', [ref, EMPTY_LITERAL]), false)}
|
||||
{filterMenuItem(column.isNotNull())}
|
||||
{filterMenuItem(column.equal(EMPTY_LITERAL), false)}
|
||||
{filterMenuItem(column.like(EMPTY_LITERAL), false)}
|
||||
{filterMenuItem(F('REGEXP_LIKE', column, EMPTY_LITERAL), false)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumn(columnName)) return;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumnName(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -118,24 +110,12 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text="Group by">
|
||||
{groupByMenuItem(SqlRef.column(columnName))}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('SUBSTRING', [
|
||||
SqlRef.column(columnName),
|
||||
SqlLiteral.create(1),
|
||||
SqlLiteral.create(2),
|
||||
]),
|
||||
`${columnName}_substring`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('REGEXP_EXTRACT', [
|
||||
SqlRef.column(columnName),
|
||||
SqlLiteral.create('(\\d+)'),
|
||||
]),
|
||||
`${columnName}_extract`,
|
||||
)}
|
||||
{groupByMenuItem(column)}
|
||||
{groupByMenuItem(F('SUBSTRING', column, 1, 2), `${columnName}_substring`)}
|
||||
{groupByMenuItem(F('REGEXP_EXTRACT', column, '(\\d+)'), `${columnName}_extract`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
@ -143,7 +123,6 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function aggregateMenuItem(ex: SqlExpression, alias: string, run = true) {
|
||||
return (
|
||||
|
@ -156,18 +135,16 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text="Aggregate">
|
||||
{aggregateMenuItem(SqlFunction.countDistinct(ref), `dist_${columnName}`)}
|
||||
{aggregateMenuItem(F.countDistinct(column), `dist_${columnName}`)}
|
||||
{aggregateMenuItem(
|
||||
SqlFunction.COUNT_STAR.addWhereExpression(ref.equal(EMPTY_LITERAL)),
|
||||
F.count().addWhereExpression(column.equal(EMPTY_LITERAL)),
|
||||
`filtered_dist_${columnName}`,
|
||||
false,
|
||||
)}
|
||||
{aggregateMenuItem(
|
||||
SqlFunction.simple('LATEST', [ref, SqlLiteral.create(100)]),
|
||||
`latest_${columnName}`,
|
||||
)}
|
||||
{aggregateMenuItem(F('LATEST', column, 100), `latest_${columnName}`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
@ -175,6 +152,8 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
function renderJoinMenu(): JSX.Element | undefined {
|
||||
const { schema, table, columnName, parsedQuery, onQueryChange } = props;
|
||||
if (schema !== 'lookup' || !parsedQuery) return;
|
||||
const firstTableName = parsedQuery.getFirstTableName();
|
||||
if (!firstTableName) return;
|
||||
|
||||
const { originalTableColumn, lookupColumn } = getJoinColumns(parsedQuery, table);
|
||||
|
||||
|
@ -188,13 +167,15 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
parsedQuery.addJoin(
|
||||
SqlJoinPart.create(
|
||||
'LEFT',
|
||||
SqlTableRef.create(table, schema),
|
||||
SqlRef.column(columnName, table, 'lookup').equal(
|
||||
SqlRef.column(
|
||||
lookupColumn === columnName ? originalTableColumn : 'XXX',
|
||||
parsedQuery.getFirstTableName(),
|
||||
N(schema).table(table),
|
||||
N('lookup')
|
||||
.table(table)
|
||||
.column(columnName)
|
||||
.equal(
|
||||
T(firstTableName).column(
|
||||
lookupColumn === columnName ? originalTableColumn : 'XXX',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
false,
|
||||
|
@ -209,13 +190,15 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
parsedQuery.addJoin(
|
||||
SqlJoinPart.create(
|
||||
'INNER',
|
||||
SqlTableRef.create(table, schema),
|
||||
SqlRef.column(columnName, table, 'lookup').equal(
|
||||
SqlRef.column(
|
||||
lookupColumn === columnName ? originalTableColumn : 'XXX',
|
||||
parsedQuery.getFirstTableName(),
|
||||
N(schema).table(table),
|
||||
N('lookup')
|
||||
.table(table)
|
||||
.column(columnName)
|
||||
.equal(
|
||||
T(firstTableName).column(
|
||||
lookupColumn === columnName ? originalTableColumn : 'XXX',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
false,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import { MenuDivider, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral, SqlQuery, SqlRef } from 'druid-query-toolkit';
|
||||
import { C, F, SqlExpression, SqlQuery } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { prettyPrintSql } from '../../../../../utils';
|
||||
|
@ -42,12 +42,12 @@ const BETWEEN: SqlExpression = SqlExpression.parse(`(? <= ? AND ? < ?)`);
|
|||
// ------------------------------------
|
||||
|
||||
function fillWithColumn(b: SqlExpression, columnName: string): SqlExpression {
|
||||
return b.fillPlaceholders([SqlRef.column(columnName)]);
|
||||
return b.fillPlaceholders([C(columnName)]);
|
||||
}
|
||||
|
||||
function fillWithColumnStartEnd(columnName: string, start: Date, end: Date): SqlExpression {
|
||||
const ref = SqlRef.column(columnName);
|
||||
return BETWEEN.fillPlaceholders([SqlLiteral.create(start), ref, ref, SqlLiteral.create(end)])!;
|
||||
const column = C(columnName);
|
||||
return BETWEEN.fillPlaceholders([start, column, column, end])!;
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
|
@ -160,7 +160,7 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumn(columnName)) return;
|
||||
if (!parsedQuery.getEffectiveWhereExpression().containsColumnName(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -192,7 +192,6 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
function renderGroupByMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function groupByMenuItem(ex: SqlExpression, alias: string) {
|
||||
return (
|
||||
|
@ -211,41 +210,18 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text="Group by">
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_FLOOR', [ref, SqlLiteral.create('PT1H')]),
|
||||
`${columnName}_by_hour`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_FLOOR', [ref, SqlLiteral.create('P1D')]),
|
||||
`${columnName}_by_day`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_FLOOR', [ref, SqlLiteral.create('P1M')]),
|
||||
`${columnName}_by_month`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_FLOOR', [ref, SqlLiteral.create('P1Y')]),
|
||||
`${columnName}_by_year`,
|
||||
)}
|
||||
{groupByMenuItem(F.timeFloor(column, 'PT1H'), `${columnName}_by_hour`)}
|
||||
{groupByMenuItem(F.timeFloor(column, 'P1D'), `${columnName}_by_day`)}
|
||||
{groupByMenuItem(F.timeFloor(column, 'P1M'), `${columnName}_by_month`)}
|
||||
{groupByMenuItem(F.timeFloor(column, 'P1Y'), `${columnName}_by_year`)}
|
||||
<MenuDivider />
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_EXTRACT', [ref, SqlLiteral.create('HOUR')]),
|
||||
`hour_of_${columnName}`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_EXTRACT', [ref, SqlLiteral.create('DAY')]),
|
||||
`day_of_${columnName}`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_EXTRACT', [ref, SqlLiteral.create('MONTH')]),
|
||||
`month_of_${columnName}`,
|
||||
)}
|
||||
{groupByMenuItem(
|
||||
SqlFunction.simple('TIME_EXTRACT', [ref, SqlLiteral.create('YEAR')]),
|
||||
`year_of_${columnName}`,
|
||||
)}
|
||||
{groupByMenuItem(F('TIME_EXTRACT', column, 'HOUR'), `hour_of_${columnName}`)}
|
||||
{groupByMenuItem(F('TIME_EXTRACT', column, 'DAY'), `day_of_${columnName}`)}
|
||||
{groupByMenuItem(F('TIME_EXTRACT', column, 'MONTH'), `month_of_${columnName}`)}
|
||||
{groupByMenuItem(F('TIME_EXTRACT', column, 'YEAR'), `year_of_${columnName}`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
@ -253,7 +229,6 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
const ref = SqlRef.column(columnName);
|
||||
|
||||
function aggregateMenuItem(ex: SqlExpression, alias: string) {
|
||||
return (
|
||||
|
@ -266,10 +241,11 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
);
|
||||
}
|
||||
|
||||
const column = C(columnName);
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text="Aggregate">
|
||||
{aggregateMenuItem(SqlFunction.simple('MAX', [ref]), `max_${columnName}`)}
|
||||
{aggregateMenuItem(SqlFunction.simple('MIN', [ref]), `min_${columnName}`)}
|
||||
{aggregateMenuItem(F.max(column), `max_${columnName}`)}
|
||||
{aggregateMenuItem(F.min(column), `min_${columnName}`)}
|
||||
</MenuItem>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -20,13 +20,16 @@ import { HTMLSelect, Menu, MenuItem, Position, Tree, TreeNodeInfo } from '@bluep
|
|||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import {
|
||||
C,
|
||||
F,
|
||||
N,
|
||||
SqlColumn,
|
||||
SqlComparison,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlJoinPart,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlTableRef,
|
||||
SqlTable,
|
||||
T,
|
||||
} from 'druid-query-toolkit';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
|
||||
|
@ -44,12 +47,12 @@ import { NumberMenuItems, StringMenuItems, TimeMenuItems } from './column-tree-m
|
|||
|
||||
import './column-tree.scss';
|
||||
|
||||
const COUNT_STAR = SqlFunction.COUNT_STAR.as('Count');
|
||||
const COUNT_STAR = F.count().as('Count');
|
||||
|
||||
function getCountExpression(columnNames: string[]): SqlExpression {
|
||||
for (const columnName of columnNames) {
|
||||
if (columnName === 'count' || columnName === '__count') {
|
||||
return SqlFunction.simple('SUM', [SqlRef.column(columnName)]).as('Count');
|
||||
return F.sum(C(columnName)).as('Count');
|
||||
}
|
||||
}
|
||||
return COUNT_STAR;
|
||||
|
@ -96,22 +99,22 @@ function handleColumnShow(options: HandleColumnClickOptions): void {
|
|||
where = parsedQuery.getWhereExpression();
|
||||
aggregates = parsedQuery.getAggregateSelectExpressions();
|
||||
} else if (columnSchema === 'druid') {
|
||||
from = SqlTableRef.create(columnTable);
|
||||
from = T(columnTable);
|
||||
where = defaultWhere;
|
||||
} else {
|
||||
from = SqlTableRef.create(columnTable, columnSchema);
|
||||
from = N(columnSchema).table(columnTable);
|
||||
}
|
||||
|
||||
if (!aggregates.length) {
|
||||
aggregates.push(COUNT_STAR);
|
||||
}
|
||||
|
||||
const columnRef = SqlRef.column(columnName);
|
||||
const column = C(columnName);
|
||||
let query: SqlQuery;
|
||||
if (columnSchema === 'druid' && columnType === 'TIMESTAMP') {
|
||||
query = TIME_QUERY.fillPlaceholders([columnRef, from]) as SqlQuery;
|
||||
query = TIME_QUERY.fillPlaceholders([column, from]) as SqlQuery;
|
||||
} else {
|
||||
query = STRING_QUERY.fillPlaceholders([columnRef, from]) as SqlQuery;
|
||||
query = STRING_QUERY.fillPlaceholders([column, from]) as SqlQuery;
|
||||
}
|
||||
|
||||
let newSelectExpressions = query.selectExpressions;
|
||||
|
@ -152,11 +155,11 @@ export function getJoinColumns(parsedQuery: SqlQuery, _table: string) {
|
|||
const firstOnExpression = parsedQuery.fromClause.joinParts.first().onExpression;
|
||||
if (firstOnExpression instanceof SqlComparison && firstOnExpression.op === '=') {
|
||||
const { lhs, rhs } = firstOnExpression;
|
||||
if (lhs instanceof SqlRef && lhs.getNamespace() === 'lookup') {
|
||||
lookupColumn = lhs.getColumn();
|
||||
if (lhs instanceof SqlColumn && lhs.getNamespaceName() === 'lookup') {
|
||||
lookupColumn = lhs.getName();
|
||||
}
|
||||
if (rhs instanceof SqlRef) {
|
||||
originalTableColumn = rhs.getColumn();
|
||||
if (rhs instanceof SqlColumn) {
|
||||
originalTableColumn = rhs.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +202,7 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
<Deferred
|
||||
content={() => {
|
||||
const parsedQuery = props.getParsedQuery();
|
||||
const tableRef = SqlTableRef.create(tableName);
|
||||
const tableRef = T(tableName);
|
||||
const prettyTableRef = prettyPrintSql(tableRef);
|
||||
const countExpression = getCountExpression(
|
||||
metadata.map(child => child.COLUMN_NAME),
|
||||
|
@ -207,7 +210,7 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
|
||||
const getQueryOnTable = () => {
|
||||
return SqlQuery.create(
|
||||
SqlTableRef.create(
|
||||
SqlTable.create(
|
||||
tableName,
|
||||
schemaName === 'druid' ? undefined : schemaName,
|
||||
),
|
||||
|
@ -235,7 +238,7 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
.changeSelectExpressions(
|
||||
metadata
|
||||
.map(child => child.COLUMN_NAME)
|
||||
.map(columnName => SqlRef.column(columnName)),
|
||||
.map(columnName => C(columnName)),
|
||||
)
|
||||
.changeWhereExpression(getWhere()),
|
||||
true,
|
||||
|
@ -297,13 +300,16 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
.addJoin(
|
||||
SqlJoinPart.create(
|
||||
'LEFT',
|
||||
SqlTableRef.create(tableName, schemaName),
|
||||
SqlRef.column(lookupColumn, tableName, 'lookup').equal(
|
||||
SqlRef.column(
|
||||
originalTableColumn,
|
||||
parsedQuery.getFirstTableName(),
|
||||
N(schemaName).table(tableName),
|
||||
N('lookup')
|
||||
.table(tableName)
|
||||
.column(lookupColumn)
|
||||
.equal(
|
||||
SqlColumn.create(
|
||||
originalTableColumn,
|
||||
parsedQuery.getFirstTableName(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
false,
|
||||
|
@ -322,13 +328,16 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
parsedQuery.addJoin(
|
||||
SqlJoinPart.create(
|
||||
'INNER',
|
||||
SqlTableRef.create(tableName, schemaName),
|
||||
SqlRef.column(lookupColumn, tableName, 'lookup').equal(
|
||||
SqlRef.column(
|
||||
originalTableColumn,
|
||||
parsedQuery.getFirstTableName(),
|
||||
N(schemaName).table(tableName),
|
||||
N('lookup')
|
||||
.table(tableName)
|
||||
.column(lookupColumn)
|
||||
.equal(
|
||||
SqlColumn.create(
|
||||
originalTableColumn,
|
||||
parsedQuery.getFirstTableName(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
false,
|
||||
|
|
|
@ -21,7 +21,7 @@ import { ResizeSensor2 } from '@blueprintjs/popover2';
|
|||
import type { Ace } from 'ace-builds';
|
||||
import ace from 'ace-builds';
|
||||
import classNames from 'classnames';
|
||||
import { SqlRef, SqlTableRef } from 'druid-query-toolkit';
|
||||
import { C, T } from 'druid-query-toolkit';
|
||||
import escape from 'lodash.escape';
|
||||
import React from 'react';
|
||||
import AceEditor from 'react-ace';
|
||||
|
@ -164,7 +164,7 @@ export class FlexibleQueryInput extends React.PureComponent<
|
|||
) {
|
||||
const completions = ([] as any[]).concat(
|
||||
uniq(columnMetadata.map(d => d.TABLE_SCHEMA)).map(v => ({
|
||||
value: SqlTableRef.create(v).toString(),
|
||||
value: String(T(v)),
|
||||
score: 10,
|
||||
meta: 'schema',
|
||||
})),
|
||||
|
@ -173,7 +173,7 @@ export class FlexibleQueryInput extends React.PureComponent<
|
|||
.filter(d => (currentSchema ? d.TABLE_SCHEMA === currentSchema : true))
|
||||
.map(d => d.TABLE_NAME),
|
||||
).map(v => ({
|
||||
value: SqlTableRef.create(v).toString(),
|
||||
value: String(T(v)),
|
||||
score: 49,
|
||||
meta: 'datasource',
|
||||
})),
|
||||
|
@ -186,7 +186,7 @@ export class FlexibleQueryInput extends React.PureComponent<
|
|||
)
|
||||
.map(d => d.COLUMN_NAME),
|
||||
).map(v => ({
|
||||
value: SqlRef.column(v).toString(),
|
||||
value: String(C(v)),
|
||||
score: 50,
|
||||
meta: 'column',
|
||||
})),
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SqlTableRef } from 'druid-query-toolkit';
|
||||
import { T } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { Execution, WorkbenchQuery } from '../../../druid-models';
|
||||
|
@ -47,7 +47,7 @@ export const IngestSuccessPane = React.memo(function IngestSuccessPane(
|
|||
? stages.getTotalCounterForStage(lastStage, 'input0', 'rows') // Assume input0 since we know the segmentGenerator will only ever have one stage input
|
||||
: -1;
|
||||
|
||||
const table = SqlTableRef.create(datasource);
|
||||
const table = T(datasource);
|
||||
|
||||
const warnings = stages?.getWarningCount() || 0;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import { Button, Callout, FormGroup, Icon, Intent, Tag } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlRef } from 'druid-query-toolkit';
|
||||
import { C, SqlExpression } from 'druid-query-toolkit';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { AutoForm, CenterMessage, LearnMore, Loader } from '../../../components';
|
||||
|
@ -135,7 +135,7 @@ export const InputFormatStep = React.memo(function InputFormatStep(props: InputF
|
|||
|
||||
return {
|
||||
column,
|
||||
timeExpression: formatSql.fillPlaceholders([SqlRef.column(column)]),
|
||||
timeExpression: formatSql.fillPlaceholders([C(column)]),
|
||||
};
|
||||
})[0];
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ import { IconName, IconNames } from '@blueprintjs/icons';
|
|||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import classNames from 'classnames';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { SqlTableRef } from 'druid-query-toolkit';
|
||||
import { T } from 'druid-query-toolkit';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Loader } from '../../../components';
|
||||
|
@ -182,10 +182,8 @@ LIMIT 100`,
|
|||
w.datasource !== WorkbenchQuery.INLINE_DATASOURCE_MARKER && (
|
||||
<MenuItem
|
||||
icon={IconNames.APPLICATION}
|
||||
text={`SELECT * FROM ${SqlTableRef.create(w.datasource)}`}
|
||||
onClick={() =>
|
||||
onChangeQuery(`SELECT * FROM ${SqlTableRef.create(w.datasource)}`)
|
||||
}
|
||||
text={`SELECT * FROM ${T(w.datasource)}`}
|
||||
onClick={() => onChangeQuery(`SELECT * FROM ${T(w.datasource)}`)}
|
||||
/>
|
||||
)}
|
||||
<MenuItem
|
||||
|
|
|
@ -21,14 +21,15 @@ import { IconNames } from '@blueprintjs/icons';
|
|||
import { Popover2 } from '@blueprintjs/popover2';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
C,
|
||||
Column,
|
||||
F,
|
||||
QueryResult,
|
||||
SqlAlias,
|
||||
SqlExpression,
|
||||
SqlFunction,
|
||||
SqlLiteral,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlStar,
|
||||
} from 'druid-query-toolkit';
|
||||
import * as JSONBig from 'json-bigint-native';
|
||||
|
@ -65,10 +66,6 @@ import './result-table-pane.scss';
|
|||
|
||||
const CAST_TARGETS: string[] = ['VARCHAR', 'BIGINT', 'DOUBLE'];
|
||||
|
||||
function jsonValue(ex: SqlExpression, path: string): SqlExpression {
|
||||
return SqlExpression.parse(`JSON_VALUE(${ex}, ${SqlLiteral.create(path)})`);
|
||||
}
|
||||
|
||||
function getJsonPaths(jsons: Record<string, any>[]): string[] {
|
||||
return ['$.'].concat(computeFlattenExprsForData(jsons, 'include-arrays', true));
|
||||
}
|
||||
|
@ -118,15 +115,15 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
if (!parsedQuery || !parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) return false;
|
||||
|
||||
return (
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumn(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumn(header)
|
||||
parsedQuery.getEffectiveWhereExpression().containsColumnName(header) ||
|
||||
parsedQuery.getEffectiveHavingExpression().containsColumnName(header)
|
||||
);
|
||||
}
|
||||
|
||||
function getHeaderMenu(column: Column, headerIndex: number) {
|
||||
const header = column.name;
|
||||
const type = column.sqlType || column.nativeType;
|
||||
const ref = SqlRef.column(header);
|
||||
const ref = C(header);
|
||||
const prettyRef = prettyPrintSql(ref);
|
||||
|
||||
const menuItems: JSX.Element[] = [];
|
||||
|
@ -136,7 +133,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
|
||||
const orderByExpression = parsedQuery.isValidSelectIndex(headerIndex)
|
||||
? SqlLiteral.index(headerIndex)
|
||||
: SqlRef.column(header);
|
||||
: ref;
|
||||
const descOrderBy = orderByExpression.toOrderByExpression('DESC');
|
||||
const ascOrderBy = orderByExpression.toOrderByExpression('ASC');
|
||||
const orderBy = parsedQuery.getOrderByForSelectIndex(headerIndex);
|
||||
|
@ -254,7 +251,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
if (!selectExpression) return;
|
||||
onQueryAction(q =>
|
||||
q.addSelect(
|
||||
jsonValue(selectExpression.getUnderlyingExpression(), path).as(
|
||||
F('JSON_VALUE', selectExpression.getUnderlyingExpression(), path).as(
|
||||
selectExpression.getOutputName() + path.replace(/^\$/, ''),
|
||||
),
|
||||
{ insertIndex: headerIndex + 1 },
|
||||
|
@ -271,7 +268,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
|
||||
if (parsedQuery.isRealOutputColumnAtSelectIndex(headerIndex)) {
|
||||
const whereExpression = parsedQuery.getWhereExpression();
|
||||
if (whereExpression && whereExpression.containsColumn(header)) {
|
||||
if (whereExpression && whereExpression.containsColumnName(header)) {
|
||||
menuItems.push(
|
||||
<MenuItem
|
||||
key="remove_where"
|
||||
|
@ -287,7 +284,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
}
|
||||
|
||||
const havingExpression = parsedQuery.getHavingExpression();
|
||||
if (havingExpression && havingExpression.containsColumn(header)) {
|
||||
if (havingExpression && havingExpression.containsColumnName(header)) {
|
||||
menuItems.push(
|
||||
<MenuItem
|
||||
key="remove_having"
|
||||
|
@ -386,31 +383,19 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
<MenuItem
|
||||
text="Convert to SUM(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.simple('SUM', [underlyingSelectExpression]).as(
|
||||
`sum_${header}`,
|
||||
),
|
||||
);
|
||||
convertToAggregate(F.sum(underlyingSelectExpression).as(`sum_${header}`));
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text="Convert to MIN(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.simple('MIN', [underlyingSelectExpression]).as(
|
||||
`min_${header}`,
|
||||
),
|
||||
);
|
||||
convertToAggregate(F.min(underlyingSelectExpression).as(`min_${header}`));
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text="Convert to MAX(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.simple('MAX', [underlyingSelectExpression]).as(
|
||||
`max_${header}`,
|
||||
),
|
||||
);
|
||||
convertToAggregate(F.max(underlyingSelectExpression).as(`max_${header}`));
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -419,9 +404,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
text="Convert to COUNT(DISTINCT ...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.decorated('COUNT', 'DISTINCT', [underlyingSelectExpression]).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
F.countDistinct(underlyingSelectExpression).as(`unique_${header}`),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
@ -429,9 +412,9 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
text="Convert to APPROX_COUNT_DISTINCT_DS_HLL(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.simple('APPROX_COUNT_DISTINCT_DS_HLL', [
|
||||
underlyingSelectExpression,
|
||||
]).as(`unique_${header}`),
|
||||
F('APPROX_COUNT_DISTINCT_DS_HLL', underlyingSelectExpression).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
@ -439,9 +422,9 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
text="Convert to APPROX_COUNT_DISTINCT_DS_THETA(...)"
|
||||
onClick={() => {
|
||||
convertToAggregate(
|
||||
SqlFunction.simple('APPROX_COUNT_DISTINCT_DS_THETA', [
|
||||
underlyingSelectExpression,
|
||||
]).as(`unique_${header}`),
|
||||
F('APPROX_COUNT_DISTINCT_DS_THETA', underlyingSelectExpression).as(
|
||||
`unique_${header}`,
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
@ -496,7 +479,7 @@ export const ResultTablePane = React.memo(function ResultTablePane(props: Result
|
|||
);
|
||||
|
||||
if (!runeMode) {
|
||||
const orderByExpression = SqlRef.column(header);
|
||||
const orderByExpression = ref;
|
||||
const descOrderBy = orderByExpression.toOrderByExpression('DESC');
|
||||
const ascOrderBy = orderByExpression.toOrderByExpression('ASC');
|
||||
const descOrderByPretty = prettyPrintSql(descOrderBy);
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
import { MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlExpression, SqlFunction, SqlLiteral } from 'druid-query-toolkit';
|
||||
import { F, SqlExpression, SqlFunction } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
import { compact, oneOf, tickIcon } from '../../../utils';
|
||||
import { oneOf, tickIcon } from '../../../utils';
|
||||
|
||||
const OPTIONS: { label: string; value: string }[] = [
|
||||
{ label: 'Second', value: 'PT1S' },
|
||||
|
@ -53,16 +53,16 @@ export const TimeFloorMenuItem = function TimeFloorMenuItem(props: TimeFloorMenu
|
|||
|
||||
let innerExpression = expression.getUnderlyingExpression();
|
||||
let currentDuration: string | undefined;
|
||||
let origin: SqlExpression | undefined;
|
||||
let timezone: SqlExpression | undefined;
|
||||
let origin: string | undefined;
|
||||
let timezone: string | undefined;
|
||||
if (
|
||||
innerExpression instanceof SqlFunction &&
|
||||
oneOf(innerExpression.getEffectiveFunctionName(), 'TIME_FLOOR', 'FLOOR')
|
||||
) {
|
||||
const firstArg = innerExpression.getArg(0);
|
||||
const secondArg = innerExpression.getArgAsString(1)?.toUpperCase();
|
||||
origin = innerExpression.getArg(2);
|
||||
timezone = innerExpression.getArg(3);
|
||||
origin = innerExpression.getArgAsString(2);
|
||||
timezone = innerExpression.getArgAsString(3);
|
||||
if (firstArg && secondArg) {
|
||||
innerExpression = firstArg;
|
||||
currentDuration = UNIT_TO_DURATION[secondArg] || secondArg;
|
||||
|
@ -71,13 +71,9 @@ export const TimeFloorMenuItem = function TimeFloorMenuItem(props: TimeFloorMenu
|
|||
|
||||
const changeTimeFloor = (duration: string | undefined) => {
|
||||
onChange(
|
||||
(duration
|
||||
? SqlFunction.simple(
|
||||
'TIME_FLOOR',
|
||||
compact([innerExpression, SqlLiteral.create(duration), origin, timezone]),
|
||||
)
|
||||
: innerExpression
|
||||
).as(expression.getOutputName()),
|
||||
(duration ? F.timeFloor(innerExpression, duration, origin, timezone) : innerExpression).as(
|
||||
expression.getOutputName(),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue