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

Add SUNDB #1376

Open
wants to merge 6 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Chat2DB Pro supports all the following databases, including the most requested R

## ⏬ Download and Install Chat2DB(Pro)

- Download installation package from [official website](https://chat2db-ai.com/download)
- Download installation package from [official website](https://chat2db.ai/download)
- Double click package to install


Expand Down
120 changes: 120 additions & 0 deletions chat2db-client/src/components/ConnectionEdit/config/dataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2080,4 +2080,124 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [
extendInfo: [],
type: DatabaseTypeCode.MONGODB
},
//SUNDB
{
baseInfo: {
items: [
{
defaultValue: '@localhost',
inputType: InputType.INPUT,
labelNameCN: '名称',
labelNameEN: 'Name',
name: 'alias',
required: true,
styles: {
width: '100%',
}
},
envItem,
{
defaultValue: 'localhost',
inputType: InputType.INPUT,
labelNameCN: '主机',
labelNameEN: 'Host',
name: 'host',
required: true,
styles: {
width: '70%',
}
},
{
defaultValue: '22581',
inputType: InputType.INPUT,
labelNameCN: '端口',
labelNameEN: 'Port',
name: 'port',
labelTextAlign: 'right',
required: true,
styles: {
width: '30%',
labelWidthEN: '40px',
labelWidthCN: '40px',
labelAlign: 'right'
}
},
{
defaultValue: AuthenticationType.USERANDPASSWORD,
inputType: InputType.SELECT,
labelNameCN: '身份验证',
labelNameEN: 'Authentication',
name: 'authenticationType',
required: true,
selects: [
{
items: [
{
defaultValue: 'root',
inputType: InputType.INPUT,
labelNameCN: '用户名',
labelNameEN: 'User',
name: 'user',
required: true,
styles: {
width: '100%',
}
},
{
defaultValue: '',
inputType: InputType.PASSWORD,
labelNameCN: '密码',
labelNameEN: 'Password',
name: 'password',
required: true,
styles: {
width: '100%',
}
},
],
label: 'User&Password',
value: AuthenticationType.USERANDPASSWORD,
},
{
label: 'NONE',
value: AuthenticationType.NONE,
items: [],

},
],
styles: {
width: '50%',
}
},
{
defaultValue: '',
inputType: InputType.INPUT,
labelNameCN: '数据库',
labelNameEN: 'Database',
name: 'database',
required: false,
styles: {
width: '100%',
}
},
{
defaultValue: 'jdbc:sundb://localhost:22581/sundb',
inputType: InputType.INPUT,
labelNameCN: 'URL',
labelNameEN: 'URL',
name: 'url',
required: true,
styles: {
width: '100%',
}
},

],
pattern: /jdbc:sundb:\/\/(.*):(\d+)(\/(\w+))?/,
template: 'jdbc:sundb://{host}:{port}/{database}',
},
ssh: sshConfig,
extendInfo: [],
type: DatabaseTypeCode.SUNDB
},
];
1 change: 1 addition & 0 deletions chat2db-client/src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export enum DatabaseTypeCode {
PRESTO = "PRESTO",
HIVE = "HIVE",
KINGBASE = "KINGBASE",
SUNDB = "SUNDB",
}

export enum ConsoleStatus {
Expand Down
14 changes: 7 additions & 7 deletions chat2db-client/src/constants/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,13 @@ export const databaseMap: {
// port: 27017,
icon: '\uec21',
},
// [DatabaseTypeCode.REDIS]: {
// name: 'Redis',
// img: moreDBLogo,
// code: DatabaseTypeCode.REDIS,
// // port: 6379,
// icon: '\ue6a2',
// },
[DatabaseTypeCode.SUNDB]: {
name: 'SUNDB',
img: moreDBLogo,
code: DatabaseTypeCode.SUNDB,
// port: 27017,
icon: '\uec21',
},
};

export const databaseTypeList = Object.keys(databaseMap).map((keys) => {
Expand Down
35 changes: 35 additions & 0 deletions chat2db-server/chat2db-plugins/chat2db-sundb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-plugins</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>

<dependencies>
<dependency>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-spi</artifactId>
</dependency>
</dependencies>

<artifactId>chat2db-sundb</artifactId>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<!--The properties configuration file will be placed together with the compiled class file-->
<include>**/*.json</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package ai.chat2db.plugin.sundb;

import java.sql.*;

import ai.chat2db.spi.DBManage;
import ai.chat2db.spi.jdbc.DefaultDBManage;
import ai.chat2db.spi.sql.Chat2DBContext;
import ai.chat2db.spi.sql.ConnectInfo;
import ai.chat2db.spi.sql.SQLExecutor;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

public class SUNDBDBManage extends DefaultDBManage implements DBManage {
private String format(String tableName) {
return "\"" + tableName + "\"";
}
private static String ROUTINES_SQL
= "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE";
private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'";

private static String TRIGGER_SQL
= "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY "
+ "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'";
@Override
public String exportDatabase(Connection connection, String databaseName, String schemaName, boolean containData) throws SQLException {
StringBuilder sqlBuilder = new StringBuilder();
exportTables(connection, sqlBuilder, schemaName, containData);
exportViews(connection, schemaName, sqlBuilder);
exportProcedures(connection, schemaName, sqlBuilder);
exportTriggers(connection,schemaName, sqlBuilder);
return sqlBuilder.toString();
}

private void exportTables(Connection connection, StringBuilder sqlBuilder, String schemaName, boolean containData) throws SQLException {
String sql =String.format("SELECT TABLE_NAME FROM ALL_TABLES where OWNER='%s' and TABLESPACE_NAME='MEM_DATA_TBS'", schemaName);
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
while (resultSet.next()) {
String tableName = resultSet.getString("TABLE_NAME");
exportTable(connection, tableName, schemaName, sqlBuilder, containData);
}
}
}


private void exportTable(Connection connection, String tableName, String schemaName, StringBuilder sqlBuilder, boolean containData) throws SQLException {
/*tring sql = """
SELECT
(SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments,
(SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl
FROM dual;
""";
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(String.format(sql, tableName, tableName, schemaName))) {
String formatSchemaName = format(schemaName);
String formatTableName = format(tableName);
if (resultSet.next()) {
sqlBuilder.append("DROP TABLE IF EXISTS ").append(formatSchemaName).append(".").append(formatTableName)
.append(";").append("\n")
.append(resultSet.getString("ddl")).append("\n");
String comment = resultSet.getString("comments");
if (StringUtils.isNotBlank(comment)) {
sqlBuilder.append("COMMENT ON TABLE ").append(formatSchemaName).append(".").append(formatTableName)
.append(" IS ").append("'").append(comment).append("';");
}
exportTableColumnComment(connection, schemaName, tableName, sqlBuilder);
}
if (containData) {
exportTableData(connection, schemaName, tableName, sqlBuilder);
}
}*/
}

private void exportTableColumnComment(Connection connection, String schemaName, String tableName, StringBuilder sqlBuilder) throws SQLException {
String sql =String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" +
"where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName,tableName);
try(ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
while (resultSet.next()) {
String columnName = resultSet.getString("COLNAME");
String comment = resultSet.getString("COMMENT$");
sqlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName))
.append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n");
}
}
}


private void exportViews(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException {
try (ResultSet resultSet = connection.getMetaData().getTables(null, schemaName, null, new String[]{"VIEW"})) {
while (resultSet.next()) {
String viewName = resultSet.getString("TABLE_NAME");
exportView(connection, viewName, schemaName, sqlBuilder);
}
}
}

private void exportView(Connection connection, String viewName, String schemaName, StringBuilder sqlBuilder) throws SQLException {
/*String sql = String.format("SELECT DBMS_METADATA.GET_DDL('VIEW','%s','%s') as ddl FROM DUAL;", viewName, schemaName);
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
if (resultSet.next()) {
sqlBuilder.append(resultSet.getString("ddl")).append("\n");
}
}*/
}

private void exportProcedures(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException {
try (ResultSet resultSet = connection.getMetaData().getProcedures(null, schemaName, null)) {
while (resultSet.next()) {
String procedureName = resultSet.getString("PROCEDURE_NAME");
exportProcedure(connection, schemaName,procedureName, sqlBuilder);
}
}
}

private void exportProcedure(Connection connection, String schemaName, String procedureName, StringBuilder sqlBuilder) throws SQLException {
String sql = String.format(ROUTINES_SQL,"PROC", schemaName,procedureName);
try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql)) {
if (resultSet.next()) {
sqlBuilder.append(resultSet.getString("TEXT")).append("\n");
}
}
}

private void exportTriggers(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException {
/*String sql =String.format(TRIGGER_SQL_LIST, schemaName);
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
while (resultSet.next()) {
String triggerName = resultSet.getString("TRIGGER_NAME");
exportTrigger(connection,schemaName, triggerName, sqlBuilder);
}
}*/
}

private void exportTrigger(Connection connection, String schemaName, String triggerName, StringBuilder sqlBuilder) throws SQLException {
String sql = String.format(TRIGGER_SQL, schemaName,triggerName);
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
if (resultSet.next()) {
sqlBuilder.append(resultSet.getString("TRIGGER_BODY")).append("\n");
}
}
}

@Override
public void connectDatabase(Connection connection, String database) {
ConnectInfo connectInfo = Chat2DBContext.getConnectInfo();
if (ObjectUtils.anyNull(connectInfo) || StringUtils.isEmpty(connectInfo.getSchemaName())) {
return;
}
String schemaName = connectInfo.getSchemaName();
try {
SQLExecutor.getInstance().execute(connection, "SET SCHEMA \"" + schemaName + "\"");
} catch (SQLException e) {
e.printStackTrace();
}
}

@Override
public void dropTable(Connection connection, String databaseName, String schemaName, String tableName) {
String sql = "DROP TABLE IF EXISTS \"" + schemaName + "\".\"" +tableName + "\"";
SQLExecutor.getInstance().execute(connection,sql, resultSet -> null);
}
}