PowerModeler/source/sqlQueryExecutor.cpp

895 lines
32 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "global.h"
#include "sqlQueryExecutor.h"
#include "logger.h"
#include <QSqlDatabase>
#include <QDateTime>
SqlQueryExecutor& SqlQueryExecutor::instance()
{
//采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致
static SqlQueryExecutor instance;
return instance;
}
SqlQueryExecutor::SqlQueryExecutor()
{}
SqlQueryExecutor::~SqlQueryExecutor()
{}
//单条SQL语句执行接口
QSqlQuery SqlQueryExecutor::executeSQL(const QString& connectionName, const QString& strSQL, const QVariantHash& params, bool useTranscation)
{
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
throw DatabaseException(db.lastError());
}
//事务
bool transactionStarted = false;
if(useTranscation)
{
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
throw DatabaseException(db.lastError());
}
transactionStarted = true;
}
QSqlQuery sqlQuery(db);
try
{
if(!sqlQuery.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, sqlQuery.lastError().databaseText()));
throw DatabaseException(db.lastError());
}
//绑定参数
for(auto it = params.constBegin(); it != params.constEnd(); it++)
{
sqlQuery.bindValue(it.key(), it.value());
}
if (!sqlQuery.exec())
{
LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText()));
throw DatabaseException(sqlQuery.lastError());
}
// 提交事务(如果已开启)
if(transactionStarted && !db.commit())
{
throw DatabaseException(db.lastError());
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
}
catch (const DatabaseException& e)
{
// 错误处理:回滚事务(如果已开启)
if(transactionStarted)
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
}
throw; // 重新抛出异常
}
return sqlQuery;
}
//多条批量SQL语句执行接口
QSqlQuery SqlQueryExecutor::executeBatchSQL(const QString& connectionName, const QStringList& sqlStatements, const QList<QVariantHash>& paramsList, bool useTranscation)
{
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
throw DatabaseException(db.lastError());
}
//参数数量校验
if(!paramsList.isEmpty() && sqlStatements.size() != paramsList.size())
{
LOG_ERROR("SQL", QString("SQL statement does not match the number of parameters"));
throw DatabaseException(QSqlError("SQL statement does not match the number of parameters"));
}
//事务
bool transactionStarted = false;
if(useTranscation)
{
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
throw DatabaseException(db.lastError());
}
transactionStarted = true;
}
QSqlQuery lastQuery(db);
try
{
for(int i = 0; i < sqlStatements.size(); i++)
{
const QString& strSQL = sqlStatements.at(i);
const QVariantHash& params = paramsList.isEmpty() ? QVariantHash() : paramsList.at(i);
QSqlQuery sqlQuery(db);
if(!sqlQuery.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, sqlQuery.lastError().databaseText()));
throw DatabaseException(db.lastError());
}
//绑定参数
for(auto it = params.constBegin(); it != params.constEnd(); it++)
{
sqlQuery.bindValue(it.key(), it.value());
}
if (!sqlQuery.exec())
{
LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText()));
throw DatabaseException(sqlQuery.lastError());
}
lastQuery = std::move(sqlQuery);
}
// 提交事务(如果已开启)
if(transactionStarted && !db.commit())
{
throw DatabaseException(db.lastError());
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
}
catch (const DatabaseException& e)
{
// 错误处理:回滚事务(如果已开启)
if(transactionStarted)
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
}
throw; // 重新抛出异常
}
return lastQuery;
}
//获取表的字段类型信息目前只针对PostgerSQL
QHash<QString, QString> SqlQueryExecutor::getFiledType(const QString& connectionName, const QString& table, const QString& schema)
{
QHash<QString, QString> fieldTypes;
QString strSQL = QString(
"SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) "
"FROM pg_catalog.pg_attribute a "
"JOIN pg_catalog.pg_class c ON a.attrelid = c.oid "
"JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid "
"WHERE c.relname = LOWER(:table_name) "
"AND n.nspname = LOWER(:schema_name) "
"AND a.attnum > 0 AND NOT a.attisdropped;"
);
QVariantHash params;
params.insert(":table_name", table);
params.insert(":schema_name", schema);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
while(query.next())
fieldTypes.insert(query.value(0).toString(), query.value(1).toString());
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性原始数据类型失败"));
}
return fieldTypes;
}
//具体业务查询接口
const QVector<Model> SqlQueryExecutor::getModels(const QString& connectionName)
{
QVector<Model> models;
QString strSQL = "SELECT id, model_type, model_name, remark FROM basic.model_type ORDER BY id ASC";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
while(query.next())
{
int id = query.value(0).toInt();
QString type = query.value(1).toString();
QString name = query.value(2).toString();
QString remark = query.value(3).toString();
QVector<int> groups = getModelGroups(connectionName, id);
models.emplace_back(id, name, type, remark, groups);
}
}
catch (const DatabaseException& e)
{
emit errorOccurred(QString::fromWCharArray(L"获取模型信息失败,详情可见日志文件"));
}
return models; //编译器的RVO/NRVO会自动优化、避免临时拷贝
}
QVector<int> SqlQueryExecutor::getModelGroups(const QString& connectionName, int modelID)
{
QVector<int> groups;
QString strSQL = "SELECT attribute_group_id FROM basic.model_group WHERE model_type_id = " + QString::number(modelID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
while(query.next())
{
groups.append(query.value(0).toInt());
}
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取模型所含属性组名称失败id:%1").arg(QString::number(modelID)));
return groups;
}
return groups;
}
bool SqlQueryExecutor::addModel(const QString& connectionName, Model& model)
{
//属于批量操作需要开启事务因为后续插入映射表时需要先插入进model_type记录的自增id所以无法在一个接口函数中执行所以事务放在在接口外部执行
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
return false;
}
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
int modelID = -1;
//先向model_type中插入一条记录
QString strSQL = "INSERT INTO basic.model_type (model_type, model_name, remark) VALUES "
"(:type, :name, :remark)";
QVariantHash params;
params.insert(":type", model.type);
params.insert(":name", model.name);
params.insert(":remark", model.remark);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
modelID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id
model.id = modelID;
}
catch (const DatabaseException& e)
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
//然后向model_group中插入记录采用批量接口
/*QStringList sqlStatements;
QList<QVariantHash> paramsList;
for(int groupID : model.groups)
{
sqlStatements << "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES "
"(:modelID, :groupID)";
params.clear();
params.insert(":modelID", modelID);
params.insert(":groupID", groupID);
paramsList << params;
}
try
{
executeBatchSQL(connectionName, sqlStatements, paramsList);
}
catch (const DatabaseException& e)
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}*/
QSqlQuery query(db);
strSQL = "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES (?, ?)";
if(!query.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, query.lastError().databaseText()));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
QVariantList modelIds, groupIds;
for(int groupID : model.groups)
{
modelIds << modelID;
groupIds << groupID;
}
query.addBindValue(modelIds);
query.addBindValue(groupIds);
if( !query.execBatch() )
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
if(!db.commit()) // 提交
{
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
return true;
}
bool SqlQueryExecutor::modelNameExistsInDB(const QString& connectionName, const QString& name)
{
bool exists = false;
QString strSQL = "SELECT id FROM basic.model_type WHERE model_name = \'" + name + "\'";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
exists = true;
}
catch (const DatabaseException& e)
{
exists = true;
}
return exists;
}
bool SqlQueryExecutor::modelTypeExistsInDB(const QString& connectionName, const QString& type)
{
bool exists = false;
QString strSQL = "SELECT id FROM basic.model_type WHERE model_type = \'" + type + "\'";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
exists = true;
}
catch (const DatabaseException& e)
{
exists = true;
}
return exists;
}
bool SqlQueryExecutor::removeModel(const QString& connectionName, int modelID)
{
//数据库中有级联删除只需要从model_type中删除即可
QString strSQL = "DELETE FROM basic.model_type WHERE id = :id"/* + QString::number(modelID)*/;
QVariantHash params;
params.insert(":id", modelID);
try
{
executeSQL(connectionName, strSQL, params, true);
}
catch (const DatabaseException& e)
{
return false;
}
return true;
}
bool SqlQueryExecutor::addModleGrpus(const QString& connectionName, int modelID, QVector<int> groups)
{
//属于批量操作,需要开启事务
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
return false;
}
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
QSqlQuery query(db);
QString strSQL = "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES (?, ?)";
if(!query.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, query.lastError().databaseText()));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
QVariantList modelIds, groupIds;
for(int groupID : groups)
{
modelIds << modelID;
groupIds << groupID;
}
query.addBindValue(modelIds);
query.addBindValue(groupIds);
if( !query.execBatch() )
{
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, query.lastError().databaseText()));
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
if(!db.commit()) // 提交
{
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
return true;
}
const QVector<AttributeGroup> SqlQueryExecutor::getAttributeGroup(const QString& connectionName)
{
QVector<AttributeGroup> groupList;
QString strSQL = "SELECT id, group_type, group_name, remark, is_public FROM basic.attribute_group ORDER BY id ASC";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
while(query.next())
{
int id = query.value(0).toInt();
QString type = query.value(1).toString();
QString name = query.value(2).toString();
QString remark = query.value(3).toString();
bool isPublic = query.value(4).toBool();
groupList.emplace_back(id,name,type,remark,isPublic); //直接调用构造函数,避免拷贝
}
}
catch (const DatabaseException& e)
{
emit errorOccurred(QString::fromWCharArray(L"获取属性组别信息失败,详情可见日志文件"));
}
return groupList;
}
const QString SqlQueryExecutor::getAttributeGroupName(const QString& connectionName, int groupID)
{
QString name = "";
QString strSQL = "SELECT group_name FROM basic.attribute_group WHERE id = :id";
QVariantHash params;
params.insert(":id", groupID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
if(query.next())
name = query.value(0).toString();
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性组名称失败id:%1").arg(QString::number(groupID)));
}
return name;
}
const AttributeGroup SqlQueryExecutor::getAttributeGroupData(const QString& connectionName, int groupID)
{
AttributeGroup group;
QString strSQL = "SELECT group_type, group_name, remark, is_public FROM basic.attribute_group WHERE id = :id";
QVariantHash params;
params.insert(":id", groupID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
if(query.next())
{
QString type = query.value(0).toString();
QString name = query.value(1).toString();
QString remark = query.value(2).toString();
bool isPublic = query.value(3).toBool();
return AttributeGroup(groupID,name,type,remark,isPublic);
}
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性组信息失败id:%1").arg(QString::number(groupID)));
}
return group;
}
bool SqlQueryExecutor::isPublicAttributeGroup(const QString& connectionName, int groupID)
{
bool isPublic = false;
QString strSQL = "SELECT is_public FROM basic.attribute_group WHERE id = :id";
QVariantHash params;
params.insert(":id", groupID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
if(query.next())
isPublic = query.value(0).toBool();
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性组类型失败id:%1").arg(QString::number(groupID)));
}
return isPublic;
}
bool SqlQueryExecutor::removeAttributeGroup(const QString& connectionName, int modelID, int groupID)
{
//从model_attribute和model_group两个map表中对相关记录进行删除(暂时不做属性本体的删除)
QStringList sqlStatements;
QList<QVariantHash> paramsList;
sqlStatements << "DELETE FROM basic.model_attribute WHERE model_type_id = :modelID AND attribute_group_id = :groupID";
QVariantHash params;
params.insert(":modelID", modelID);
params.insert(":groupID", groupID);
paramsList << params;
sqlStatements << "DELETE FROM basic.model_group WHERE model_type_id = :modelID AND attribute_group_id = :groupID";
params.clear();
params.insert(":modelID", modelID);
params.insert(":groupID", groupID);
paramsList << params;
try
{
executeBatchSQL(connectionName, sqlStatements, paramsList, true);
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"删除属性组失败model_type_id:%1attribute_group_id:%2").arg(modelID, groupID));
return false;
}
return true;
}
int SqlQueryExecutor::getAttributeCount(const QString& connectionName, int modelID, int groupID)
{
int count = 0;
//利用短路机制当attribute_group_id!=-1时括号整体为false需要进行内部条件判断=-1时整体为true忽略整体也就忽略了attribute_group_id的条件判断
QString strSQL = QString("SELECT COUNT(*) FROM basic.model_attribute WHERE model_type_id = %1 AND (attribute_group_id = %2 OR %2 = -1)").arg(modelID).arg(groupID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
count = query.value(0).toInt();
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
}
return count;
}
int SqlQueryExecutor::getAllAttributeCount(const QString& connectionName)
{
int count = 0;
QString strSQL = QString("SELECT COUNT(*) FROM basic.attribute");
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
count = query.value(0).toInt();
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
}
return count;
}
bool SqlQueryExecutor::getAttributeInfo(const QString& connectionName, const QString& columns, Attribute& attribute)
{
QString strSQL = QString("SELECT %1 FROM basic.attribute WHERE id = %2").arg(columns).arg(attribute.id);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
{
attribute.type = query.value(0).toString();
attribute.name = query.value(1).toString();
attribute.dataTypeID = query.value(2).toInt();
attribute.dataLength = query.value(3).toInt();
attribute.defaultValue = query.value(4).toString();
attribute.isVisible = query.value(5).toInt();
}
else
return false;
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
return false;
}
return true;
}
int SqlQueryExecutor::attributeTypeExistsInDB(const QString& connectionName, const QString& type)
{
int id = -1;
QString strSQL = "SELECT id FROM basic.attribute WHERE attribute = \'" + type + "\'";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
id = query.value(0).toInt();
}
catch (const DatabaseException& e)
{
id = -1;
}
return id;
}
bool SqlQueryExecutor::attributeTypeUseByModelGroup(const QString& connectionName, int attributeID, int modelID, int groupID)
{
QString strSQL = "SELECT id FROM basic.model_attribute WHERE model_type_id = :modelID AND attribute_group_id = :groupID AND attribute_id = :attributeID";
QVariantHash params;
params.insert(":modelID", modelID);
params.insert(":groupID", groupID);
params.insert(":attributeID", attributeID);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
if(query.next())
return true;
}
catch (const DatabaseException& e)
{
return false;
}
return false;
}
bool SqlQueryExecutor::batchInsertAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<Attribute> attributes)
{
//属于批量操作,需要开启事务
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
return false;
}
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
//先插入进属性表attribute因为要获取插入后的自增id所以采用逐条插入的方法
QList<qint64> attributeIDList;
for(const Attribute& attribute : attributes)
{
if(attribute.id != -1) //新建条目是通过选择已有的记录完成,此类不再做重复插入
{
attributeIDList.append(attribute.id);
continue;
}
qint64 attributeID = QDateTime::currentDateTime().toMSecsSinceEpoch();
//先向model_type中插入一条记录
QString strSQL = "INSERT INTO basic.attribute (attribute, attribute_name, data_type_id, length_precision, default_value, is_visible) VALUES "
"(:type, :name, :dataType, :dataLength, :defaultValue, :isVisible)";
QVariantHash params;
params.insert(":type", attribute.type);
params.insert(":name", attribute.name);
params.insert(":dataType", attribute.dataTypeID);
params.insert(":dataLength", attribute.dataLength);
params.insert(":defaultValue", attribute.defaultValue);
params.insert(":isVisible", attribute.isVisible);
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
attributeID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id
}
catch (const DatabaseException& e)
{
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
attributeIDList.append(attributeID);
}
//插入数据到关联表
QSqlQuery linkQuery(db);
QString strSQL = "";
bool isPublicGroup = isPublicAttributeGroup(connectionName, attributeGroupID);
if(isPublicGroup)
strSQL = "INSERT INTO basic.model_attribute_public (attribute_group_id, attribute_id) VALUES (?, ?)";
else
strSQL = "INSERT INTO basic.model_attribute (model_type_id, attribute_group_id, attribute_id) VALUES (?, ?, ?)";
if(!linkQuery.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, linkQuery.lastError().databaseText()));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
QVariantList modelIds, groupIds, attributeIds;
for(const qint64& attributeID : attributeIDList)
{
if(!isPublicGroup)
modelIds << modelID;
groupIds << attributeGroupID;
attributeIds << attributeID;
}
if(!isPublicGroup)
linkQuery.addBindValue(modelIds);
linkQuery.addBindValue(groupIds);
linkQuery.addBindValue(attributeIds);
if( !linkQuery.execBatch() )
{
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, linkQuery.lastError().databaseText()));
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
if(!db.commit()) // 提交
{
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
return true;
}
bool SqlQueryExecutor::batchDeleteAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<int> attributes)
{
//属于批量操作,需要开启事务
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
return false;
}
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
QSqlQuery query(db);
QString strSQL = "";
bool isPublicGroup = isPublicAttributeGroup(connectionName, attributeGroupID);
if(isPublicGroup)
strSQL = "DELETE FROM basic.model_attribute_public WHERE attribute_group_id = ? AND attribute_id = ?";
else
strSQL = "DELETE FROM basic.model_attribute WHERE model_type_id = ? AND attribute_group_id = ? AND attribute_id = ?";
if(!query.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, query.lastError().databaseText()));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
QVariantList modelIds, groupIds, attributeIds;
for(const int& attributeID : attributes)
{
if(!isPublicGroup)
modelIds << modelID;
groupIds << attributeGroupID;
attributeIds << attributeID;
}
if(!isPublicGroup)
query.addBindValue(modelIds);
query.addBindValue(groupIds);
query.addBindValue(attributeIds);
if( !query.execBatch() )
{
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, query.lastError().databaseText()));
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
if(!db.commit()) // 提交
{
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
return true;
}
bool SqlQueryExecutor::batchUpdateAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<Attribute> attributes)
{
//属于批量操作,需要开启事务
QSqlDatabase db = QSqlDatabase::database(connectionName);
if(!db.isOpen())
{
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
return false;
}
if(!db.transaction())
{
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
QSqlQuery query(db);
QString strSQL = "UPDATE basic.attribute SET attribute = ?, attribute_name = ?, data_type_id = ?, length_precision = ?, default_value = ?, is_visible = ? WHERE id = ?";
if(!query.prepare(strSQL))
{
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, query.lastError().databaseText()));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
QVariantList types, names, dataTypes, lengths, defaults, isVisibles, ids;
for(const Attribute& attribute : attributes)
{
types << attribute.type;
names << attribute.name;
dataTypes << attribute.dataTypeID;
lengths << attribute.dataLength;
defaults << attribute.defaultValue;
isVisibles << attribute.isVisible;
ids << attribute.id;
}
query.addBindValue(types);
query.addBindValue(names);
query.addBindValue(dataTypes);
query.addBindValue(lengths);
query.addBindValue(defaults);
query.addBindValue(isVisibles);
query.addBindValue(ids);
if( !query.execBatch() )
{
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, query.lastError().databaseText()));
LOG_INFO("DB", QString("DB Rollback"));
if(!db.rollback()) // 回滚
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
}
return false;
}
if(!db.commit()) // 提交
{
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
return false;
}
return true;
}