Skip to content
Merged
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 @@ -4,6 +4,7 @@
import ai.chat2db.spi.DBManage;
import ai.chat2db.spi.jdbc.DefaultDBManage;
import ai.chat2db.spi.model.AsyncContext;
import ai.chat2db.spi.model.Procedure;
import ai.chat2db.spi.sql.Chat2DBContext;
import ai.chat2db.spi.sql.ConnectInfo;
import ai.chat2db.spi.sql.SQLExecutor;
Expand All @@ -18,6 +19,10 @@
@Slf4j
public class DB2DBManage extends DefaultDBManage implements DBManage {

private static String PROCEDURE_SQL = "SELECT COUNT(*) AS procedure_count\n" +
"FROM SYSCAT.PROCEDURES\n" +
"WHERE PROCNAME = '%s';";

@Override
public void exportDatabase(Connection connection, String databaseName, String schemaName, AsyncContext asyncContext) throws SQLException {
exportTables(connection, databaseName, schemaName, asyncContext);
Expand Down Expand Up @@ -92,6 +97,44 @@ private void exportTriggers(Connection connection, String schemaName, AsyncConte
}
}

@Override
public void updateProcedure(Connection connection, String databaseName, String schemaName, Procedure procedure) throws SQLException {
try {
connection.setAutoCommit(false);
String procedureBody = procedure.getProcedureBody();
boolean isCreateOrReplace = procedureBody.trim().toUpperCase().startsWith("CREATE OR REPLACE ");

if (procedureBody == null || !procedureBody.trim().toUpperCase().startsWith("CREATE")) {
throw new IllegalArgumentException("No CREATE statement found.");
}

String procedureNewName = getSchemaOrProcedureName(procedureBody, schemaName, procedure);
if (!procedureNewName.equals(procedure.getProcedureName())) {
procedureBody = procedureBody.replace(procedure.getProcedureName(), procedureNewName);
}
String checkProcedureSQL = String.format(PROCEDURE_SQL, procedure.getProcedureName().toUpperCase());
String finalProcedureBody = procedureBody;
SQLExecutor.getInstance().execute(connection, checkProcedureSQL, resultSet -> {
if (resultSet.next()) {
int count = resultSet.getInt(1);
if (count >= 1) {
if (isCreateOrReplace) {
SQLExecutor.getInstance().execute(connection, finalProcedureBody, resultSet2 -> {});
} else {
throw new SQLException("Procedure with the same name already exists.");
}
}
}
});
SQLExecutor.getInstance().execute(connection, finalProcedureBody, resultSet -> {});
} catch (Exception e) {
connection.rollback();
throw new RuntimeException(e);
} finally {
connection.setAutoCommit(true);
}
}

@Override
public void connectDatabase(Connection connection, String database) {
ConnectInfo connectInfo = Chat2DBContext.getConnectInfo();
Expand All @@ -113,12 +156,20 @@ public void dropTable(Connection connection, String databaseName, String schemaN
}

@Override
public void copyTable(Connection connection, String databaseName, String schemaName, String tableName, String newTableName,boolean copyData) throws SQLException {
public void copyTable(Connection connection, String databaseName, String schemaName, String tableName, String newTableName, boolean copyData) throws SQLException {
String sql = "CREATE TABLE " + newTableName + " LIKE " + tableName + " INCLUDING INDEXES";
SQLExecutor.getInstance().execute(connection, sql, resultSet -> null);
if(copyData){
if (copyData) {
sql = "INSERT INTO " + newTableName + " SELECT * FROM " + tableName;
SQLExecutor.getInstance().execute(connection, sql, resultSet -> null);
}
}

private static String getSchemaOrProcedureName(String procedureBody, String schemaName, Procedure procedure) {
if (procedureBody.toLowerCase().contains(schemaName.toLowerCase())) {
return procedure.getProcedureName();
} else {
return schemaName + "." + procedure.getProcedureName();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import ai.chat2db.spi.DBManage;
import ai.chat2db.spi.jdbc.DefaultDBManage;
import ai.chat2db.spi.model.AsyncContext;
import ai.chat2db.spi.model.Procedure;
import ai.chat2db.spi.sql.Chat2DBContext;
import ai.chat2db.spi.sql.ConnectInfo;
import ai.chat2db.spi.sql.SQLExecutor;
Expand All @@ -29,6 +30,12 @@ private String format(String tableName) {
= "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'";

private static String PROCEDURE_SQL = "SELECT COUNT(*)\n" +
"FROM DBA_OBJECTS\n" +
"WHERE OBJECT_TYPE = 'PROCEDURE' \n" +
"AND OWNER = '%s' \n" +
"AND OBJECT_NAME = '%s'";

@Override
public void exportDatabase(Connection connection, String databaseName, String schemaName, AsyncContext asyncContext) throws SQLException {
exportTables(connection, databaseName, schemaName, asyncContext);
Expand All @@ -50,11 +57,11 @@ private void exportTables(Connection connection, String databaseName, String sch

public void exportTable(Connection connection, String databaseName, String tableName, String schemaName, AsyncContext asyncContext) throws SQLException {
String 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;
""";
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);
Expand All @@ -79,7 +86,7 @@ public void exportTable(Connection connection, String databaseName, String table

private void exportTableColumnComment(Connection connection, String schemaName, String tableName, AsyncContext asyncContext) 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);
"where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName, tableName);
try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) {
while (resultSet.next()) {
StringBuilder sqlBuilder = new StringBuilder();
Expand Down Expand Up @@ -154,6 +161,44 @@ private void exportTrigger(Connection connection, String schemaName, String trig
}
}

@Override
public void updateProcedure(Connection connection, String databaseName, String schemaName, Procedure procedure) throws SQLException {
try {
connection.setAutoCommit(false);
String procedureBody = procedure.getProcedureBody();
boolean isCreateOrReplace = procedureBody.trim().toUpperCase().startsWith("CREATE OR REPLACE ");

if (procedureBody == null || !procedureBody.trim().toUpperCase().startsWith("CREATE")) {
throw new IllegalArgumentException("No CREATE statement found.");
}

String procedureNewName = getSchemaOrProcedureName(procedureBody, schemaName, procedure);
if (!procedureNewName.equals(procedure.getProcedureName())) {
procedureBody = procedureBody.replace(procedure.getProcedureName(), procedureNewName);
}
String checkProcedureSQL = String.format(PROCEDURE_SQL, schemaName.toUpperCase(),procedure.getProcedureName().toUpperCase());
String finalProcedureBody = procedureBody;
SQLExecutor.getInstance().execute(connection, checkProcedureSQL, resultSet -> {
if (resultSet.next()) {
int count = resultSet.getInt(1);
if (count >= 1) {
if (isCreateOrReplace) {
SQLExecutor.getInstance().execute(connection, finalProcedureBody, resultSet2 -> {});
} else {
throw new SQLException("Procedure with the same name already exists.");
}
}
}
});
SQLExecutor.getInstance().execute(connection, finalProcedureBody, resultSet -> {});
} catch (Exception e) {
connection.rollback();
throw new RuntimeException(e);
} finally {
connection.setAutoCommit(true);
}
}

@Override
public void connectDatabase(Connection connection, String database) {
ConnectInfo connectInfo = Chat2DBContext.getConnectInfo();
Expand All @@ -173,4 +218,12 @@ public void dropTable(Connection connection, String databaseName, String schemaN
String sql = "DROP TABLE IF EXISTS " + tableName;
SQLExecutor.getInstance().execute(connection, sql, resultSet -> null);
}

private static String getSchemaOrProcedureName(String procedureBody, String schemaName, Procedure procedure) {
if (procedureBody.toLowerCase().contains(schemaName.toLowerCase())) {
return procedure.getProcedureName();
} else {
return schemaName + "." + procedure.getProcedureName();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import ai.chat2db.spi.DBManage;
import ai.chat2db.spi.jdbc.DefaultDBManage;
import ai.chat2db.spi.model.Function;
import ai.chat2db.spi.model.Procedure;
import ai.chat2db.spi.sql.Chat2DBContext;
import ai.chat2db.spi.sql.ConnectInfo;
import ai.chat2db.spi.sql.SQLExecutor;
Expand All @@ -14,6 +16,34 @@
@Slf4j
public class KingBaseDBManage extends DefaultDBManage implements DBManage {

@Override
public void updateProcedure(Connection connection, String databaseName, String schemaName, Procedure procedure) throws SQLException {
try {
connection.setAutoCommit(false);
String procedureBody = procedure.getProcedureBody();
String parameterSignature = extractParameterSignature(procedureBody);

if (procedureBody == null || !procedureBody.trim().toUpperCase().startsWith("CREATE")) {
throw new IllegalArgumentException("No CREATE statement found.");
}

String procedureNewName = getSchemaOrProcedureName(procedureBody, schemaName, procedure);
if (!procedureNewName.equals(procedure.getProcedureName())) {
procedureBody = procedureBody.replace(procedure.getProcedureName(), procedureNewName);
}
String dropSql = "DROP PROCEDURE IF EXISTS " + procedureNewName + parameterSignature;
SQLExecutor.getInstance().execute(connection, dropSql, resultSet -> {
});
SQLExecutor.getInstance().execute(connection, procedureBody, resultSet -> {
});
} catch (Exception e) {
connection.rollback();
throw new RuntimeException(e);
} finally {
connection.setAutoCommit(true);
}
}

@Override
public void connectDatabase(Connection connection, String database) {
try {
Expand Down Expand Up @@ -62,18 +92,68 @@ public String replaceDatabaseInJdbcUrl(String url, String newDatabase) {

@Override
public void dropTable(Connection connection, String databaseName, String schemaName, String tableName) {
String sql = "drop table if exists " +tableName;
SQLExecutor.getInstance().execute(connection,sql, resultSet -> null);
String sql = "drop table if exists " + tableName;
SQLExecutor.getInstance().execute(connection, sql, resultSet -> null);
}

@Override
public void deleteProcedure(Connection connection, String databaseName, String schemaName, Procedure procedure) {
String procedureBody = procedure.getProcedureBody();
String parameterSignature = extractParameterSignature(procedureBody);
String procedureNewName = getSchemaOrProcedureName(procedure.getProcedureBody(), schemaName, procedure);
String sql = "DROP PROCEDURE " + procedureNewName + parameterSignature;
SQLExecutor.getInstance().execute(connection, sql, resultSet -> {});
}

@Override
public void copyTable(Connection connection, String databaseName, String schemaName, String tableName, String newTableName,boolean copyData) throws SQLException {
public void deleteFunction(Connection connection, String databaseName, String schemaName, Function function) {
String functionBody = function.getFunctionBody();
String parameterSignature = extractParameterSignature(functionBody);
String functionNewName = getSchemaOrFunctionName(functionBody, schemaName, function);
String sql = "DROP FUNCTION" + functionNewName + parameterSignature;
SQLExecutor.getInstance().execute(connection, sql, resultSet -> {});
}

@Override
public void copyTable(Connection connection, String databaseName, String schemaName, String tableName, String newTableName, boolean copyData) throws SQLException {
String sql = "";
if(copyData){
if (copyData) {
sql = "CREATE TABLE " + newTableName + " AS TABLE " + tableName + " WITH DATA";
}else {
} else {
sql = "CREATE TABLE " + newTableName + " AS TABLE " + tableName + " WITH NO DATA";
}
SQLExecutor.getInstance().execute(connection, sql, resultSet -> null);
}

private String extractParameterSignature(String input) {
int depth = 0, start = -1;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '(') {
if (depth++ == 0) start = i;
} else if (c == ')' && --depth == 0 && start != -1) {
return "(" + input.substring(start + 1, i) + ")";
}
}
if (depth == 0) {
return "";
}
return null;
}

private static String getSchemaOrProcedureName(String procedureBody, String schemaName, Procedure procedure) {
if (procedureBody.toLowerCase().contains(schemaName.toLowerCase())) {
return procedure.getProcedureName();
} else {
return schemaName + "." + procedure.getProcedureName();
}
}

private static String getSchemaOrFunctionName(String functionBody, String schemaName, Function function) {
if (functionBody.toLowerCase().contains(schemaName.toLowerCase())) {
return function.getFunctionName();
} else {
return schemaName + "." + function.getFunctionName();
}
}
}
Loading