Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature-1002]Catalog adds right-click delete function #4178

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,30 @@ public Result<Schema> getMSSchemaInfo(@RequestBody StudioMetaStoreDTO studioMeta
public Result<List<Column>> getMSColumns(@RequestBody StudioMetaStoreDTO studioMetaStoreDTO) {
return Result.succeed(studioService.getMSColumns(studioMetaStoreDTO));
}

/** Drop Meta Store Flink Table */
@PostMapping("/dropMSTable")
@ApiOperation("Drop Flink Table")
@ApiImplicitParams({
@ApiImplicitParam(name = "envId", value = "envId", required = true, dataType = "Integer", paramType = "query"),
@ApiImplicitParam(
name = "catalog",
value = "catalog",
required = true,
dataType = "String",
paramType = "query"),
@ApiImplicitParam(
name = "database",
value = "database",
required = true,
dataType = "String",
paramType = "query"),
@ApiImplicitParam(name = "table", value = "table", required = true, dataType = "String", paramType = "query")
})
public Result<List<Column>> dropMSTable(@RequestBody StudioMetaStoreDTO studioMetaStoreDTO) {
if (studioService.dropMSTable(studioMetaStoreDTO)) {
return Result.succeed();
}
return Result.failed();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ public interface StudioService {
Schema getMSSchemaInfo(StudioMetaStoreDTO studioMetaStoreDTO);

List<Column> getMSColumns(StudioMetaStoreDTO studioMetaStoreDTO);

boolean dropMSTable(StudioMetaStoreDTO studioMetaStoreDTO);
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import org.dinky.data.dto.StudioLineageDTO;
import org.dinky.data.dto.StudioMetaStoreDTO;
import org.dinky.data.dto.TaskDTO;
import org.dinky.data.enums.Status;
import org.dinky.data.exception.BusException;
import org.dinky.data.model.Catalog;
import org.dinky.data.model.ClusterInstance;
import org.dinky.data.model.Column;
Expand Down Expand Up @@ -209,6 +211,22 @@ public List<Column> getMSColumns(StudioMetaStoreDTO studioMetaStoreDTO) {
return columns;
}

@Override
public boolean dropMSTable(StudioMetaStoreDTO studioMetaStoreDTO) {
String catalogName = studioMetaStoreDTO.getCatalog();
String database = studioMetaStoreDTO.getDatabase();
String tableName = studioMetaStoreDTO.getTable();
if (Dialect.isCommonSql(studioMetaStoreDTO.getDialect())) {
throw new BusException(Status.SYS_CATALOG_ONLY_SUPPORT_FLINK_SQL_OPERATION);
} else {
String envSql = taskService.buildEnvSql(studioMetaStoreDTO);
JobManager jobManager = getJobManager(studioMetaStoreDTO, envSql);
CustomTableEnvironment customTableEnvironment =
jobManager.getExecutor().getCustomTableEnvironment();
return FlinkTableMetadataUtil.dropTable(customTableEnvironment, catalogName, database, tableName);
}
}

private JobManager getJobManager(StudioMetaStoreDTO studioMetaStoreDTO, String envSql) {
JobManager jobManager = jobManagerCache.get(envSql, () -> {
JobConfig config = studioMetaStoreDTO.getJobConfig();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.flink.table.catalog.CatalogBaseTable;
import org.apache.flink.table.catalog.ObjectIdentifier;
import org.apache.flink.table.catalog.ObjectPath;
import org.apache.flink.table.catalog.exceptions.TableNotExistException;
import org.apache.flink.table.types.logical.DecimalType;
import org.apache.flink.table.types.logical.LogicalType;
import org.apache.flink.table.types.logical.TimestampType;
Expand All @@ -37,6 +38,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

public class FlinkTableMetadataUtil {
Expand Down Expand Up @@ -131,4 +133,19 @@ public static List<Column> getColumnList(
});
return columns;
}

public static boolean dropTable(
CustomTableEnvironment customTableEnvironment, String catalogName, String database, String tableName) {
Optional<org.apache.flink.table.catalog.Catalog> catalogOptional =
customTableEnvironment.getCatalogManager().getCatalog(catalogName);
if (catalogOptional.isPresent()) {
try {
catalogOptional.get().dropTable(new ObjectPath(database, tableName), true);
return true;
} catch (TableNotExistException e) {
return false;
}
}
return false;
}
}
7 changes: 6 additions & 1 deletion dinky-common/src/main/java/org/dinky/data/enums/Status.java
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,12 @@ public enum Status {
SYS_APPROVAL_SETTINGS_TASK_REVIEWER_ROLES(210, "sys.approval.settings.taskReviewerRoles"),
SYS_APPROVAL_SETTINGS_TASK_REVIEWER_ROLES_NOTE(211, "sys.approval.settings.taskReviewerRoles.note"),
SYS_APPROVAL_TASK_NOT_APPROVED(212, "sys.approval.taskNotApproved"),
SYS_APPROVAL_DUPLICATE_APPROVAL_IN_PROCESS(213, "sys.approval.duplicateInProcess");
SYS_APPROVAL_DUPLICATE_APPROVAL_IN_PROCESS(213, "sys.approval.duplicateInProcess"),
/**
* Catalog
*/
SYS_CATALOG_ONLY_SUPPORT_FLINK_SQL_OPERATION(214, "sys.catalog.operationOnlySupportedOnFlinkSql");

private final int code;
private final String key;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,4 +333,7 @@ sys.approval.settings.enforceCrossReview.note=Submitter of an approval are not a
sys.approval.settings.taskReviewerRoles=Reviewer Role Codes
sys.approval.settings.taskReviewerRoles.note=Roles who can review tasks, different role codes should be divided by comma. For example: SuperAdmin,Reviewer
sys.approval.taskNotApproved=Current task is not published or published version is not approved, please try again after task being published and approved
sys.approval.duplicateInProcess=Already have an approval in process, please do not submit again
sys.approval.duplicateInProcess=Already have an approval in process, please do not submit again

# catalog
sys.catalog.operationOnlySupportedOnFlinkSql=Only supports operations on the catalog of Flink SQL jobs
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,6 @@ sys.approval.settings.taskReviewerRoles=具有审批权限的角色编码
sys.approval.settings.taskReviewerRoles.note=具有审批权限的角色编码,多个角色用英文逗号隔开,例如:SuperAdmin,Reviewer
sys.approval.taskNotApproved=当前作业未发布或发布版本未通过审核,不允许运行,请在任务发布且发布版本通过审核后重试
sys.approval.duplicateInProcess=存在仍在进行的审批流程,请勿重复提交

# catalog
sys.catalog.operationOnlySupportedOnFlinkSql=仅允许对FlinkSql作业的Catalog进行操作
4 changes: 4 additions & 0 deletions dinky-web/src/locales/en-US/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ export default {
'datastudio.sqlTask.flinkJar.args.tip': 'Please enter the program running parameters (args)',
'datastudio.sqlTask.flinkJar.allowNonRestoredState':
'Ignore undeclared state (allowNonRestoredState)',
'datastudio.project.delete.table': 'Drop [{catalog}.{database}.{table}]',
'datastudio.project.delete.table.confirm':
'Drop statement will be called to delete the table. \nPlease operate with caution! This operation is irreversible!!! \n\t\t\t\tConfirm to delete?',

/**
*
* devops
Expand Down
3 changes: 3 additions & 0 deletions dinky-web/src/locales/zh-CN/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ export default {
'datastudio.sqlTask.flinkJar.args': '程序运行参数(args)',
'datastudio.sqlTask.flinkJar.args.tip': '请输入程序运行参数(args)',
'datastudio.sqlTask.flinkJar.allowNonRestoredState': '忽略未声明状态(allowNonRestoredState)',
'datastudio.project.delete.table': '删除 [{catalog}.{database}.{table}]',
'datastudio.project.delete.table.confirm':
'此操作将执行Drop语句来删除当前表单.\n\t\t\t\t请谨慎操作! 该操作不可逆!!!\n\t\t\t\t\t确认删除吗?',
/**
*
* devops
Expand Down
140 changes: 140 additions & 0 deletions dinky-web/src/pages/DataStudio/Toolbar/Catalog/RightContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { MenuInfo } from 'rc-menu/es/interface';
import React, { useEffect, useState } from 'react';
import { InitProjectState } from '@/types/Studio/init.d';
import { ProjectState } from '@/types/Studio/state';
import { Modal, Typography } from 'antd';
import { RightContextMenuState } from '@/pages/DataStudio/data.d';
import { InitContextMenuPosition } from '@/pages/DataStudio/function';
import RightContextMenu from '@/pages/DataStudio/RightContextMenu';
import { l } from '@/utils/intl';
import { dropMSTable } from "@/pages/DataStudio/Toolbar/Catalog/service";
import { CatalogState } from "@/pages/DataStudio/Toolbar/Catalog/data";
import { TABLE_RIGHT_MENU } from "@/pages/DataStudio/Toolbar/Catalog/constant";

const {Text} = Typography;
export type RightContextProps = {
refreshMetaStoreTables: () => Promise<any>;
catalogState: CatalogState | undefined;
};
export const useRightContext = (props: RightContextProps) => {
const {
refreshMetaStoreTables,
catalogState: CatalogState
} = props;

const [rightContextMenuState, setRightContextMenuState] = useState<RightContextMenuState>({
show: false,
position: InitContextMenuPosition
});
const [projectState, setProjectState] = useState<ProjectState>(InitProjectState);
useEffect(() => {
setProjectState((prevState) => ({
...prevState,
menuItems: []
}));
}, [projectState.isCut, projectState.cutId]);
/**
* the right click event
* @param info
*/
const handleProjectRightClick = (info: any) => {
const {
node: {isLeaf, key, fullInfo, isTable, isView},
node,
event
} = info;
setProjectState((prevState) => ({
...prevState,
isLeaf: isLeaf,
menuItems: isTable || isView ? TABLE_RIGHT_MENU() : [],
contextMenuOpen: true,
rightClickedNode: {...node, ...fullInfo},
value: fullInfo
}));
};

const handleContextCancel = () => {
setProjectState((prevState) => ({
...prevState,
contextMenuOpen: false
}));
};

const handleDeleteSubmit = async () => {
const {name, type, key: table, catalog, schema: database} = projectState.rightClickedNode;
const {envId, dialect} = props.catalogState;

handleContextCancel();
console.log(projectState.rightClickedNode);
console.log(props.catalogState)
Modal.confirm({
title: l('datastudio.project.delete.table', '', {catalog, database, table}),
width: '30%',
content: (
<Text className={'needWrap'} type='danger'>
{l('datastudio.project.delete.table.confirm')}
</Text>
),
okText: l('button.confirm'),
cancelText: l('button.cancel'),
onOk: async () => {
await dropMSTable({
envId,
catalog,
database,
table,
dialect
});
await refreshMetaStoreTables();
}
});
};
const handleMenuClick = async (node: MenuInfo) => {
setProjectState((prevState) => ({...prevState, rightActiveKey: node.key}));
switch (node.key) {
case 'delete':
await handleDeleteSubmit();
break
default:
handleContextCancel();
break;
}
};

return {
RightContent: (
<>
<RightContextMenu
contextMenuPosition={rightContextMenuState.position}
open={rightContextMenuState.show}
openChange={() =>
setRightContextMenuState((prevState) => ({...prevState, show: false}))
}
items={projectState.menuItems}
onClick={handleMenuClick}
/>
</>
),
setRightContextMenuState,
handleProjectRightClick
};
};
30 changes: 30 additions & 0 deletions dinky-web/src/pages/DataStudio/Toolbar/Catalog/constant.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { MenuItemType } from "antd/es/menu/interface";
import { DeleteTwoTone } from "@ant-design/icons";
import { l } from "@/utils/intl";

export const TABLE_RIGHT_MENU = (): MenuItemType[] => [
{
key: 'delete',
icon: <DeleteTwoTone twoToneColor={'red'}/>,
label: l('button.delete')
}
];
14 changes: 14 additions & 0 deletions dinky-web/src/pages/DataStudio/Toolbar/Catalog/data.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,17 @@ export type TableDataNode = {
isTable: boolean;
} & DataNode &
DataSources.Table;

export type ViewDataNode = {
isView: boolean;
schema: string;
catalog: string;
} & DataNode;

export type CatalogState = {
envId?: number;
databaseId?: number;
dialect?: string;
fragment?: boolean;
engine?: string;
};
Loading
Loading