mirror of https://github.com/apache/druid.git
Web console: update druid-query-toolkit to version 0.4.x (#9500)
* add support for new version of DQT * update druid-query-toolkit * fix direction css * fix remove * update package * remove useless conditional * bump package * jest -u Co-authored-by: Maggie Brewster <maggiebrewster@implydata20sMBP.attlocal.net>
This commit is contained in:
parent
6afd55c8f4
commit
bcb9a632c7
|
@ -4237,9 +4237,9 @@
|
|||
}
|
||||
},
|
||||
"druid-query-toolkit": {
|
||||
"version": "0.3.29",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.3.29.tgz",
|
||||
"integrity": "sha512-WKpsmmqgZd5vgOGCyWZ+2h0aNpTbd82h0svC5GBbhqmXB++vkJchYPGjPmmHkNMV2JI2f40ztxel3hpZv5zSQg==",
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.4.3.tgz",
|
||||
"integrity": "sha512-g2xHaD9lhpTZjM9UEiOQBpgBvO1hm0/cVgqymbUIUf6cgBCm7C1o20fHQzCEK4FBhVmWQSt63pjhRaQ+OM4FGQ==",
|
||||
"requires": {
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
"d3-axis": "^1.0.12",
|
||||
"d3-scale": "^3.2.0",
|
||||
"d3-selection": "^1.4.0",
|
||||
"druid-query-toolkit": "^0.3.29",
|
||||
"druid-query-toolkit": "^0.4.3",
|
||||
"file-saver": "^2.0.2",
|
||||
"has-own-prop": "^2.0.0",
|
||||
"hjson": "^3.2.1",
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
|
||||
import { MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { SqlQuery, StringType } from 'druid-query-toolkit';
|
||||
import { aliasFactory } from 'druid-query-toolkit/build/ast/sql-query/helpers';
|
||||
import { SqlAliasRef, SqlFunction, SqlLiteral, SqlQuery, SqlRef } from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
export interface NumberMenuItemsProps {
|
||||
|
@ -37,13 +36,25 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
<MenuItem
|
||||
text={`"${columnName}" > 100`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(columnName, 100, '>'));
|
||||
onQueryChange(
|
||||
parsedQuery.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'>',
|
||||
SqlLiteral.fromInput(100),
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text={`"${columnName}" <= 100`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(columnName, 100, '<='));
|
||||
onQueryChange(
|
||||
parsedQuery.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'<=',
|
||||
SqlLiteral.fromInput(100),
|
||||
),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</MenuItem>
|
||||
|
@ -52,7 +63,7 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasFilterForColumn(columnName)) return;
|
||||
if (!parsedQuery.getCurrentFilters().includes(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -67,13 +78,13 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
|
||||
function renderRemoveGroupBy(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupByForColumn(columnName)) return;
|
||||
if (!parsedQuery.hasGroupByColumn(columnName)) return;
|
||||
return (
|
||||
<MenuItem
|
||||
icon={IconNames.UNGROUP_OBJECTS}
|
||||
text={'Remove group by'}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.removeGroupBy(columnName), true);
|
||||
onQueryChange(parsedQuery.removeFromGroupBy(columnName), true);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -81,32 +92,31 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
|
||||
function renderGroupByMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.groupByClause) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text={`Group by`}>
|
||||
<MenuItem
|
||||
text={`"${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.addToGroupBy(columnName), true);
|
||||
onQueryChange(
|
||||
parsedQuery.addToGroupBy(SqlRef.fromNameWithDoubleQuotes(columnName)),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text={`TRUNC("${columnName}", -1) AS "${columnName}_trunc"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addFunctionToGroupBy(
|
||||
'TRUNC',
|
||||
[' '],
|
||||
[
|
||||
new StringType({
|
||||
spacing: [],
|
||||
chars: columnName,
|
||||
quote: '"',
|
||||
}),
|
||||
-1,
|
||||
],
|
||||
aliasFactory(`${columnName}_truncated`),
|
||||
parsedQuery.addToGroupBy(
|
||||
SqlAliasRef.sqlAliasFactory(
|
||||
SqlFunction.sqlFunctionFactory('TRUNC', [
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
SqlLiteral.fromInput(-1),
|
||||
]),
|
||||
`${columnName}_truncated`,
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
@ -118,7 +128,7 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
|
||||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.groupByClause) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text={`Aggregate`}>
|
||||
|
@ -126,7 +136,11 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
text={`SUM(${columnName}) AS "sum_${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(columnName, 'SUM', aliasFactory(`sum_${columnName}`)),
|
||||
parsedQuery.addAggregateColumn(
|
||||
[SqlRef.fromName(columnName)],
|
||||
'SUM',
|
||||
`sum_${columnName}`,
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -135,7 +149,11 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
text={`MAX(${columnName}) AS "max_${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(columnName, 'MAX', aliasFactory(`max_${columnName}`)),
|
||||
parsedQuery.addAggregateColumn(
|
||||
[SqlRef.fromName(columnName)],
|
||||
'MAX',
|
||||
`max_${columnName}`,
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -144,7 +162,11 @@ export const NumberMenuItems = React.memo(function NumberMenuItems(props: Number
|
|||
text={`MIN(${columnName}) AS "min_${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(columnName, 'MIN', aliasFactory(`min_${columnName}`)),
|
||||
parsedQuery.addAggregateColumn(
|
||||
[SqlRef.fromName(columnName)],
|
||||
'MIN',
|
||||
`min_${columnName}`,
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
import { MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import {
|
||||
ComparisonExpression,
|
||||
ComparisonExpressionRhs,
|
||||
FilterClause,
|
||||
refExpressionFactory,
|
||||
SqlAliasRef,
|
||||
SqlFunction,
|
||||
SqlLiteral,
|
||||
SqlMulti,
|
||||
SqlQuery,
|
||||
WhereClause,
|
||||
SqlRef,
|
||||
} from 'druid-query-toolkit';
|
||||
import { aliasFactory, stringFactory } from 'druid-query-toolkit/build/ast/sql-query/helpers';
|
||||
import React from 'react';
|
||||
|
||||
export interface StringMenuItemsProps {
|
||||
|
@ -44,13 +43,13 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
<MenuItem
|
||||
text={`"${columnName}" = 'xxx'`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(columnName, 'xxx', '='), false);
|
||||
onQueryChange(parsedQuery.addWhereFilter(columnName, '=', 'xxx'), false);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text={`"${columnName}" LIKE '%xxx%'`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(columnName, '%xxx%', 'LIKE'), false);
|
||||
onQueryChange(parsedQuery.addWhereFilter(columnName, 'LIKE', '%xxx%'), false);
|
||||
}}
|
||||
/>
|
||||
</MenuItem>
|
||||
|
@ -59,7 +58,7 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasFilterForColumn(columnName)) return;
|
||||
if (!parsedQuery.getCurrentFilters().includes(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -74,13 +73,13 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
|
||||
function renderRemoveGroupBy(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupByForColumn(columnName)) return;
|
||||
if (!parsedQuery.hasGroupByColumn(columnName)) return;
|
||||
return (
|
||||
<MenuItem
|
||||
icon={IconNames.UNGROUP_OBJECTS}
|
||||
text={'Remove group by'}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.removeGroupBy(columnName), true);
|
||||
onQueryChange(parsedQuery.removeFromGroupBy(columnName), true);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -88,26 +87,32 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
|
||||
function renderGroupByMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text={`Group by`}>
|
||||
<MenuItem
|
||||
text={`"${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.addToGroupBy(columnName), true);
|
||||
onQueryChange(
|
||||
parsedQuery.addToGroupBy(SqlRef.fromNameWithDoubleQuotes(columnName)),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
text={`SUBSTRING("${columnName}", 1, 2) AS "${columnName}_substring"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addFunctionToGroupBy(
|
||||
'SUBSTRING',
|
||||
[' ', ' '],
|
||||
[stringFactory(columnName, `"`), 1, 2],
|
||||
|
||||
aliasFactory(`${columnName}_substring`),
|
||||
parsedQuery.addToGroupBy(
|
||||
SqlAliasRef.sqlAliasFactory(
|
||||
SqlFunction.sqlFunctionFactory('SUBSTRING', [
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
SqlLiteral.fromInput(1),
|
||||
SqlLiteral.fromInput(2),
|
||||
]),
|
||||
`${columnName}_substring`,
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
@ -119,7 +124,7 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
|
||||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text={`Aggregate`}>
|
||||
|
@ -128,9 +133,11 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
onClick={() =>
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(
|
||||
columnName,
|
||||
[SqlRef.fromNameWithDoubleQuotes(columnName)],
|
||||
'COUNT',
|
||||
aliasFactory(`dist_${columnName}`),
|
||||
`dist_${columnName}`,
|
||||
undefined,
|
||||
'DISTINCT',
|
||||
),
|
||||
true,
|
||||
)
|
||||
|
@ -141,28 +148,13 @@ export const StringMenuItems = React.memo(function StringMenuItems(props: String
|
|||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(
|
||||
refExpressionFactory('*'),
|
||||
[SqlRef.fromName('*')],
|
||||
'COUNT',
|
||||
aliasFactory(`${columnName}_filtered_count`),
|
||||
false,
|
||||
new FilterClause({
|
||||
keyword: 'FILTER',
|
||||
spacing: [' '],
|
||||
ex: new WhereClause({
|
||||
keyword: 'WHERE',
|
||||
spacing: [' '],
|
||||
filter: new ComparisonExpression({
|
||||
parens: [],
|
||||
ex: stringFactory(columnName, '"'),
|
||||
rhs: new ComparisonExpressionRhs({
|
||||
parens: [],
|
||||
op: '=',
|
||||
rhs: stringFactory('xxx', `'`),
|
||||
spacing: [' ', ' '],
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
`${columnName}_filtered_count`,
|
||||
SqlMulti.sqlMultiFactory('=', [
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
SqlLiteral.fromInput('xxx'),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -18,17 +18,20 @@
|
|||
|
||||
import { MenuDivider, MenuItem } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { AdditiveExpression, SqlQuery, Timestamp, timestampFactory } from 'druid-query-toolkit';
|
||||
import {
|
||||
aliasFactory,
|
||||
intervalFactory,
|
||||
refExpressionFactory,
|
||||
stringFactory,
|
||||
} from 'druid-query-toolkit/build/ast/sql-query/helpers';
|
||||
SqlAliasRef,
|
||||
SqlFunction,
|
||||
SqlInterval,
|
||||
SqlLiteral,
|
||||
SqlMulti,
|
||||
SqlQuery,
|
||||
SqlRef,
|
||||
SqlTimestamp,
|
||||
} from 'druid-query-toolkit';
|
||||
import React from 'react';
|
||||
|
||||
function dateToTimestamp(date: Date): Timestamp {
|
||||
return timestampFactory(
|
||||
function dateToTimestamp(date: Date): SqlTimestamp {
|
||||
return SqlTimestamp.sqlTimestampFactory(
|
||||
date
|
||||
.toISOString()
|
||||
.split('.')[0]
|
||||
|
@ -103,14 +106,17 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
<MenuItem
|
||||
text={`Latest hour`}
|
||||
onClick={() => {
|
||||
const additiveExpression = new AdditiveExpression({
|
||||
parens: [],
|
||||
op: ['-'],
|
||||
ex: [refExpressionFactory('CURRENT_TIMESTAMP'), intervalFactory('HOUR', '1')],
|
||||
spacing: [' ', ' '],
|
||||
});
|
||||
onQueryChange(
|
||||
parsedQuery.removeFilter(columnName).filterRow(columnName, additiveExpression, '>='),
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.addWhereFilter(
|
||||
columnName,
|
||||
'>=',
|
||||
SqlMulti.sqlMultiFactory('-', [
|
||||
SqlRef.fromName('CURRENT_TIMESTAMP'),
|
||||
SqlInterval.sqlIntervalFactory('HOUR', 1),
|
||||
]),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -118,14 +124,17 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
<MenuItem
|
||||
text={`Latest day`}
|
||||
onClick={() => {
|
||||
const additiveExpression = new AdditiveExpression({
|
||||
parens: [],
|
||||
op: ['-'],
|
||||
ex: [refExpressionFactory('CURRENT_TIMESTAMP'), intervalFactory('DAY', '1')],
|
||||
spacing: [' ', ' '],
|
||||
});
|
||||
onQueryChange(
|
||||
parsedQuery.removeFilter(columnName).filterRow(columnName, additiveExpression, '>='),
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.addWhereFilter(
|
||||
columnName,
|
||||
'>=',
|
||||
SqlMulti.sqlMultiFactory('-', [
|
||||
SqlRef.fromName('CURRENT_TIMESTAMP'),
|
||||
SqlInterval.sqlIntervalFactory('Day', 1),
|
||||
]),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -133,14 +142,17 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
<MenuItem
|
||||
text={`Latest week`}
|
||||
onClick={() => {
|
||||
const additiveExpression = new AdditiveExpression({
|
||||
parens: [],
|
||||
op: ['-'],
|
||||
ex: [refExpressionFactory('CURRENT_TIMESTAMP'), intervalFactory('DAY', '7')],
|
||||
spacing: [' ', ' '],
|
||||
});
|
||||
onQueryChange(
|
||||
parsedQuery.removeFilter(columnName).filterRow(columnName, additiveExpression, '>='),
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.addWhereFilter(
|
||||
columnName,
|
||||
'>=',
|
||||
SqlMulti.sqlMultiFactory('-', [
|
||||
SqlRef.fromName('CURRENT_TIMESTAMP'),
|
||||
SqlInterval.sqlIntervalFactory('Day', 7),
|
||||
]),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -148,14 +160,17 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
<MenuItem
|
||||
text={`Latest month`}
|
||||
onClick={() => {
|
||||
const additiveExpression = new AdditiveExpression({
|
||||
parens: [],
|
||||
op: ['-'],
|
||||
ex: [refExpressionFactory('CURRENT_TIMESTAMP'), intervalFactory('MONTH', '1')],
|
||||
spacing: [' ', ' '],
|
||||
});
|
||||
onQueryChange(
|
||||
parsedQuery.removeFilter(columnName).filterRow(columnName, additiveExpression, '>='),
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.addWhereFilter(
|
||||
columnName,
|
||||
'>=',
|
||||
SqlMulti.sqlMultiFactory('-', [
|
||||
SqlRef.fromName('CURRENT_TIMESTAMP'),
|
||||
SqlInterval.sqlIntervalFactory('MONTH', 1),
|
||||
]),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -163,14 +178,17 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
<MenuItem
|
||||
text={`Latest year`}
|
||||
onClick={() => {
|
||||
const additiveExpression = new AdditiveExpression({
|
||||
parens: [],
|
||||
op: ['-'],
|
||||
ex: [refExpressionFactory('CURRENT_TIMESTAMP'), intervalFactory('YEAR', '1')],
|
||||
spacing: [' ', ' '],
|
||||
});
|
||||
onQueryChange(
|
||||
parsedQuery.removeFilter(columnName).filterRow(columnName, additiveExpression, '>='),
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.addWhereFilter(
|
||||
columnName,
|
||||
'>=',
|
||||
SqlMulti.sqlMultiFactory('-', [
|
||||
SqlRef.fromName('CURRENT_TIMESTAMP'),
|
||||
SqlInterval.sqlIntervalFactory('YEAR', 1),
|
||||
]),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -183,8 +201,16 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
onQueryChange(
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.filterRow(dateToTimestamp(hourStart), stringFactory(columnName, `"`), '<=')
|
||||
.filterRow(columnName, dateToTimestamp(nextHour(hourStart)), '<'),
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'>=',
|
||||
dateToTimestamp(hourStart),
|
||||
)
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'<',
|
||||
dateToTimestamp(nextHour(hourStart)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -196,8 +222,16 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
onQueryChange(
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.filterRow(dateToTimestamp(dayStart), stringFactory(columnName, `"`), '<=')
|
||||
.filterRow(columnName, dateToTimestamp(nextDay(dayStart)), '<'),
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'>=',
|
||||
dateToTimestamp(dayStart),
|
||||
)
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'<',
|
||||
dateToTimestamp(nextDay(dayStart)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -209,8 +243,16 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
onQueryChange(
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.filterRow(dateToTimestamp(monthStart), stringFactory(columnName, `"`), '<=')
|
||||
.filterRow(columnName, dateToTimestamp(nextMonth(monthStart)), '<'),
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'>=',
|
||||
dateToTimestamp(monthStart),
|
||||
)
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'<',
|
||||
dateToTimestamp(nextMonth(monthStart)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -222,8 +264,16 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
onQueryChange(
|
||||
parsedQuery
|
||||
.removeFilter(columnName)
|
||||
.filterRow(dateToTimestamp(yearStart), stringFactory(columnName, `"`), '<=')
|
||||
.filterRow(columnName, dateToTimestamp(nextYear(yearStart)), '<'),
|
||||
.addWhereFilter(
|
||||
SqlRef.fromNameWithDoubleQuotes(columnName),
|
||||
'<=',
|
||||
dateToTimestamp(yearStart),
|
||||
)
|
||||
.addWhereFilter(
|
||||
dateToTimestamp(yearStart),
|
||||
'<',
|
||||
dateToTimestamp(nextYear(yearStart)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -234,7 +284,7 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
|
||||
function renderRemoveFilter(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasFilterForColumn(columnName)) return;
|
||||
if (!parsedQuery.getCurrentFilters().includes(columnName)) return;
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
|
@ -249,13 +299,13 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
|
||||
function renderRemoveGroupBy(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupByForColumn(columnName)) return;
|
||||
if (!parsedQuery.hasGroupByColumn(columnName)) return;
|
||||
return (
|
||||
<MenuItem
|
||||
icon={IconNames.UNGROUP_OBJECTS}
|
||||
text={'Remove group by'}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.removeGroupBy(columnName), true);
|
||||
onQueryChange(parsedQuery.removeFromGroupBy(columnName), true);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -263,7 +313,7 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
|
||||
function renderGroupByMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.GROUP_OBJECTS} text={`Group by`}>
|
||||
|
@ -271,11 +321,14 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
text={`TIME_FLOOR("${columnName}", 'PT1H') AS "${columnName}_time_floor"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addFunctionToGroupBy(
|
||||
'TIME_FLOOR',
|
||||
[' '],
|
||||
[stringFactory(columnName, `"`), stringFactory('PT1H', `'`)],
|
||||
aliasFactory(`${columnName}_time_floor`),
|
||||
parsedQuery.addToGroupBy(
|
||||
SqlAliasRef.sqlAliasFactory(
|
||||
SqlFunction.sqlFunctionFactory('TIME_FLOOR', [
|
||||
SqlRef.fromName(columnName),
|
||||
SqlLiteral.fromInput('PT1h'),
|
||||
]),
|
||||
`${columnName}_time_floor`,
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
@ -285,11 +338,14 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
text={`TIME_FLOOR("${columnName}", 'P1D') AS "${columnName}_time_floor"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addFunctionToGroupBy(
|
||||
'TIME_FLOOR',
|
||||
[' '],
|
||||
[stringFactory(columnName, `"`), stringFactory('P1D', `'`)],
|
||||
aliasFactory(`${columnName}_time_floor`),
|
||||
parsedQuery.addToGroupBy(
|
||||
SqlAliasRef.sqlAliasFactory(
|
||||
SqlFunction.sqlFunctionFactory('TIME_FLOOR', [
|
||||
SqlRef.fromName(columnName),
|
||||
SqlLiteral.fromInput('P1D'),
|
||||
]),
|
||||
`${columnName}_time_floor`,
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
@ -299,11 +355,14 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
text={`TIME_FLOOR("${columnName}", 'P7D') AS "${columnName}_time_floor"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addFunctionToGroupBy(
|
||||
'TIME_FLOOR',
|
||||
[' '],
|
||||
[stringFactory(columnName, `"`), stringFactory('P7D', `'`)],
|
||||
aliasFactory(`${columnName}_time_floor`),
|
||||
parsedQuery.addToGroupBy(
|
||||
SqlAliasRef.sqlAliasFactory(
|
||||
SqlFunction.sqlFunctionFactory('TIME_FLOOR', [
|
||||
SqlRef.fromName(columnName),
|
||||
SqlLiteral.fromInput('P7D'),
|
||||
]),
|
||||
`${columnName}_time_floor`,
|
||||
),
|
||||
),
|
||||
true,
|
||||
);
|
||||
|
@ -315,7 +374,7 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
|
||||
function renderAggregateMenu(): JSX.Element | undefined {
|
||||
const { columnName, parsedQuery, onQueryChange } = props;
|
||||
if (!parsedQuery.hasGroupBy()) return;
|
||||
if (!parsedQuery.groupByExpression) return;
|
||||
|
||||
return (
|
||||
<MenuItem icon={IconNames.FUNCTION} text={`Aggregate`}>
|
||||
|
@ -323,7 +382,11 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
text={`MAX("${columnName}") AS "max_${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(columnName, 'MAX', aliasFactory(`max_${columnName}`)),
|
||||
parsedQuery.addAggregateColumn(
|
||||
[SqlRef.fromNameWithDoubleQuotes(columnName)],
|
||||
'MAX',
|
||||
`max_${columnName}`,
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
@ -332,7 +395,11 @@ export const TimeMenuItems = React.memo(function TimeMenuItems(props: TimeMenuIt
|
|||
text={`MIN("${columnName}") AS "min_${columnName}"`}
|
||||
onClick={() => {
|
||||
onQueryChange(
|
||||
parsedQuery.addAggregateColumn(columnName, 'MIN', aliasFactory(`min_${columnName}`)),
|
||||
parsedQuery.addAggregateColumn(
|
||||
[SqlRef.fromNameWithDoubleQuotes(columnName)],
|
||||
'MIN',
|
||||
`min_${columnName}`,
|
||||
),
|
||||
true,
|
||||
);
|
||||
}}
|
||||
|
|
|
@ -27,7 +27,7 @@ import {
|
|||
Tree,
|
||||
} from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { refExpressionFactory, SqlQuery, stringFactory } from 'druid-query-toolkit';
|
||||
import { SqlQuery } from 'druid-query-toolkit';
|
||||
import React, { ChangeEvent } from 'react';
|
||||
|
||||
import { Loader } from '../../../components';
|
||||
|
@ -184,12 +184,7 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
|
|||
icon={IconNames.EXCHANGE}
|
||||
text={`Replace FROM with: ${table}`}
|
||||
onClick={() => {
|
||||
props.onQueryStringChange(
|
||||
parsedQuery.replaceFrom(
|
||||
refExpressionFactory(stringFactory(table, `"`)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
props.onQueryStringChange(parsedQuery.replaceFrom(table), true);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -74,7 +74,7 @@ exports[`query output matches snapshot 1`] = `
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
class="rt-th aggregate-header rt-resizable-header"
|
||||
class="rt-th aggregate-header rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
tabindex="-1"
|
||||
|
@ -101,7 +101,7 @@ exports[`query output matches snapshot 1`] = `
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
class="rt-th aggregate-header rt-resizable-header"
|
||||
class="rt-th aggregate-header rt-resizable-header"
|
||||
role="columnheader"
|
||||
style="flex: 100 0 auto; width: 100px;"
|
||||
tabindex="-1"
|
||||
|
|
|
@ -19,10 +19,7 @@
|
|||
import { Menu, MenuItem, Popover } from '@blueprintjs/core';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { HeaderRows, SqlQuery } from 'druid-query-toolkit';
|
||||
import {
|
||||
basicIdentifierEscape,
|
||||
basicLiteralEscape,
|
||||
} from 'druid-query-toolkit/build/ast/sql-query/helpers';
|
||||
import { basicIdentifierEscape, basicLiteralEscape } from 'druid-query-toolkit/build/sql/helpers';
|
||||
import React, { useState } from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
|
||||
|
@ -94,7 +91,7 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
icon: IconNames.CROSS,
|
||||
title: `Remove: ${trimValue(header)}`,
|
||||
onAction: () => {
|
||||
onQueryChange(parsedQuery.excludeColumn(header), true);
|
||||
onQueryChange(parsedQuery.remove(header), true);
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -161,14 +158,14 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
icon={IconNames.FILTER_KEEP}
|
||||
text={`Filter by: ${trimValue(header)} = ${trimValue(value)}`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(header, value, '='), true);
|
||||
onQueryChange(parsedQuery.addWhereFilter(header, '=', value), true);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
icon={IconNames.FILTER_REMOVE}
|
||||
text={`Filter by: ${trimValue(header)} != ${trimValue(value)}`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(header, value, '!='), true);
|
||||
onQueryChange(parsedQuery.addWhereFilter(header, '!=', value), true);
|
||||
}}
|
||||
/>
|
||||
{!isNaN(Number(value)) && (
|
||||
|
@ -177,14 +174,14 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
icon={IconNames.FILTER_KEEP}
|
||||
text={`Filter by: ${trimValue(header)} >= ${trimValue(value)}`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(header, value, '>='), true);
|
||||
onQueryChange(parsedQuery.addWhereFilter(header, '>=', value), true);
|
||||
}}
|
||||
/>
|
||||
<MenuItem
|
||||
icon={IconNames.FILTER_KEEP}
|
||||
text={`Filter by: ${trimValue(header)} <= ${trimValue(value)}`}
|
||||
onClick={() => {
|
||||
onQueryChange(parsedQuery.filterRow(header, value, '<='), true);
|
||||
onQueryChange(parsedQuery.addWhereFilter(header, '<=', value), true);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
@ -236,27 +233,23 @@ export const QueryOutput = React.memo(function QueryOutput(props: QueryOutputPro
|
|||
|
||||
function getHeaderClassName(header: string) {
|
||||
const { parsedQuery } = props;
|
||||
if (!parsedQuery) return;
|
||||
|
||||
const className = [];
|
||||
if (parsedQuery) {
|
||||
const sorted = parsedQuery.getSorted();
|
||||
if (sorted) {
|
||||
className.push(
|
||||
sorted.map(sorted => {
|
||||
if (sorted.id === header) {
|
||||
return sorted.desc ? '-sort-desc' : '-sort-asc';
|
||||
}
|
||||
return '';
|
||||
})[0],
|
||||
);
|
||||
}
|
||||
const sorted = parsedQuery.getSorted();
|
||||
const aggregateColumns = parsedQuery.getAggregateColumns();
|
||||
|
||||
const aggregateColumns = parsedQuery.getAggregateColumns();
|
||||
if (aggregateColumns && aggregateColumns.includes(header)) {
|
||||
className.push('aggregate-header');
|
||||
if (sorted) {
|
||||
const sortedColumnNames = sorted.map(column => column.id);
|
||||
if (sortedColumnNames.includes(header)) {
|
||||
className.push(sorted[sortedColumnNames.indexOf(header)].desc ? '-sort-desc' : '-sort-asc');
|
||||
}
|
||||
}
|
||||
|
||||
if (aggregateColumns && aggregateColumns.includes(header)) {
|
||||
className.push('aggregate-header');
|
||||
}
|
||||
|
||||
return className.join(' ');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue