This is an automated email from the ASF dual-hosted git repository.
vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new bf3139562c6 Web console: support for the export execution state
(#15969)
bf3139562c6 is described below
commit bf3139562c6cdc38361afac4bb2cd72bf1fbc8f1
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Mon Feb 26 11:28:25 2024 -0800
Web console: support for the export execution state (#15969)
* init
* add CSV keyword
---
web-console/lib/keywords.js | 1 +
.../src/druid-models/execution/execution.ts | 2 +-
.../workbench-query/workbench-query.spec.ts | 94 ----------------------
.../workbench-query/workbench-query.ts | 33 ++------
.../views/workbench-view/query-tab/query-tab.scss | 20 +++++
.../views/workbench-view/query-tab/query-tab.tsx | 28 ++++---
6 files changed, 47 insertions(+), 131 deletions(-)
diff --git a/web-console/lib/keywords.js b/web-console/lib/keywords.js
index 62dec991f86..bf7b9a03910 100644
--- a/web-console/lib/keywords.js
+++ b/web-console/lib/keywords.js
@@ -108,6 +108,7 @@ exports.SQL_EXPRESSION_PARTS = [
'YEAR',
'TIMESTAMP',
'INTERVAL',
+ 'CSV',
];
exports.SQL_CONSTANTS = ['NULL', 'FALSE', 'TRUE'];
diff --git a/web-console/src/druid-models/execution/execution.ts
b/web-console/src/druid-models/execution/execution.ts
index 3059a401c4f..0cf8d5d0ed3 100644
--- a/web-console/src/druid-models/execution/execution.ts
+++ b/web-console/src/druid-models/execution/execution.ts
@@ -567,7 +567,7 @@ export class Execution {
return this.destination?.numTotalRows;
}
- public isSuccessfulInsert(): boolean {
+ public isSuccessfulIngest(): boolean {
return Boolean(this.status === 'SUCCESS' && this.getIngestDatasource());
}
diff --git
a/web-console/src/druid-models/workbench-query/workbench-query.spec.ts
b/web-console/src/druid-models/workbench-query/workbench-query.spec.ts
index ec057b3efc7..02bb3e399b0 100644
--- a/web-console/src/druid-models/workbench-query/workbench-query.spec.ts
+++ b/web-console/src/druid-models/workbench-query/workbench-query.spec.ts
@@ -455,100 +455,6 @@ describe('WorkbenchQuery', () => {
});
});
- describe('#getIngestDatasource', () => {
- it('works with INSERT', () => {
- const sql = sane`
- -- Some comment
- INSERT INTO trips2
- SELECT
- TIME_PARSE(pickup_datetime) AS __time,
- *
- FROM TABLE(
- EXTERN(
- '{"type": "local", ...}',
- '{"type":"csv", ...}'
- )
- ) EXTEND (cab_type, VARCHAR)
- CLUSTERED BY trip_id
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
-
- it('works with INSERT (unparsable)', () => {
- const sql = sane`
- -- Some comment
- INSERT into trips2
- SELECT
- TIME_PARSE(pickup_datetime) AS __time,
- *
- FROM TABLE(
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
-
- it('works with INSERT (unparsable with paren)', () => {
- const sql = sane`
- -- Some comment
- INSERT into trips2
- (SELECT TIME_PARSE(pickup_datetime) AS __time,
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
-
- it('works with REPLACE', () => {
- const sql = sane`
- REPLACE INTO trips2 OVERWRITE ALL
- SELECT
- TIME_PARSE(pickup_datetime) AS __time,
- *
- FROM TABLE(
- EXTERN(
- '{"type": "local", ...}',
- '{"type":"csv", ...}'
- )
- ) EXTEND (cab_type, VARCHAR)
- CLUSTERED BY trip_id
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
-
- it('works with REPLACE (unparsable)', () => {
- const sql = sane`
- REPLACE INTO trips2 OVERWRITE ALL
- WITH kttm_data AS (SELECT *
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
-
- it('works with REPLACE (unparsable with comment at start)', () => {
- const sql = sane`
- -- Hello world SELECT
-
- REPLACE INTO trips2 OVERWRITE ALL
- WITH kttm_data AS (SELECT *
- `;
-
- const workbenchQuery = WorkbenchQuery.blank().changeQueryString(sql);
- expect(workbenchQuery.getIngestDatasource()).toEqual('trips2');
-
expect(workbenchQuery.changeEngine('sql-native').getIngestDatasource()).toBeUndefined();
- });
- });
-
describe('#getIssue', () => {
it('works', () => {
expect(
diff --git a/web-console/src/druid-models/workbench-query/workbench-query.ts
b/web-console/src/druid-models/workbench-query/workbench-query.ts
index f027efdc0a5..27cf6a0109d 100644
--- a/web-console/src/druid-models/workbench-query/workbench-query.ts
+++ b/web-console/src/druid-models/workbench-query/workbench-query.ts
@@ -158,7 +158,7 @@ export class WorkbenchQuery {
.changeQueryString(queryString)
.changeQueryContext(cleanContext);
- if (noSqlOuterLimit && !retQuery.getIngestDatasource()) {
+ if (noSqlOuterLimit && !retQuery.isIngestQuery()) {
retQuery = retQuery.changeUnlimited(true);
}
@@ -221,23 +221,6 @@ export class WorkbenchQuery {
return /EXTERN\s*\(|(?:INSERT|REPLACE)\s+INTO/im.test(queryString);
}
- static getIngestDatasourceFromQueryFragment(queryFragment: string): string |
undefined {
- // Assuming the queryFragment is no parsable find the prefix that look
like:
- // REPLACE<space>INTO<space><whatever><space>SELECT<space or EOF>
- const matchInsertReplaceIndex =
queryFragment.match(/(?:INSERT|REPLACE)\s+INTO/i)?.index;
- if (typeof matchInsertReplaceIndex !== 'number') return;
-
- const queryStartingWithInsertOrReplace =
queryFragment.substring(matchInsertReplaceIndex);
-
- const matchEnd =
queryStartingWithInsertOrReplace.match(/\(|\b(?:SELECT|WITH)\b|$/i);
- const fragmentQuery = SqlQuery.maybeParse(
- queryStartingWithInsertOrReplace.substring(0, matchEnd?.index) + '
SELECT * FROM t',
- );
- if (!fragmentQuery) return;
-
- return fragmentQuery.getIngestTable()?.getName();
- }
-
public readonly queryString: string;
public readonly queryContext: QueryContext;
public readonly queryParameters?: QueryParameter[];
@@ -409,21 +392,17 @@ export class WorkbenchQuery {
}
}
- public getIngestDatasource(): string | undefined {
- if (this.getEffectiveEngine() !== 'sql-msq-task') return;
+ public isIngestQuery(): boolean {
+ if (this.getEffectiveEngine() !== 'sql-msq-task') return false;
const { queryString, parsedQuery } = this;
if (parsedQuery) {
- return parsedQuery.getIngestTable()?.getName();
+ return Boolean(parsedQuery.getIngestTable());
}
- if (this.isJsonLike()) return;
-
- return WorkbenchQuery.getIngestDatasourceFromQueryFragment(queryString);
- }
+ if (this.isJsonLike()) return false;
- public isIngestQuery(): boolean {
- return Boolean(this.getIngestDatasource());
+ return /(?:INSERT|REPLACE)\s+INTO/i.test(queryString);
}
public toggleUnlimited(): WorkbenchQuery {
diff --git a/web-console/src/views/workbench-view/query-tab/query-tab.scss
b/web-console/src/views/workbench-view/query-tab/query-tab.scss
index eee0375e0ea..4c143194a87 100644
--- a/web-console/src/views/workbench-view/query-tab/query-tab.scss
+++ b/web-console/src/views/workbench-view/query-tab/query-tab.scss
@@ -124,5 +124,25 @@ $vertical-gap: 6px;
right: 0;
}
}
+
+ .generic-status-container {
+ position: relative;
+
+ .generic-status-container-info {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+ right: 5px;
+ height: 30px;
+ }
+
+ .execution-stages-pane {
+ position: absolute;
+ top: 40px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ }
+ }
}
}
diff --git a/web-console/src/views/workbench-view/query-tab/query-tab.tsx
b/web-console/src/views/workbench-view/query-tab/query-tab.tsx
index 8c7db042736..bd3a7dc769c 100644
--- a/web-console/src/views/workbench-view/query-tab/query-tab.tsx
+++ b/web-console/src/views/workbench-view/query-tab/query-tab.tsx
@@ -286,11 +286,11 @@ export const QueryTab = React.memo(function
QueryTab(props: QueryTabProps) {
useCallback(state => state.increment, []),
);
useEffect(() => {
- if (execution?.isSuccessfulInsert()) {
+ if (execution?.isSuccessfulIngest()) {
incrementMetadataVersion();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [Boolean(execution?.isSuccessfulInsert())]);
+ }, [Boolean(execution?.isSuccessfulIngest())]);
function moveToPosition(position: RowColumn) {
const currentQueryInput = queryInputRef.current;
@@ -434,12 +434,6 @@ export const QueryTab = React.memo(function
QueryTab(props: QueryTabProps) {
queryResult={execution.result}
onQueryAction={handleQueryAction}
/>
- ) : execution.isSuccessfulInsert() ? (
- <IngestSuccessPane
- execution={execution}
- onDetails={onDetails}
- onQueryTab={onQueryTab}
- />
) : execution.error ? (
<div className="error-container">
<ExecutionErrorPane execution={execution} />
@@ -452,8 +446,24 @@ export const QueryTab = React.memo(function
QueryTab(props: QueryTabProps) {
/>
)}
</div>
+ ) : execution.isSuccessfulIngest() ? (
+ <IngestSuccessPane
+ execution={execution}
+ onDetails={onDetails}
+ onQueryTab={onQueryTab}
+ />
) : (
- <div>Unknown query execution state</div>
+ <div className="generic-status-container">
+ <div className="generic-status-container-info">
+ {`Execution completed with status: ${execution.status}`}
+ </div>
+ <ExecutionStagesPane
+ execution={execution}
+ onErrorClick={() => onDetails(statsTaskId!, 'error')}
+ onWarningClick={() => onDetails(statsTaskId!, 'warnings')}
+ goToTask={goToTask}
+ />
+ </div>
))}
{executionState.error && (
<QueryErrorPane
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]