void MainWindow::on_actionRefresh_triggered()
{
if (db.isEmpty()) {
MessageDialog::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("没有任何连接"));
return;
}
// 遍历所有数据库连接
for (const QString& connectName : db) {
QSqlDatabase m_db = QSqlDatabase::database(connectName);
if (!m_db.isOpen()) {
MessageDialog::warning(this, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("连接已关闭: %1").arg(connectName));
continue;
}
// 获取连接类型
int dbType = connectType.contains(connectName) ? connectType[connectName] : 1;
bool isKingbase = (dbType == 3); // Kingbase数据库
bool isDM8 = (dbType == 2); // DM8数据库
bool isOracle = (dbType == 1); // Oracle数据库
// 查找连接对应的用户节点和连接节点
QString user;
QTreeWidgetItem* connectItem = findConnectionItem(connectName, user);
if (!connectItem || user.isEmpty()) {
MessageDialog::warning(this, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("未找到连接节点或用户: %1").arg(connectName));
continue;
}
// ================= 多模式数据库处理 (Kingbase 或 DM8) =================
if (isKingbase || isDM8) {
QStringList schemaNames;
// 根据不同数据库类型获取模式列表
if (isKingbase) {
schemaNames = getKingbaseSchemas(m_db);
} else { // DM8
schemaNames = getDM8Schemas(m_db);
}
foreach (const QString& schemaName, schemaNames) {
// 跳过系统模式
if (shouldSkipSchema(schemaName, isKingbase, isDM8)) continue;
// 查找或创建模式节点
QTreeWidgetItem* schemaNode = findOrCreateSchemaNode(
connectItem, schemaName, isKingbase, isDM8);
// 切换至对应模式
if (!switchToSchema(m_db, schemaName, isKingbase, isDM8)) {
continue;
}
// 刷新当前模式下的所有对象类型
refreshAllObjectsInSchema(connectName, user, schemaName,
isKingbase, isDM8, schemaNode, m_db);
}
}
// ================= 单模式数据库处理 (Oracle) =================
else if (isOracle) {
QString schemaName = user; // 使用用户名作为模式名
QTreeWidgetItem* schemaNode = findOrCreateSchemaNode(
connectItem, schemaName, false, false);
// 刷新Oracle模式下的所有对象
refreshAllObjectsInSchema(connectName, user, schemaName,
false, false, schemaNode, m_db);
}
}
MessageDialog::information(this,
QString::fromLocal8Bit("刷新完成"),
QString::fromLocal8Bit("所有数据库连接已同步最新状态"));
}
// 查找连接节点工具函数
QTreeWidgetItem* MainWindow::findConnectionItem(const QString& connectName, QString& user)
{
for (int i = 0; i < ui->connectionTree->topLevelItemCount(); ++i) {
QTreeWidgetItem* userNode = ui->connectionTree->topLevelItem(i);
if (!userNode) continue;
user = userNode->data(0, Qt::UserRole).toString();
for (int j = 0; j < userNode->childCount(); ++j) {
QTreeWidgetItem* child = userNode->child(j);
if (!child) continue;
QString nameFromNode = child->data(0, Qt::UserRole).toString();
if (nameFromNode == connectName) {
return child;
}
}
}
return nullptr;
}
// 获取Kingbase模式列表
QStringList MainWindow::getKingbaseSchemas(QSqlDatabase& db)
{
QStringList schemas;
QSqlQuery query(db);
// 尝试创建扩展(如果不存在)
query.exec("create extension if not exists dbms_metadata");
if (query.exec("SELECT nspname FROM pg_namespace "
"WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema' "
"ORDER BY nspname")) {
while (query.next()) {
schemas << query.value(0).toString();
}
}
return schemas;
}
// 获取DM8模式列表
QStringList MainWindow::getDM8Schemas(QSqlDatabase& db)
{
QStringList schemas;
QSqlQuery query(db);
// 使用DBA_OBJECTS或ALL_OBJECTS获取模式列表
QString queryStr = "SELECT DISTINCT OWNER FROM DBA_OBJECTS "
"WHERE OWNER NOT IN ('SYS','SYSTEM','SYSAUDITOR','SYSSSO','SYSDBO') "
"ORDER BY OWNER";
if (!query.exec(queryStr)) {
queryStr = "SELECT DISTINCT OWNER FROM ALL_OBJECTS "
"WHERE OWNER NOT IN ('SYS','SYSTEM','SYSAUDITOR','SYSSSO','SYSDBO') "
"ORDER BY OWNER";
query.exec(queryStr);
}
while (query.next()) {
schemas << query.value(0).toString();
}
return schemas;
}
// 判断是否跳过模式
bool MainWindow::shouldSkipSchema(const QString& schemaName, bool isKingbase, bool isDM8)
{
if (isKingbase) {
return (schemaName == "sys" || schemaName == "anon");
} else if (isDM8) {
return (schemaName == "SYS" || schemaName == "SYSTEM" ||
schemaName == "SYSAUDITOR" || schemaName == "SYSSSO" ||
schemaName == "SYSDBO");
}
return false;
}
// 查找或创建模式节点
QTreeWidgetItem* MainWindow::findOrCreateSchemaNode(QTreeWidgetItem* connectItem,
const QString& schemaName,
bool isKingbase,
bool isDM8)
{
QString displayName = QString::fromLocal8Bit("模式:%1").arg(schemaName);
// 查找现有节点
for (int i = 0; i < connectItem->childCount(); ++i) {
QTreeWidgetItem* child = connectItem->child(i);
if (child && child->text(0) == displayName) {
return child;
}
}
// 创建新节点
QTreeWidgetItem* schemaNode = new QTreeWidgetItem(connectItem);
schemaNode->setText(0, displayName);
schemaNode->setData(0, Qt::UserRole, QString::fromLocal8Bit("模式:") + schemaName);
// 设置工具提示
if (isKingbase) {
schemaNode->setToolTip(0, QString::fromLocal8Bit("Kingbase模式 - SET search_path TO %1, public").arg(schemaName));
} else if (isDM8) {
schemaNode->setToolTip(0, QString::fromLocal8Bit("DM8模式 - ALTER SESSION SET CURRENT_SCHEMA = %1").arg(schemaName));
} else {
schemaNode->setToolTip(0, QString::fromLocal8Bit("Oracle用户模式"));
}
// 创建对象分类节点(表、视图、函数等)
createObjectCategoryNodes(schemaNode);
return schemaNode;
}
// 创建对象分类节点
void MainWindow::createObjectCategoryNodes(QTreeWidgetItem* schemaNode)
{
const QStringList categories = {
QString::fromLocal8Bit("表"),
QString::fromLocal8Bit("视图"),
QString::fromLocal8Bit("函数"),
QString::fromLocal8Bit("过程"),
QString::fromLocal8Bit("触发器"),
QString::fromLocal8Bit("序列")
};
foreach (const QString& category, categories) {
QTreeWidgetItem* item = new QTreeWidgetItem(schemaNode);
item->setText(0, category);
item->setData(0, Qt::UserRole, QString::fromLocal8Bit("类型:") + category);
}
}
// 切换到指定模式
bool MainWindow::switchToSchema(QSqlDatabase& db,
const QString& schemaName,
bool isKingbase,
bool isDM8)
{
QString sql;
if (isKingbase) {
sql = QString("SET search_path TO %1, public").arg(schemaName);
} else if (isDM8) {
sql = QString("ALTER SESSION SET CURRENT_SCHEMA = \"%1\"").arg(schemaName);
} else {
// Oracle不需要切换
return true;
}
QSqlQuery query(db);
if (!query.exec(sql)) {
MessageDialog::warning(this, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("无法切换至模式:%1\n错误:%2")
.arg(schemaName)
.arg(query.lastError().text()));
return false;
}
return true;
}
// 刷新模式下的所有对象
void MainWindow::refreshAllObjectsInSchema(const QString& connectName,
const QString& user,
const QString& schemaName,
bool isKingbase,
bool isDM8,
QTreeWidgetItem* schemaNode,
QSqlDatabase& db)
{
// 构建分类节点映射
QMap<QString, QTreeWidgetItem*> categoryMap;
for (int i = 0; i < schemaNode->childCount(); ++i) {
QTreeWidgetItem* child = schemaNode->child(i);
if (child) {
categoryMap[child->text(0)] = child;
}
}
// 刷新每种对象类型
QVector<QPair<QString, QString>> objectTypes = {
{QString::fromLocal8Bit("表"), "TABLE"},
{QString::fromLocal8Bit("视图"), "VIEW"},
{QString::fromLocal8Bit("函数"), "FUNCTION"},
{QString::fromLocal8Bit("过程"), "PROCEDURE"},
{QString::fromLocal8Bit("触发器"), "TRIGGER"},
{QString::fromLocal8Bit("序列"), "SEQUENCE"}
};
foreach (const auto& type, objectTypes) {
if (categoryMap.contains(type.first)) {
refreshObjectType(
connectName,
user,
schemaName,
type.first,
type.second,
isKingbase || isDM8,
categoryMap[type.first],
db,
schemaName
);
}
}
}
// 刷新特定类型的对象
void MainWindow::refreshObjectType(const QString& connectName,
const QString& user,
const QString& schemaName,
const QString& typeName,
const QString& objectType,
bool isMultiSchema, // 指示是否为多模式数据库
QTreeWidgetItem* typeItem,
QSqlDatabase& db,
const QString& objectSchema)
{
// 清空现有节点和缓存
clearExistingItemsAndCache(user, connectName, schemaName, typeName);
// 构建查询
QString queryStr = buildObjectQuery(objectType, isMultiSchema, objectSchema);
// 执行查询
QSqlQuery query(db);
// 多模式数据库需要绑定模式参数
if (isMultiSchema) {
query.prepare(queryStr);
query.addBindValue(objectSchema);
} else {
query.prepare(queryStr);
}
if (!query.exec()) {
handleQueryError(typeName, query.lastError());
return;
}
// 处理查询结果
while (query.next()) {
QString objectName = query.value(0).toString();
QString ddl = getEntityDDL(connectName, objectType, objectName,
isMultiSchema, objectSchema);
// 检查DDL是否有效
if (!isValidDDL(ddl, isMultiSchema)) {
continue;
}
// 更新缓存
updateObjectCache(user, connectName, schemaName, typeName,
objectName, ddl);
// 添加树节点
addObjectToTree(typeItem, objectName);
}
}
// 清除现有项和缓存
void MainWindow::clearExistingItemsAndCache(const QString& user,
const QString& connectName,
const QString& schemaName,
const QString& typeName)
{
// 清空树节点
qDeleteAll(typeItem->takeChildren());
// 清空缓存
QMap<QString, QMap<QString, QMap<QString, QString>>>* cacheMap = nullptr;
if (typeName == QString::fromLocal8Bit("表")) {
cacheMap = &tables;
} else if (typeName == QString::fromLocal8Bit("视图")) {
cacheMap = &views;
} else if (typeName == QString::fromLocal8Bit("函数")) {
cacheMap = &funcs;
} else if (typeName == QString::fromLocal8Bit("过程")) {
cacheMap = &procs;
} else if (typeName == QString::fromLocal8Bit("触发器")) {
cacheMap = &triggers;
} else if (typeName == QString::fromLocal8Bit("序列")) {
cacheMap = &seqs;
}
if (cacheMap &&
cacheMap->contains(user) &&
(*cacheMap)[user].contains(connectName)) {
(*cacheMap)[user][connectName].remove(schemaName);
}
}
// 构建对象查询
QString MainWindow::buildObjectQuery(const QString& objectType,
bool isMultiSchema,
const QString& schemaName)
{
if (isMultiSchema) {
// Kingbase/DM8查询
static QMap<QString, QString> multiSchemaQueries = {
{"TABLE", "SELECT tablename FROM pg_tables WHERE schemaname = ? ORDER BY tablename"},
{"VIEW", "SELECT viewname FROM pg_views WHERE schemaname = ? ORDER BY viewname"},
{"FUNCTION", "SELECT proname FROM pg_proc WHERE pronamespace = "
"(SELECT oid FROM pg_namespace WHERE nspname = ?) ORDER BY proname"},
{"PROCEDURE", "SELECT proname FROM pg_proc WHERE pronamespace = "
"(SELECT oid FROM pg_namespace WHERE nspname = ?) "
"AND prokind = 'p' ORDER BY proname"},
{"TRIGGER", "SELECT tgname FROM pg_trigger WHERE tgrelid IN "
"(SELECT oid FROM pg_class WHERE relnamespace = "
"(SELECT oid FROM pg_namespace WHERE nspname = ?)) ORDER BY tgname"},
{"SEQUENCE", "SELECT sequencename FROM pg_sequences WHERE schemaname = ? ORDER BY sequencename"}
};
return multiSchemaQueries.value(objectType, "");
} else {
// Oracle查询
static QMap<QString, QString> oracleQueries = {
{"TABLE", "SELECT table_name FROM user_tables ORDER BY table_name"},
{"VIEW", "SELECT view_name FROM user_views ORDER BY view_name"},
{"FUNCTION", "SELECT object_name FROM user_objects WHERE object_type = 'FUNCTION' ORDER BY object_name"},
{"PROCEDURE", "SELECT object_name FROM user_objects WHERE object_type = 'PROCEDURE' ORDER BY object_name"},
{"TRIGGER", "SELECT trigger_name FROM user_triggers ORDER BY trigger_name"},
{"SEQUENCE", "SELECT sequence_name FROM user_sequences ORDER BY sequence_name"}
};
return oracleQueries.value(objectType, "");
}
}
// 处理查询错误
void MainWindow::handleQueryError(const QString& typeName, const QSqlError& error)
{
MessageDialog::warning(nullptr, QString::fromLocal8Bit("警告"),
QString::fromLocal8Bit("查询%1失败: %2").arg(typeName).arg(error.text()));
qDebug() << "Query failed:" << typeName << error.text();
}
// 检查DDL是否有效
bool MainWindow::isValidDDL(const QString& ddl, bool isMultiSchema)
{
if (ddl.contains(QString::fromLocal8Bit("获取失败"))) {
return false;
}
// Oracle特定检查
if (!isMultiSchema &&
ddl.contains("DBMS_METADATA.GET_DDL") &&
ddl.contains("Unable to execute statement")) {
return false;
}
return true;
}
// 更新对象缓存
void MainWindow::updateObjectCache(const QString& user,
const QString& connectName,
const QString& schemaName,
const QString& typeName,
const QString& objectName,
const QString& ddl)
{
if (typeName == QString::fromLocal8Bit("表")) {
tables[user][connectName][schemaName].insert(objectName, ddl);
} else if (typeName == QString::fromLocal8Bit("视图")) {
views[user][connectName][schemaName].insert(objectName, ddl);
} else if (typeName == QString::fromLocal8Bit("函数")) {
funcs[user][connectName][schemaName].insert(objectName, ddl);
} else if (typeName == QString::fromLocal8Bit("过程")) {
procs[user][connectName][schemaName].insert(objectName, ddl);
} else if (typeName == QString::fromLocal8Bit("触发器")) {
triggers[user][connectName][schemaName].insert(objectName, ddl);
} else if (typeName == QString::fromLocal8Bit("序列")) {
seqs[user][connectName][schemaName].insert(objectName, ddl);
}
}
void Main能否在此基础上继续生成未完成的内容
最新发布