Unverified Commit 56a8db9a authored by aiwenmo's avatar aiwenmo Committed by GitHub

[Feature-728][admin,web] Add meta store feature (#729)

Co-authored-by: 's avatarwenmo <32723967+wenmo@users.noreply.github.com>
parent 92f97a6a
package com.dlink.controller; package com.dlink.controller;
import com.dlink.assertion.Asserts; import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.dlink.common.result.Result; import com.dlink.common.result.Result;
import com.dlink.dto.SessionDTO; import com.dlink.dto.SessionDTO;
import com.dlink.dto.StudioCADTO; import com.dlink.dto.StudioCADTO;
import com.dlink.dto.StudioDDLDTO; import com.dlink.dto.StudioDDLDTO;
import com.dlink.dto.StudioExecuteDTO; import com.dlink.dto.StudioExecuteDTO;
import com.dlink.explainer.lineage.LineageResult; import com.dlink.dto.StudioMetaStoreDTO;
import com.dlink.job.JobResult; import com.dlink.job.JobResult;
import com.dlink.result.IResult; import com.dlink.result.IResult;
import com.dlink.service.StudioService; import com.dlink.service.StudioService;
...@@ -14,12 +26,6 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -14,12 +26,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
/** /**
* StudioController * StudioController
* *
...@@ -161,4 +167,20 @@ public class StudioController { ...@@ -161,4 +167,20 @@ public class StudioController {
@RequestParam String savePointType, @RequestParam String name, @RequestParam Integer taskId) { @RequestParam String savePointType, @RequestParam String name, @RequestParam Integer taskId) {
return Result.succeed(studioService.savepoint(taskId, clusterId, jobId, savePointType, name), "savepoint 成功"); return Result.succeed(studioService.savepoint(taskId, clusterId, jobId, savePointType, name), "savepoint 成功");
} }
/**
* 获取 Meta Store Catalog 和 Database
*/
@PostMapping("/getMSCatalogs")
public Result getMSCatalogs(@RequestBody StudioMetaStoreDTO studioMetaStoreDTO) {
return Result.succeed(studioService.getMSCatalogs(studioMetaStoreDTO), "获取成功");
}
/**
* 获取 Meta Store Table
*/
@PostMapping("/getMSTables")
public Result getMSTables(@RequestBody StudioMetaStoreDTO studioMetaStoreDTO) {
return Result.succeed(studioService.getMSTables(studioMetaStoreDTO), "获取成功");
}
} }
package com.dlink.dto;
import lombok.Getter;
import java.util.HashMap;
import java.util.Map;
import com.dlink.assertion.Asserts;
import com.dlink.gateway.GatewayType;
import com.dlink.job.JobConfig;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
/**
* StudioMetaStoreDTO
*
* @author wenmo
* @since 2022/7/16 23:18
*/
@Getter
public class StudioMetaStoreDTO extends AbstractStatementDTO {
private String catalog;
private String database;
private String dialect;
private Integer databaseId;
public JobConfig getJobConfig() {
return new JobConfig(
GatewayType.LOCAL.getLongValue(), true, false, false, false,
null, null, null, null, null,
null, isFragment(), false, false, 0,
null, null, null, null, null);
}
}
package com.dlink.service; package com.dlink.service;
import com.dlink.dto.*; import java.util.List;
import com.dlink.dto.SessionDTO;
import com.dlink.dto.SqlDTO;
import com.dlink.dto.StudioCADTO;
import com.dlink.dto.StudioDDLDTO;
import com.dlink.dto.StudioExecuteDTO;
import com.dlink.dto.StudioMetaStoreDTO;
import com.dlink.explainer.lineage.LineageResult; import com.dlink.explainer.lineage.LineageResult;
import com.dlink.job.JobResult; import com.dlink.job.JobResult;
import com.dlink.model.Catalog;
import com.dlink.model.Table;
import com.dlink.result.IResult; import com.dlink.result.IResult;
import com.dlink.result.SelectResult; import com.dlink.result.SelectResult;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
...@@ -10,8 +19,6 @@ import com.dlink.session.SessionInfo; ...@@ -10,8 +19,6 @@ import com.dlink.session.SessionInfo;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.List;
/** /**
* StudioService * StudioService
* *
...@@ -47,4 +54,8 @@ public interface StudioService { ...@@ -47,4 +54,8 @@ public interface StudioService {
boolean cancel(Integer clusterId, String jobId); boolean cancel(Integer clusterId, String jobId);
boolean savepoint(Integer taskId, Integer clusterId, String jobId, String savePointType, String name); boolean savepoint(Integer taskId, Integer clusterId, String jobId, String savePointType, String name);
List<Catalog> getMSCatalogs(StudioMetaStoreDTO studioMetaStoreDTO);
List<Table> getMSTables(StudioMetaStoreDTO studioMetaStoreDTO);
} }
...@@ -2,6 +2,7 @@ package com.dlink.service.impl; ...@@ -2,6 +2,7 @@ package com.dlink.service.impl;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -19,6 +20,7 @@ import com.dlink.dto.SqlDTO; ...@@ -19,6 +20,7 @@ import com.dlink.dto.SqlDTO;
import com.dlink.dto.StudioCADTO; import com.dlink.dto.StudioCADTO;
import com.dlink.dto.StudioDDLDTO; import com.dlink.dto.StudioDDLDTO;
import com.dlink.dto.StudioExecuteDTO; import com.dlink.dto.StudioExecuteDTO;
import com.dlink.dto.StudioMetaStoreDTO;
import com.dlink.explainer.lineage.LineageBuilder; import com.dlink.explainer.lineage.LineageBuilder;
import com.dlink.explainer.lineage.LineageResult; import com.dlink.explainer.lineage.LineageResult;
import com.dlink.gateway.GatewayType; import com.dlink.gateway.GatewayType;
...@@ -29,10 +31,14 @@ import com.dlink.job.JobManager; ...@@ -29,10 +31,14 @@ import com.dlink.job.JobManager;
import com.dlink.job.JobResult; import com.dlink.job.JobResult;
import com.dlink.metadata.driver.Driver; import com.dlink.metadata.driver.Driver;
import com.dlink.metadata.result.JdbcSelectResult; import com.dlink.metadata.result.JdbcSelectResult;
import com.dlink.model.Catalog;
import com.dlink.model.Cluster; import com.dlink.model.Cluster;
import com.dlink.model.DataBase; import com.dlink.model.DataBase;
import com.dlink.model.Savepoints; import com.dlink.model.Savepoints;
import com.dlink.model.Schema;
import com.dlink.model.Table;
import com.dlink.model.Task; import com.dlink.model.Task;
import com.dlink.result.DDLResult;
import com.dlink.result.IResult; import com.dlink.result.IResult;
import com.dlink.result.SelectResult; import com.dlink.result.SelectResult;
import com.dlink.result.SqlExplainResult; import com.dlink.result.SqlExplainResult;
...@@ -115,6 +121,15 @@ public class StudioServiceImpl implements StudioService { ...@@ -115,6 +121,15 @@ public class StudioServiceImpl implements StudioService {
return jobResult; return jobResult;
} }
private IResult executeMSFlinkSql(StudioMetaStoreDTO studioMetaStoreDTO) {
addFlinkSQLEnv(studioMetaStoreDTO);
JobConfig config = studioMetaStoreDTO.getJobConfig();
JobManager jobManager = JobManager.build(config);
IResult jobResult = jobManager.executeDDL(studioMetaStoreDTO.getStatement());
RunTimeUtil.recovery(jobManager);
return jobResult;
}
public JobResult executeCommonSql(SqlDTO sqlDTO) { public JobResult executeCommonSql(SqlDTO sqlDTO) {
JobResult result = new JobResult(); JobResult result = new JobResult();
result.setStatement(sqlDTO.getStatement()); result.setStatement(sqlDTO.getStatement());
...@@ -348,6 +363,84 @@ public class StudioServiceImpl implements StudioService { ...@@ -348,6 +363,84 @@ public class StudioServiceImpl implements StudioService {
return false; return false;
} }
@Override
public List<Catalog> getMSCatalogs(StudioMetaStoreDTO studioMetaStoreDTO) {
List<Catalog> catalogs = new ArrayList<>();
if (Dialect.isSql(studioMetaStoreDTO.getDialect())) {
DataBase dataBase = dataBaseService.getById(studioMetaStoreDTO.getDatabaseId());
if (!Asserts.isNull(dataBase)) {
Catalog defaultCatalog = Catalog.build("default_catalog");
Driver driver = Driver.build(dataBase.getDriverConfig());
defaultCatalog.setSchemas(driver.listSchemas());
catalogs.add(defaultCatalog);
}
} else {
studioMetaStoreDTO.setStatement("SHOW CATALOGS");
IResult result = executeMSFlinkSql(studioMetaStoreDTO);
if (result instanceof DDLResult) {
DDLResult ddlResult = (DDLResult) result;
Iterator<String> iterator = ddlResult.getColumns().iterator();
if (iterator.hasNext()) {
String key = iterator.next();
List<Map<String, Object>> rowData = ddlResult.getRowData();
for (Map<String, Object> item : rowData) {
catalogs.add(Catalog.build(item.get(key).toString()));
}
}
for (Catalog catalog : catalogs) {
String statement = "USE CATALOG " + catalog.getName() + ";\r\nSHOW DATABASES";
studioMetaStoreDTO.setStatement(statement);
IResult tableResult = executeMSFlinkSql(studioMetaStoreDTO);
if (result instanceof DDLResult) {
DDLResult tableDDLResult = (DDLResult) tableResult;
Iterator<String> tableIterator = tableDDLResult.getColumns().iterator();
if (tableIterator.hasNext()) {
String key = tableIterator.next();
List<Map<String, Object>> rowData = tableDDLResult.getRowData();
List<Schema> schemas = new ArrayList<>();
for (Map<String, Object> item : rowData) {
schemas.add(Schema.build(item.get(key).toString()));
}
catalog.setSchemas(schemas);
}
}
}
}
}
return catalogs;
}
@Override
public List<Table> getMSTables(StudioMetaStoreDTO studioMetaStoreDTO) {
List<Table> tables = new ArrayList<>();
if (Dialect.isSql(studioMetaStoreDTO.getDialect())) {
DataBase dataBase = dataBaseService.getById(studioMetaStoreDTO.getDatabaseId());
if (Asserts.isNotNull(dataBase)) {
Driver driver = Driver.build(dataBase.getDriverConfig());
tables.addAll(driver.listTables(studioMetaStoreDTO.getDatabase()));
}
} else {
String statement = "USE CATALOG " + studioMetaStoreDTO.getCatalog() + ";\r\n" +
"USE " + studioMetaStoreDTO.getDatabase() + ";\r\nSHOW TABLES";
studioMetaStoreDTO.setStatement(statement);
IResult result = executeMSFlinkSql(studioMetaStoreDTO);
if (result instanceof DDLResult) {
DDLResult ddlResult = (DDLResult) result;
Iterator<String> iterator = ddlResult.getColumns().iterator();
if (iterator.hasNext()) {
String key = iterator.next();
List<Map<String, Object>> rowData = ddlResult.getRowData();
for (Map<String, Object> item : rowData) {
Table table = Table.build(item.get(key).toString(), studioMetaStoreDTO.getDatabase());
table.setCatalog(studioMetaStoreDTO.getCatalog());
tables.add(table);
}
}
}
}
return tables;
}
private void initUDF(JobConfig config, String statement) { private void initUDF(JobConfig config, String statement) {
if (!GatewayType.LOCAL.equalsValue(config.getType())) { if (!GatewayType.LOCAL.equalsValue(config.getType())) {
return; return;
......
package com.dlink.service.impl; package com.dlink.service.impl;
import cn.hutool.core.bean.BeanUtil; import org.apache.commons.lang3.StringUtils;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dlink.alert.Alert; import com.dlink.alert.Alert;
...@@ -70,25 +91,8 @@ import com.dlink.service.TaskVersionService; ...@@ -70,25 +91,8 @@ import com.dlink.service.TaskVersionService;
import com.dlink.utils.CustomStringJavaCompiler; import com.dlink.utils.CustomStringJavaCompiler;
import com.dlink.utils.JSONUtil; import com.dlink.utils.JSONUtil;
import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource; import cn.hutool.core.bean.BeanUtil;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 任务 服务实现类 * 任务 服务实现类
...@@ -185,9 +189,9 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -185,9 +189,9 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
return executeCommonSql(SqlDTO.build(task.getStatement(), return executeCommonSql(SqlDTO.build(task.getStatement(),
task.getDatabaseId(), null)); task.getDatabaseId(), null));
} }
if (StringUtils.isBlank(savePointPath)){ if (StringUtils.isBlank(savePointPath)) {
task.setSavePointStrategy(SavePointStrategy.LATEST.getValue()); task.setSavePointStrategy(SavePointStrategy.LATEST.getValue());
}else { } else {
task.setSavePointStrategy(SavePointStrategy.CUSTOM.getValue()); task.setSavePointStrategy(SavePointStrategy.CUSTOM.getValue());
task.setSavePointPath(savePointPath); task.setSavePointPath(savePointPath);
updateById(task); updateById(task);
...@@ -202,7 +206,6 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -202,7 +206,6 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
} }
private JobResult executeCommonSql(SqlDTO sqlDTO) { private JobResult executeCommonSql(SqlDTO sqlDTO) {
JobResult result = new JobResult(); JobResult result = new JobResult();
result.setStatement(sqlDTO.getStatement()); result.setStatement(sqlDTO.getStatement());
...@@ -359,7 +362,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -359,7 +362,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
defaultFlinkSQLEnvTask.setAlias("DefaultCatalog"); defaultFlinkSQLEnvTask.setAlias("DefaultCatalog");
defaultFlinkSQLEnvTask.setDialect(Dialect.FLINKSQLENV.getValue()); defaultFlinkSQLEnvTask.setDialect(Dialect.FLINKSQLENV.getValue());
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("create catalog myCatalog with(\n"); sb.append("create catalog my_catalog with(\n");
sb.append(" 'type' = 'dlink_mysql',\n"); sb.append(" 'type' = 'dlink_mysql',\n");
sb.append(" 'username' = '"); sb.append(" 'username' = '");
sb.append(username); sb.append(username);
...@@ -372,7 +375,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -372,7 +375,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
sb.append("'\n"); sb.append("'\n");
sb.append(")"); sb.append(")");
sb.append(separator); sb.append(separator);
sb.append("use catalog myCatalog"); sb.append("use catalog my_catalog");
sb.append(separator); sb.append(separator);
defaultFlinkSQLEnvTask.setStatement(sb.toString()); defaultFlinkSQLEnvTask.setStatement(sb.toString());
defaultFlinkSQLEnvTask.setFragment(true); defaultFlinkSQLEnvTask.setFragment(true);
...@@ -545,7 +548,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen ...@@ -545,7 +548,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TaskMapper, Task> implemen
if (Asserts.isNotNull(task.getJobInstanceId()) && task.getJobInstanceId() != 0) { if (Asserts.isNotNull(task.getJobInstanceId()) && task.getJobInstanceId() != 0) {
savepointJobInstance(task.getJobInstanceId(), SavePointType.CANCEL.getValue()); savepointJobInstance(task.getJobInstanceId(), SavePointType.CANCEL.getValue());
} }
if (StringUtils.isNotBlank(savePointPath)){ if (StringUtils.isNotBlank(savePointPath)) {
task.setSavePointStrategy(SavePointStrategy.CUSTOM.getValue()); task.setSavePointStrategy(SavePointStrategy.CUSTOM.getValue());
task.setSavePointPath(savePointPath); task.setSavePointPath(savePointPath);
} }
......
package com.dlink.model;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* Catalog
*
* @author wenmo
* @since 2022/7/17 21:37
*/
@Getter
@Setter
public class Catalog implements Serializable {
private static final long serialVersionUID = -7535759384541414568L;
private String name;
private List<Schema> schemas = new ArrayList<>();
public Catalog() {
}
public Catalog(String name) {
this.name = name;
}
public Catalog(String name, List<Schema> schemas) {
this.name = name;
this.schemas = schemas;
}
public static Catalog build(String name) {
return new Catalog(name);
}
}
...@@ -426,6 +426,7 @@ public class JobManager { ...@@ -426,6 +426,7 @@ public class JobManager {
public IResult executeDDL(String statement) { public IResult executeDDL(String statement) {
String[] statements = SqlUtil.getStatements(statement, sqlSeparator); String[] statements = SqlUtil.getStatements(statement, sqlSeparator);
try { try {
IResult result = null;
for (String item : statements) { for (String item : statements) {
String newStatement = executor.pretreatStatement(item); String newStatement = executor.pretreatStatement(item);
if (newStatement.trim().isEmpty()) { if (newStatement.trim().isEmpty()) {
...@@ -437,10 +438,10 @@ public class JobManager { ...@@ -437,10 +438,10 @@ public class JobManager {
} }
LocalDateTime startTime = LocalDateTime.now(); LocalDateTime startTime = LocalDateTime.now();
TableResult tableResult = executor.executeSql(newStatement); TableResult tableResult = executor.executeSql(newStatement);
IResult result = ResultBuilder.build(operationType, config.getMaxRowNum(), false, false, executor.getTimeZone()).getResult(tableResult); result = ResultBuilder.build(operationType, config.getMaxRowNum(), false, false, executor.getTimeZone()).getResult(tableResult);
result.setStartTime(startTime); result.setStartTime(startTime);
return result;
} }
return result;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
......
...@@ -43,6 +43,15 @@ export type StudioParam = { ...@@ -43,6 +43,15 @@ export type StudioParam = {
checkPoint?: number, checkPoint?: number,
savePointPath?: string, savePointPath?: string,
} }
export type StudioMetaStoreParam = {
statement?: string,
fragment?: boolean,
dialect?: string,
envId?: number,
databaseId?: number,
}
export type CAParam = { export type CAParam = {
statement: string, statement: string,
statementSet: boolean, statementSet: boolean,
......
import {executeDDL} from "@/pages/DataStudio/service"; import {executeDDL, getMSCatalogs} from "@/pages/DataStudio/service";
import FlinkSQL from "./FlinkSQL"; import FlinkSQL from "./FlinkSQL";
import {SessionType} from "@/pages/DataStudio/model"; import {MetaStoreCatalogType, SessionType, TaskType} from "@/pages/DataStudio/model";
import {Modal, message} from "antd"; import {Modal, message} from "antd";
import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud"; import {addOrUpdateData, getData, handleRemove} from "@/components/Common/crud";
...@@ -274,3 +274,35 @@ export function cancelTask(id: number) { ...@@ -274,3 +274,35 @@ export function cancelTask(id: number) {
export function recoveryTask(id: number) { export function recoveryTask(id: number) {
return getData('api/task/recoveryTask', {id}); return getData('api/task/recoveryTask', {id});
} }
/*--- 刷新 MetaStore Catalogs ---*/
export async function showMetaStoreCatalogs(task: TaskType, dispatch: any) {
if (!task?.dialect) {
return;
}
let param = {
envId: task.envId,
fragment: task.fragment,
dialect: task.dialect,
databaseId: task.databaseId,
};
const result = getMSCatalogs(param);
result.then(res => {
const catalogs: MetaStoreCatalogType[] = [];
if (res.datas) {
for (let i = 0; i < res.datas.length; i++) {
catalogs.push({
name: res.datas[i].name,
databases: res.datas[i].schemas,
});
}
}
dispatch && dispatch({
type: "Studio/saveMetaStore",
payload: {
activeKey: task.id,
metaStore: catalogs
},
});
})
}
import {Button, Col, Empty, message, Modal, Row, Select, Tabs, Tooltip, Tree} from "antd";
import {MetaStoreTableType, StateType} from "@/pages/DataStudio/model";
import {connect} from "umi";
import React, {useState} from "react";
import {
CodepenOutlined,
DownOutlined,
OrderedListOutlined,
ReloadOutlined,
TableOutlined
} from '@ant-design/icons';
import {Scrollbars} from 'react-custom-scrollbars';
import Columns from "@/pages/DataBase/Columns";
import Tables from "@/pages/DataBase/Tables";
import {TreeDataNode} from "@/components/Studio/StudioTree/Function";
import Generation from "@/pages/DataBase/Generation";
import {getMSTables} from "@/pages/DataStudio/service";
import {Dispatch} from "@@/plugin-dva/connect";
const {DirectoryTree} = Tree;
const {Option, OptGroup} = Select;
const {TabPane} = Tabs;
const StudioMetaStore = (props: any) => {
const {current, toolHeight} = props;
const [catalog, setCatalog] = useState<string>();
const [database, setDatabase] = useState<string>();
const [treeData, setTreeData] = useState<[]>([]);
const [modalVisit, setModalVisit] = useState(false);
const [row, setRow] = useState<TreeDataNode>();
const onRefreshTreeData = (catalogAndDatabase: string) => {
if (!current?.task?.dialect || !catalogAndDatabase) {
return;
}
const names = catalogAndDatabase.split('.');
let catalogTmp = 'default_catalog';
let databaseTmp = 'default_database';
if (names.length > 1) {
catalogTmp = names[0];
databaseTmp = names[1];
} else if (names.length == 1) {
databaseTmp = names[0];
}
setCatalog(catalogTmp);
setDatabase(databaseTmp);
let param = {
envId: current.task.envId,
fragment: current.task.fragment,
dialect: current.task.dialect,
databaseId: current.task.databaseId,
catalog: catalogTmp,
database: databaseTmp,
};
const result = getMSTables(param);
result.then(res => {
const tables: MetaStoreTableType[] = [];
if (res.datas) {
for (let i = 0; i < res.datas.length; i++) {
tables.push({
name: res.datas[i].name,
columns: res.datas[i].columns,
});
}
}
const tablesData: [] = [];
for (let i = 0; i < tables.length; i++) {
tablesData.push({
name: tables[i].name,
title: tables[i].name,
key: tables[i].name,
icon: <TableOutlined/>,
isLeaf: true,
catalog: catalogTmp,
database: databaseTmp,
})
}
setTreeData(tablesData);
props.saveMetaStoreTable(current.key, catalogTmp, databaseTmp, tables);
message.success(`刷新 Catalog 成功`);
})
};
const refreshMetaStoreTables = () => {
onRefreshTreeData(catalog + '.' + database);
};
const onChangeMetaStoreCatalogs = (value: number) => {
onRefreshTreeData(value);
};
const getMetaStoreCatalogsOptions = () => {
const itemList = [];
if (current?.metaStore) {
for (const item of current?.metaStore) {
itemList.push(<OptGroup label={item.name}>
{item.databases.map(({name}) => (
<Option value={item.name + '.' + name} label={item.name + '.' + name}>{name}</Option>
))}
</OptGroup>)
}
}
return itemList;
};
const openColumnInfo = (e: React.MouseEvent, node: TreeDataNode) => {
if (node.isLeaf) {
setRow(node);
setModalVisit(true);
}
}
const cancelHandle = () => {
setRow(undefined);
setModalVisit(false);
}
return (
<>
<Row>
<Col span={24}>
<Tooltip title="刷新 Catalog">
<Button
type="text"
icon={<ReloadOutlined/>}
onClick={refreshMetaStoreTables}
/>
</Tooltip>
</Col>
</Row>
<Select
style={{width: '95%'}}
placeholder="选择 Catalog & Database"
optionLabelProp="label"
onChange={onChangeMetaStoreCatalogs}
>
{getMetaStoreCatalogsOptions()}
</Select>
<Scrollbars style={{height: (toolHeight - 32)}}>
{treeData.length > 0 ? (
<DirectoryTree
showIcon
switcherIcon={<DownOutlined/>}
treeData={treeData}
onRightClick={({event, node}: any) => {
openColumnInfo(event, node)
}}
/>) : (<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>)}
</Scrollbars>
<Modal
title={row?.key}
visible={modalVisit}
width={1000}
onCancel={() => {
cancelHandle();
}}
footer={[
<Button key="back" onClick={() => {
cancelHandle();
}}>
关闭
</Button>,
]}
>
<Tabs defaultActiveKey="tableInfo" size="small">
<TabPane
tab={
<span>
<TableOutlined/>
表信息
</span>
}
key="tableInfo"
>
{row ? <Tables table={row}/> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</TabPane>
<TabPane
tab={
<span>
<CodepenOutlined/>
字段信息
</span>
}
key="columnInfo"
>
{row ? <Columns dbId={current.task.databaseId} schema={row.database} table={row.name}/> :
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</TabPane>
<TabPane
tab={
<span>
<OrderedListOutlined/>
SQL 生成
</span>
}
key="sqlGeneration"
>
{row ? <Generation dbId={current.task.databaseId} schema={row.database} table={row.name}/> :
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>}
</TabPane>
</Tabs>
</Modal>
</>
);
};
const mapDispatchToProps = (dispatch: Dispatch) => ({
saveMetaStoreTable: (activeKey: number, catalog: string, database: string, tables: MetaStoreTableType[]) => dispatch({
type: "Studio/saveMetaStoreTable",
payload: {
activeKey,
catalog,
database,
tables,
},
}),
});
export default connect(({Studio}: { Studio: StateType }) => ({
current: Studio.current,
toolHeight: Studio.toolHeight,
}), mapDispatchToProps)(StudioMetaStore);
import {Tabs, Empty} from "antd"; import {Tabs, Empty} from "antd";
import {BarsOutlined,DatabaseOutlined,AppstoreOutlined,ClusterOutlined,MessageOutlined,FireOutlined,FunctionOutlined} from "@ant-design/icons"; import {
BarsOutlined,
DatabaseOutlined,
AppstoreOutlined,
ClusterOutlined,
MessageOutlined,
InsertRowAboveOutlined,
FunctionOutlined
} from "@ant-design/icons";
import {StateType} from "@/pages/DataStudio/model"; import {StateType} from "@/pages/DataStudio/model";
import {connect} from "umi"; import {connect} from "umi";
import styles from "./index.less"; import styles from "./index.less";
...@@ -9,37 +17,41 @@ import React from "react"; ...@@ -9,37 +17,41 @@ import React from "react";
import StudioDataBase from "./StudioDataBase"; import StudioDataBase from "./StudioDataBase";
import StudioCluster from "./StudioCluster"; import StudioCluster from "./StudioCluster";
import StudioMetaData from "./StudioMetaData"; import StudioMetaData from "./StudioMetaData";
import StudioMetaStore from "./StudioMetaStore";
const { TabPane } = Tabs; const {TabPane} = Tabs;
const StudioLeftTool = (props:any) => { const StudioLeftTool = (props: any) => {
const {toolHeight} = props; const {toolHeight} = props;
return ( return (
<Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{ height: toolHeight}}> <Tabs defaultActiveKey="1" size="small" tabPosition="left" style={{height: toolHeight}}>
<TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree"> <TabPane tab={<span><BarsOutlined/> 目录</span>} key="StudioTree">
<StudioTree/> <StudioTree/>
</TabPane> </TabPane>
<TabPane tab={<span><MessageOutlined /> 会话</span>} key="Connectors"> <TabPane tab={<span><InsertRowAboveOutlined/> 结构</span>} key="MetaStore">
<StudioConnector /> <StudioMetaStore/>
</TabPane> </TabPane>
<TabPane tab={<span><ClusterOutlined /> 集群</span>} key="Cluster"> <TabPane tab={<span><MessageOutlined/> 会话</span>} key="Connectors">
<StudioCluster /> <StudioConnector/>
</TabPane> </TabPane>
<TabPane tab={<span><DatabaseOutlined /> 数据源</span>} key="DataSource"> <TabPane tab={<span><ClusterOutlined/> 集群</span>} key="Cluster">
<StudioDataBase /> <StudioCluster/>
</TabPane> </TabPane>
<TabPane tab={<span><AppstoreOutlined /> 元数据</span>} key="MetaData"> <TabPane tab={<span><DatabaseOutlined/> 数据源</span>} key="DataSource">
<StudioMetaData /> <StudioDataBase/>
</TabPane> </TabPane>
<TabPane tab={<span><FunctionOutlined /> 函数</span>} key="Function" > <TabPane tab={<span><AppstoreOutlined/> 元数据</span>} key="MetaData">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> <StudioMetaData/>
</TabPane>
<TabPane tab={<span><FunctionOutlined/> 函数</span>} key="Function">
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</TabPane> </TabPane>
</Tabs> </Tabs>
); );
}; };
export default connect(({ Studio }: { Studio: StateType }) => ({ export default connect(({Studio}: { Studio: StateType }) => ({
sql: Studio.sql, sql: Studio.sql,
toolHeight: Studio.toolHeight, toolHeight: Studio.toolHeight,
}))(StudioLeftTool); }))(StudioLeftTool);
...@@ -483,7 +483,7 @@ const StudioMenu = (props: any) => { ...@@ -483,7 +483,7 @@ const StudioMenu = (props: any) => {
return ( return (
<Row className={styles.container}> <Row className={styles.container}>
<Col span={24}> {/*<Col span={24}>
<div> <div>
<Space> <Space>
<Dropdown overlay={menu}> <Dropdown overlay={menu}>
...@@ -508,14 +508,14 @@ const StudioMenu = (props: any) => { ...@@ -508,14 +508,14 @@ const StudioMenu = (props: any) => {
</Dropdown> </Dropdown>
</Space> </Space>
</div> </div>
</Col> </Col>*/}
<Divider className={styles["ant-divider-horizontal-0"]}/> <Divider className={styles["ant-divider-horizontal-0"]}/>
<Col span={24}> <Col span={24}>
<Row> <Row>
<Col span={16}> <Col span={16}>
<Breadcrumb className={styles["dw-path"]}> <Breadcrumb className={styles["dw-path"]}>
<EnvironmentOutlined/> <EnvironmentOutlined style={{lineHeight: '32px'}}/>
<Divider type="vertical"/> <Divider type="vertical" style={{height: 'unset'}}/>
{getPathItem(currentPath)} {getPathItem(currentPath)}
</Breadcrumb> </Breadcrumb>
{currentSession.session && {currentSession.session &&
...@@ -659,7 +659,7 @@ const StudioMenu = (props: any) => { ...@@ -659,7 +659,7 @@ const StudioMenu = (props: any) => {
<Tooltip title="查看 API"> <Tooltip title="查看 API">
<Button <Button
type="text" type="text"
icon={<ApiTwoTone />} icon={<ApiTwoTone/>}
onClick={showAPI} onClick={showAPI}
/> />
</Tooltip> </Tooltip>
......
...@@ -13,7 +13,7 @@ import UpdateCatalogueForm from './components/UpdateCatalogueForm'; ...@@ -13,7 +13,7 @@ import UpdateCatalogueForm from './components/UpdateCatalogueForm';
import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm"; import SimpleTaskForm from "@/components/Studio/StudioTree/components/SimpleTaskForm";
import {Scrollbars} from "react-custom-scrollbars"; import {Scrollbars} from "react-custom-scrollbars";
import {getIcon} from "@/components/Studio/icon"; import {getIcon} from "@/components/Studio/icon";
import {showEnv} from "@/components/Studio/StudioEvent/DDL"; import {showEnv, showMetaStoreCatalogs} from "@/components/Studio/StudioEvent/DDL";
import UploadModal from "@/components/Studio/StudioTree/components/UploadModal"; import UploadModal from "@/components/Studio/StudioTree/components/UploadModal";
type StudioTreeProps = { type StudioTreeProps = {
...@@ -170,7 +170,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -170,7 +170,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
toCut(rightClickNode); toCut(rightClickNode);
} else if (key == 'Paste') { } else if (key == 'Paste') {
toPaste(rightClickNode); toPaste(rightClickNode);
}else if (key == 'Copy') { } else if (key == 'Copy') {
toCopy(rightClickNode); toCopy(rightClickNode);
} }
}; };
...@@ -229,6 +229,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -229,6 +229,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
chart: {}, chart: {},
}, },
monaco: React.createRef(), monaco: React.createRef(),
metaStore: []
}; };
newTabs!.activeKey = node!.taskId; newTabs!.activeKey = node!.taskId;
newTabs!.panes!.push(newPane); newTabs!.panes!.push(newPane);
...@@ -236,6 +237,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -236,6 +237,7 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
type: "Studio/saveTabs", type: "Studio/saveTabs",
payload: newTabs, payload: newTabs,
}); });
showMetaStoreCatalogs(result.datas, dispatch);
}) })
} }
}; };
...@@ -308,10 +310,10 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => { ...@@ -308,10 +310,10 @@ const StudioTree: React.FC<StudioTreeProps> = (props) => {
const toCopy = async (node: TreeDataNode | undefined) => { const toCopy = async (node: TreeDataNode | undefined) => {
let catalogues = { let catalogues = {
taskId:node?.taskId, taskId: node?.taskId,
parentId: node?.id parentId: node?.id
}; };
const datas = await handleOption('/api/catalogue/copyTask',"复制作业",catalogues); const datas = await handleOption('/api/catalogue/copyTask', "复制作业", catalogues);
if (datas) { if (datas) {
getTreeData(); getTreeData();
......
...@@ -24,9 +24,9 @@ const Studio = (props: any) => { ...@@ -24,9 +24,9 @@ const Studio = (props: any) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const VIEW = { const VIEW = {
leftToolWidth: 300, leftToolWidth: 300,
marginTop: 116, marginTop: 84,
topHeight: 35.6, topHeight: 35.6,
bottomHeight: 153.6, bottomHeight: 127,
rightMargin: 32, rightMargin: 32,
leftMargin: 36, leftMargin: 36,
midMargin: 46, midMargin: 46,
...@@ -152,7 +152,6 @@ const Studio = (props: any) => { ...@@ -152,7 +152,6 @@ const Studio = (props: any) => {
</Row> </Row>
</DraggleVerticalLayout> </DraggleVerticalLayout>
</Card> </Card>
</div> </div>
) )
}; };
......
...@@ -111,6 +111,7 @@ export type TabsItemType = { ...@@ -111,6 +111,7 @@ export type TabsItemType = {
monaco?: any; monaco?: any;
isModified: boolean; isModified: boolean;
sqlMetaData?: SqlMetaData; sqlMetaData?: SqlMetaData;
metaStore?: MetaStoreCatalogType[]
} }
export type TabsType = { export type TabsType = {
...@@ -135,6 +136,26 @@ export type SessionType = { ...@@ -135,6 +136,26 @@ export type SessionType = {
connectors: ConnectorType[]; connectors: ConnectorType[];
} }
export type MetaStoreCatalogType = {
name: string;
databases: MetaStoreDataBaseType[];
}
export type MetaStoreDataBaseType = {
name: string;
tables: MetaStoreTableType[];
}
export type MetaStoreTableType = {
name: string;
columns: MetaStoreColumnType[];
}
export type MetaStoreColumnType = {
name: string;
type: string;
}
export type StateType = { export type StateType = {
isFullScreen: boolean; isFullScreen: boolean;
toolHeight?: number; toolHeight?: number;
...@@ -174,6 +195,8 @@ export type ModelType = { ...@@ -174,6 +195,8 @@ export type ModelType = {
saveCurrentPath: Reducer<StateType>; saveCurrentPath: Reducer<StateType>;
// saveMonaco: Reducer<StateType>; // saveMonaco: Reducer<StateType>;
saveSqlMetaData: Reducer<StateType>; saveSqlMetaData: Reducer<StateType>;
saveMetaStore: Reducer<StateType>;
saveMetaStoreTable: Reducer<StateType>;
saveTabs: Reducer<StateType>; saveTabs: Reducer<StateType>;
closeTabs: Reducer<StateType>; closeTabs: Reducer<StateType>;
changeActiveKey: Reducer<StateType>; changeActiveKey: Reducer<StateType>;
...@@ -219,10 +242,10 @@ const Model: ModelType = { ...@@ -219,10 +242,10 @@ const Model: ModelType = {
panes: [], panes: [],
}, },
session: [], session: [],
result:{}, result: {},
rightClickMenu: false, rightClickMenu: false,
refs:{ refs: {
history:{}, history: {},
} }
}, },
...@@ -250,12 +273,12 @@ const Model: ModelType = { ...@@ -250,12 +273,12 @@ const Model: ModelType = {
...state, ...state,
toolHeight: payload, toolHeight: payload,
}; };
},saveToolRightWidth(state, {payload}) { }, saveToolRightWidth(state, {payload}) {
return { return {
...state, ...state,
toolRightWidth: payload, toolRightWidth: payload,
}; };
},saveToolLeftWidth(state, {payload}) { }, saveToolLeftWidth(state, {payload}) {
return { return {
...state, ...state,
toolLeftWidth: payload, toolLeftWidth: payload,
...@@ -274,7 +297,7 @@ const Model: ModelType = { ...@@ -274,7 +297,7 @@ const Model: ModelType = {
return { return {
...state, ...state,
current: {...newCurrent}, current: {...newCurrent},
tabs:{...newTabs}, tabs: {...newTabs},
}; };
}, },
saveCurrentPath(state, {payload}) { saveCurrentPath(state, {payload}) {
...@@ -292,7 +315,7 @@ const Model: ModelType = { ...@@ -292,7 +315,7 @@ const Model: ModelType = {
saveSqlMetaData(state, {payload}) { saveSqlMetaData(state, {payload}) {
let newCurrent = state.current; let newCurrent = state.current;
const newTabs = state.tabs; const newTabs = state.tabs;
if(newCurrent.key == payload.activeKey){ if (newCurrent.key == payload.activeKey) {
newCurrent.sqlMetaData = {...payload.sqlMetaData}; newCurrent.sqlMetaData = {...payload.sqlMetaData};
newCurrent.isModified = payload.isModified; newCurrent.isModified = payload.isModified;
} }
...@@ -309,6 +332,50 @@ const Model: ModelType = { ...@@ -309,6 +332,50 @@ const Model: ModelType = {
tabs: {...newTabs}, tabs: {...newTabs},
}; };
}, },
saveMetaStore(state, {payload}) {
let newCurrent = state.current;
const newTabs = state.tabs;
if (newCurrent.key == payload.activeKey) {
newCurrent.metaStore = [...payload.metaStore];
}
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload.activeKey) {
newTabs.panes[i].metaStore = [...payload.metaStore];
break;
}
}
return {
...state,
current: {...newCurrent},
tabs: {...newTabs},
};
},
saveMetaStoreTable(state, {payload}) {
let newCurrent = state.current;
const newTabs = state.tabs;
if (newCurrent.key == payload.activeKey) {
for (let i = 0; i < newCurrent.metaStore.length; i++) {
if (newCurrent.metaStore[i].name === payload.catalog) {
for (let j = 0; j < newCurrent.metaStore[i].databases.length; j++) {
if (newCurrent.metaStore[i].databases[j].name === payload.database) {
newCurrent.metaStore[i].databases[j].tables = [...payload.tables]
}
}
}
}
}
for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload.activeKey) {
newTabs.panes[i] = {...newCurrent};
break;
}
}
return {
...state,
current: {...newCurrent},
tabs: {...newTabs},
};
},
saveTabs(state, {payload}) { saveTabs(state, {payload}) {
let newCurrent = state.current; let newCurrent = state.current;
for (let i = 0; i < payload.panes.length; i++) { for (let i = 0; i < payload.panes.length; i++) {
...@@ -316,7 +383,7 @@ const Model: ModelType = { ...@@ -316,7 +383,7 @@ const Model: ModelType = {
newCurrent = payload.panes[i]; newCurrent = payload.panes[i];
} }
} }
if(payload.panes.length == 0){ if (payload.panes.length == 0) {
return { return {
...state, ...state,
current: undefined, current: undefined,
...@@ -328,7 +395,7 @@ const Model: ModelType = { ...@@ -328,7 +395,7 @@ const Model: ModelType = {
...state, ...state,
current: { current: {
...newCurrent, ...newCurrent,
isModified:false, isModified: false,
}, },
tabs: {...payload}, tabs: {...payload},
currentPath: newCurrent.path, currentPath: newCurrent.path,
...@@ -343,12 +410,12 @@ const Model: ModelType = { ...@@ -343,12 +410,12 @@ const Model: ModelType = {
} }
} }
let newCurrent = undefined; let newCurrent = undefined;
if(newTabs.panes.length > 0){ if (newTabs.panes.length > 0) {
newCurrent = newTabs.panes[newTabs.panes.length - 1]; newCurrent = newTabs.panes[newTabs.panes.length - 1];
} }
if (newCurrent && (newTabs.activeKey == payload)) { if (newCurrent && (newTabs.activeKey == payload)) {
newTabs.activeKey = newCurrent.key; newTabs.activeKey = newCurrent.key;
}else{ } else {
newTabs.activeKey = undefined; newTabs.activeKey = undefined;
} }
return { return {
...@@ -400,7 +467,7 @@ const Model: ModelType = { ...@@ -400,7 +467,7 @@ const Model: ModelType = {
if (newTabs.panes[i].key == payload.key) { if (newTabs.panes[i].key == payload.key) {
newTabs.panes[i].task = payload; newTabs.panes[i].task = payload;
newTabs.panes[i].isModified = false; newTabs.panes[i].isModified = false;
if(newCurrent.key == payload.key){ if (newCurrent.key == payload.key) {
newCurrent = newTabs.panes[i]; newCurrent = newTabs.panes[i];
} }
} }
...@@ -446,7 +513,7 @@ const Model: ModelType = { ...@@ -446,7 +513,7 @@ const Model: ModelType = {
for (let i = 0; i < newTabs.panes.length; i++) { for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].key == payload.key) { if (newTabs.panes[i].key == payload.key) {
newTabs.panes[i].console.result.result = payload.datas; newTabs.panes[i].console.result.result = payload.datas;
if(newCurrent.key == payload.key){ if (newCurrent.key == payload.key) {
newCurrent.console = newTabs.panes[i].console; newCurrent.console = newTabs.panes[i].console;
} }
break; break;
...@@ -463,27 +530,27 @@ const Model: ModelType = { ...@@ -463,27 +530,27 @@ const Model: ModelType = {
...state, ...state,
cluster: [...payload], cluster: [...payload],
}; };
},saveSessionCluster(state, {payload}) { }, saveSessionCluster(state, {payload}) {
return { return {
...state, ...state,
sessionCluster: [...payload], sessionCluster: [...payload],
}; };
},saveClusterConfiguration(state, {payload}) { }, saveClusterConfiguration(state, {payload}) {
return { return {
...state, ...state,
clusterConfiguration: [...payload], clusterConfiguration: [...payload],
}; };
},saveDataBase(state, {payload}) { }, saveDataBase(state, {payload}) {
return { return {
...state, ...state,
database: [...payload], database: [...payload],
}; };
},saveEnv(state, {payload}) { }, saveEnv(state, {payload}) {
return { return {
...state, ...state,
env: [...payload], env: [...payload],
}; };
},saveChart(state, {payload}) { }, saveChart(state, {payload}) {
let newTabs = state?.tabs; let newTabs = state?.tabs;
let newCurrent = state?.current; let newCurrent = state?.current;
for (let i = 0; i < newTabs.panes.length; i++) { for (let i = 0; i < newTabs.panes.length; i++) {
...@@ -505,7 +572,7 @@ const Model: ModelType = { ...@@ -505,7 +572,7 @@ const Model: ModelType = {
for (let i = 0; i < newTabs.panes.length; i++) { for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].task.id == payload.id) { if (newTabs.panes[i].task.id == payload.id) {
newTabs.panes[i].task.step = payload.step; newTabs.panes[i].task.step = payload.step;
if(newCurrent.key == newTabs.panes[i].key){ if (newCurrent.key == newTabs.panes[i].key) {
newCurrent = newTabs.panes[i]; newCurrent = newTabs.panes[i];
} }
} }
...@@ -522,7 +589,7 @@ const Model: ModelType = { ...@@ -522,7 +589,7 @@ const Model: ModelType = {
for (let i = 0; i < newTabs.panes.length; i++) { for (let i = 0; i < newTabs.panes.length; i++) {
if (newTabs.panes[i].task.id == payload.id) { if (newTabs.panes[i].task.id == payload.id) {
newTabs.panes[i].task.jobInstanceId = payload.jobInstanceId; newTabs.panes[i].task.jobInstanceId = payload.jobInstanceId;
if(newCurrent.key == newTabs.panes[i].key){ if (newCurrent.key == newTabs.panes[i].key) {
newCurrent = newTabs.panes[i]; newCurrent = newTabs.panes[i];
} }
} }
...@@ -546,7 +613,7 @@ const Model: ModelType = { ...@@ -546,7 +613,7 @@ const Model: ModelType = {
newCurrent.task.alias = payload.name; newCurrent.task.alias = payload.name;
} }
} }
if(newTabs.panes.length == 0){ if (newTabs.panes.length == 0) {
return { return {
...state, ...state,
current: undefined, current: undefined,
......
import request from 'umi-request'; import request from 'umi-request';
import {CAParam, StudioParam} from "@/components/Studio/StudioEdit/data"; import {CAParam, StudioMetaStoreParam, StudioParam} from "@/components/Studio/StudioEdit/data";
export async function executeSql(params: StudioParam) { export async function executeSql(params: StudioParam) {
return request<API.Result>('/api/studio/executeSql', { return request<API.Result>('/api/studio/executeSql', {
...@@ -46,7 +46,7 @@ export async function getJobPlan(params: StudioParam) { ...@@ -46,7 +46,7 @@ export async function getJobPlan(params: StudioParam) {
}); });
} }
export async function getJobData(jobId:string) { export async function getJobData(jobId: string) {
return request<API.Result>('/api/studio/getJobData', { return request<API.Result>('/api/studio/getJobData', {
method: 'GET', method: 'GET',
params: { params: {
...@@ -72,3 +72,21 @@ export async function getLineage(params: CAParam) { ...@@ -72,3 +72,21 @@ export async function getLineage(params: CAParam) {
}, },
}); });
} }
export async function getMSCatalogs(params: StudioMetaStoreParam) {
return request<API.Result>('/api/studio/getMSCatalogs', {
method: 'POST',
data: {
...params,
},
});
}
export async function getMSTables(params: StudioMetaStoreParam) {
return request<API.Result>('/api/studio/getMSTables', {
method: 'POST',
data: {
...params,
},
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment