|
|
|
|
@ -1,145 +1,145 @@
|
|
|
|
|
package org.dromara.ai.service.impl;
|
|
|
|
|
|
|
|
|
|
import org.dromara.ai.mapper.SQLServerDatabaseMetaMapper;
|
|
|
|
|
import org.dromara.ai.test.ChatRequest;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
import java.util.LinkedHashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Author xins
|
|
|
|
|
* @Date 2025/7/8 9:25
|
|
|
|
|
* @Description:
|
|
|
|
|
*/
|
|
|
|
|
@Service
|
|
|
|
|
public class DatabaseMetaServiceImpl {
|
|
|
|
|
|
|
|
|
|
@Autowired
|
|
|
|
|
private SQLServerDatabaseMetaMapper databaseMetaMapper;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取格式化的数据库结构描述
|
|
|
|
|
*/
|
|
|
|
|
public String getFormattedSchema() {
|
|
|
|
|
List<Map<String, Object>> allColumns = databaseMetaMapper.getAllTablesStructure();
|
|
|
|
|
|
|
|
|
|
Map<String, List<Map<String, Object>>> tables = allColumns.stream()
|
|
|
|
|
.collect(Collectors.groupingBy(
|
|
|
|
|
col -> (String) col.get("tableName"),
|
|
|
|
|
LinkedHashMap::new,
|
|
|
|
|
Collectors.toList()
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder("SQL Server 数据库结构:\n\n");
|
|
|
|
|
|
|
|
|
|
for (Map.Entry<String, List<Map<String, Object>>> entry : tables.entrySet()) {
|
|
|
|
|
String tableName = entry.getKey();
|
|
|
|
|
List<String> primaryKeys = databaseMetaMapper.getPrimaryKeys(tableName);
|
|
|
|
|
|
|
|
|
|
sb.append("- 表名: ").append(tableName).append("\n");
|
|
|
|
|
sb.append(" 主键: ").append(String.join(", ", primaryKeys)).append("\n");
|
|
|
|
|
sb.append(" 字段:\n");
|
|
|
|
|
|
|
|
|
|
for (Map<String, Object> column : entry.getValue()) {
|
|
|
|
|
sb.append(" * ")
|
|
|
|
|
.append(column.get("columnName"))
|
|
|
|
|
.append(" (").append(column.get("dataType"));
|
|
|
|
|
|
|
|
|
|
if (column.get("maxLength") != null && (short)column.get("maxLength") > 0) {
|
|
|
|
|
sb.append(", 长度: ").append(column.get("maxLength"));
|
|
|
|
|
}
|
|
|
|
|
if (column.get("precision") != null && (short)column.get("precision") > 0) {
|
|
|
|
|
sb.append(", 精度: ").append(column.get("precision"));
|
|
|
|
|
}
|
|
|
|
|
if (column.get("scale") != null && (short)column.get("scale") > 0) {
|
|
|
|
|
sb.append(", 小数位: ").append(column.get("scale"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sb.append(column.get("nullable").equals(1) ? ", 可空" : ", 非空");
|
|
|
|
|
|
|
|
|
|
if (!((String)column.get("defaultValue")).isEmpty()) {
|
|
|
|
|
sb.append(", 默认值: ").append(column.get("defaultValue"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!((String)column.get("description")).isEmpty()) {
|
|
|
|
|
sb.append(", 描述: ").append(column.get("description"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sb.append(")\n");
|
|
|
|
|
}
|
|
|
|
|
sb.append("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return sb.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String generateSQL(String naturalLanguageQuery) {
|
|
|
|
|
// 1. 获取数据库结构
|
|
|
|
|
String schemaDescription = this.getFormattedSchema();
|
|
|
|
|
|
|
|
|
|
// 2. 构建 AI 提示
|
|
|
|
|
String prompt = String.format(
|
|
|
|
|
"你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
|
|
|
|
|
"请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
|
|
|
|
|
"---\n%s\n---\n\n" +
|
|
|
|
|
"要求:\n" +
|
|
|
|
|
"1. 只返回 SQL 语句,不要包含解释\n" +
|
|
|
|
|
"2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT)\n" +
|
|
|
|
|
"3. 考虑性能优化\n" +
|
|
|
|
|
"4. 使用合适的索引提示(如果需要)\n" +
|
|
|
|
|
"5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
|
|
|
|
|
"6. 使用 ANSI 标准的 JOIN 语法",
|
|
|
|
|
schemaDescription, naturalLanguageQuery
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
ChatRequest chatRequest = new ChatRequest();
|
|
|
|
|
chatRequest.setPrompt(prompt);
|
|
|
|
|
|
|
|
|
|
return prompt;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取表的结构信息
|
|
|
|
|
*/
|
|
|
|
|
public Map<String, Object> getTableDetail(String tableName) {
|
|
|
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
result.put("tableName", tableName);
|
|
|
|
|
result.put("primaryKeys", databaseMetaMapper.getPrimaryKeys(tableName));
|
|
|
|
|
result.put("columns", databaseMetaMapper.getTableStructure(tableName));
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public String generateSQL1(String naturalLanguageQuery) {
|
|
|
|
|
// 1. 获取数据库结构
|
|
|
|
|
String schemaDescription = this.getFormattedSchema();
|
|
|
|
|
|
|
|
|
|
// 2. 构建 AI 提示
|
|
|
|
|
String prompt = String.format(
|
|
|
|
|
"你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
|
|
|
|
|
"请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
|
|
|
|
|
"---\n%s\n---\n\n" +
|
|
|
|
|
"要求:\n" +
|
|
|
|
|
"1. 只返回 SQL 语句,不要包含解释\n" +
|
|
|
|
|
"2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT)\n" +
|
|
|
|
|
"3. 考虑性能优化\n" +
|
|
|
|
|
"4. 使用合适的索引提示(如果需要)\n" +
|
|
|
|
|
"5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
|
|
|
|
|
"6. 使用 ANSI 标准的 JOIN 语法",
|
|
|
|
|
schemaDescription, naturalLanguageQuery
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return prompt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//package org.dromara.ai.service.impl;
|
|
|
|
|
//
|
|
|
|
|
//import org.dromara.ai.mapper.SQLServerDatabaseMetaMapper;
|
|
|
|
|
//import org.dromara.ai.test.ChatRequest;
|
|
|
|
|
//import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
//import org.springframework.stereotype.Service;
|
|
|
|
|
//
|
|
|
|
|
//import java.util.LinkedHashMap;
|
|
|
|
|
//import java.util.List;
|
|
|
|
|
//import java.util.Map;
|
|
|
|
|
//import java.util.stream.Collectors;
|
|
|
|
|
//
|
|
|
|
|
///**
|
|
|
|
|
// * @Author xins
|
|
|
|
|
// * @Date 2025/7/8 9:25
|
|
|
|
|
// * @Description:
|
|
|
|
|
// */
|
|
|
|
|
//@Service
|
|
|
|
|
//public class DatabaseMetaServiceImpl {
|
|
|
|
|
//
|
|
|
|
|
// @Autowired
|
|
|
|
|
// private SQLServerDatabaseMetaMapper databaseMetaMapper;
|
|
|
|
|
//
|
|
|
|
|
// /**
|
|
|
|
|
// * 获取格式化的数据库结构描述
|
|
|
|
|
// */
|
|
|
|
|
// public String getFormattedSchema() {
|
|
|
|
|
// List<Map<String, Object>> allColumns = databaseMetaMapper.getAllTablesStructure();
|
|
|
|
|
//
|
|
|
|
|
// Map<String, List<Map<String, Object>>> tables = allColumns.stream()
|
|
|
|
|
// .collect(Collectors.groupingBy(
|
|
|
|
|
// col -> (String) col.get("tableName"),
|
|
|
|
|
// LinkedHashMap::new,
|
|
|
|
|
// Collectors.toList()
|
|
|
|
|
// ));
|
|
|
|
|
//
|
|
|
|
|
// StringBuilder sb = new StringBuilder("SQL Server 数据库结构:\n\n");
|
|
|
|
|
//
|
|
|
|
|
// for (Map.Entry<String, List<Map<String, Object>>> entry : tables.entrySet()) {
|
|
|
|
|
// String tableName = entry.getKey();
|
|
|
|
|
// List<String> primaryKeys = databaseMetaMapper.getPrimaryKeys(tableName);
|
|
|
|
|
//
|
|
|
|
|
// sb.append("- 表名: ").append(tableName).append("\n");
|
|
|
|
|
// sb.append(" 主键: ").append(String.join(", ", primaryKeys)).append("\n");
|
|
|
|
|
// sb.append(" 字段:\n");
|
|
|
|
|
//
|
|
|
|
|
// for (Map<String, Object> column : entry.getValue()) {
|
|
|
|
|
// sb.append(" * ")
|
|
|
|
|
// .append(column.get("columnName"))
|
|
|
|
|
// .append(" (").append(column.get("dataType"));
|
|
|
|
|
//
|
|
|
|
|
// if (column.get("maxLength") != null && (short)column.get("maxLength") > 0) {
|
|
|
|
|
// sb.append(", 长度: ").append(column.get("maxLength"));
|
|
|
|
|
// }
|
|
|
|
|
// if (column.get("precision") != null && (short)column.get("precision") > 0) {
|
|
|
|
|
// sb.append(", 精度: ").append(column.get("precision"));
|
|
|
|
|
// }
|
|
|
|
|
// if (column.get("scale") != null && (short)column.get("scale") > 0) {
|
|
|
|
|
// sb.append(", 小数位: ").append(column.get("scale"));
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// sb.append(column.get("nullable").equals(1) ? ", 可空" : ", 非空");
|
|
|
|
|
//
|
|
|
|
|
// if (!((String)column.get("defaultValue")).isEmpty()) {
|
|
|
|
|
// sb.append(", 默认值: ").append(column.get("defaultValue"));
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// if (!((String)column.get("description")).isEmpty()) {
|
|
|
|
|
// sb.append(", 描述: ").append(column.get("description"));
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// sb.append(")\n");
|
|
|
|
|
// }
|
|
|
|
|
// sb.append("\n");
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// return sb.toString();
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// public String generateSQL(String naturalLanguageQuery) {
|
|
|
|
|
// // 1. 获取数据库结构
|
|
|
|
|
// String schemaDescription = this.getFormattedSchema();
|
|
|
|
|
//
|
|
|
|
|
// // 2. 构建 AI 提示
|
|
|
|
|
// String prompt = String.format(
|
|
|
|
|
// "你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
|
|
|
|
|
// "请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
|
|
|
|
|
// "---\n%s\n---\n\n" +
|
|
|
|
|
// "要求:\n" +
|
|
|
|
|
// "1. 只返回 SQL 语句,不要包含解释\n" +
|
|
|
|
|
// "2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT)\n" +
|
|
|
|
|
// "3. 考虑性能优化\n" +
|
|
|
|
|
// "4. 使用合适的索引提示(如果需要)\n" +
|
|
|
|
|
// "5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
|
|
|
|
|
// "6. 使用 ANSI 标准的 JOIN 语法",
|
|
|
|
|
// schemaDescription, naturalLanguageQuery
|
|
|
|
|
// );
|
|
|
|
|
//
|
|
|
|
|
// ChatRequest chatRequest = new ChatRequest();
|
|
|
|
|
// chatRequest.setPrompt(prompt);
|
|
|
|
|
//
|
|
|
|
|
// return prompt;
|
|
|
|
|
//
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// /**
|
|
|
|
|
// * 获取表的结构信息
|
|
|
|
|
// */
|
|
|
|
|
// public Map<String, Object> getTableDetail(String tableName) {
|
|
|
|
|
// Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
// result.put("tableName", tableName);
|
|
|
|
|
// result.put("primaryKeys", databaseMetaMapper.getPrimaryKeys(tableName));
|
|
|
|
|
// result.put("columns", databaseMetaMapper.getTableStructure(tableName));
|
|
|
|
|
// return result;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// public String generateSQL1(String naturalLanguageQuery) {
|
|
|
|
|
// // 1. 获取数据库结构
|
|
|
|
|
// String schemaDescription = this.getFormattedSchema();
|
|
|
|
|
//
|
|
|
|
|
// // 2. 构建 AI 提示
|
|
|
|
|
// String prompt = String.format(
|
|
|
|
|
// "你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
|
|
|
|
|
// "请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
|
|
|
|
|
// "---\n%s\n---\n\n" +
|
|
|
|
|
// "要求:\n" +
|
|
|
|
|
// "1. 只返回 SQL 语句,不要包含解释\n" +
|
|
|
|
|
// "2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT)\n" +
|
|
|
|
|
// "3. 考虑性能优化\n" +
|
|
|
|
|
// "4. 使用合适的索引提示(如果需要)\n" +
|
|
|
|
|
// "5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
|
|
|
|
|
// "6. 使用 ANSI 标准的 JOIN 语法",
|
|
|
|
|
// schemaDescription, naturalLanguageQuery
|
|
|
|
|
// );
|
|
|
|
|
//
|
|
|
|
|
// return prompt;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
//}
|
|
|
|
|
|