2025-03-14 16:06:20 +08:00
# include "global.h"
# include "sqlQueryExecutor.h"
# include "logger.h"
# include <QSqlDatabase>
2025-04-01 14:37:41 +08:00
# include <QDateTime>
2025-03-14 16:06:20 +08:00
SqlQueryExecutor & SqlQueryExecutor : : instance ( )
{
//采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致
static SqlQueryExecutor instance ;
return instance ;
}
SqlQueryExecutor : : SqlQueryExecutor ( )
{ }
SqlQueryExecutor : : ~ SqlQueryExecutor ( )
{ }
2025-03-17 18:36:10 +08:00
//单条SQL语句执行接口
2025-04-01 14:37:41 +08:00
QSqlQuery SqlQueryExecutor : : executeSQL ( const QString & connectionName , const QString & strSQL , const QVariantHash & params , bool useTranscation )
2025-03-14 16:06:20 +08:00
{
2025-04-01 14:37:41 +08:00
QSqlDatabase db = QSqlDatabase : : database ( connectionName ) ;
2025-03-14 16:06:20 +08:00
if ( ! db . isOpen ( ) )
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Database not open. connectionName: %1 " ) . arg ( connectionName ) ) ;
2025-03-14 16:06:20 +08:00
throw DatabaseException ( db . lastError ( ) ) ;
}
2025-03-17 14:46:52 +08:00
//事务
bool transactionStarted = false ;
if ( useTranscation )
{
if ( ! db . transaction ( ) )
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Start transaction failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 14:46:52 +08:00
throw DatabaseException ( db . lastError ( ) ) ;
}
transactionStarted = true ;
}
2025-03-14 16:06:20 +08:00
QSqlQuery sqlQuery ( db ) ;
2025-03-17 14:46:52 +08:00
try
2025-03-14 16:06:20 +08:00
{
2025-03-17 14:46:52 +08:00
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 ( ) ) ;
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Commit transaction failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 14:46:52 +08:00
}
2025-03-14 16:06:20 +08:00
}
2025-03-17 14:46:52 +08:00
catch ( const DatabaseException & e )
2025-03-14 16:06:20 +08:00
{
2025-03-17 14:46:52 +08:00
// 错误处理:回滚事务(如果已开启)
if ( transactionStarted )
{
2025-04-01 16:45:30 +08:00
LOG_INFO ( " DB " , QString ( " DB Rollback " ) ) ;
2025-03-17 14:46:52 +08:00
if ( ! db . rollback ( ) ) // 回滚失败时记录警告
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Rollback failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 14:46:52 +08:00
}
}
throw ; // 重新抛出异常
2025-03-14 16:06:20 +08:00
}
return sqlQuery ;
}
2025-03-17 18:36:10 +08:00
//多条批量SQL语句执行接口
2025-04-01 14:37:41 +08:00
QSqlQuery SqlQueryExecutor : : executeBatchSQL ( const QString & connectionName , const QStringList & sqlStatements , const QList < QVariantHash > & paramsList , bool useTranscation )
2025-03-17 18:36:10 +08:00
{
2025-04-01 14:37:41 +08:00
QSqlDatabase db = QSqlDatabase : : database ( connectionName ) ;
2025-03-17 18:36:10 +08:00
if ( ! db . isOpen ( ) )
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Database not open. connectionName: %1 " ) . arg ( connectionName ) ) ;
2025-03-17 18:36:10 +08:00
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 ( ) )
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Start transaction failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 18:36:10 +08:00
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 ) ;
2025-04-17 15:34:43 +08:00
}
// 提交事务(如果已开启)
if ( transactionStarted & & ! db . commit ( ) )
{
throw DatabaseException ( db . lastError ( ) ) ;
LOG_ERROR ( " DB " , QString ( " Commit transaction failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 18:36:10 +08:00
}
}
catch ( const DatabaseException & e )
{
// 错误处理:回滚事务(如果已开启)
if ( transactionStarted )
{
2025-04-01 14:37:41 +08:00
LOG_INFO ( " DB " , QString ( " DB Rollback " ) ) ;
2025-03-17 18:36:10 +08:00
if ( ! db . rollback ( ) ) // 回滚失败时记录警告
{
2025-04-01 14:37:41 +08:00
LOG_ERROR ( " DB " , QString ( " Rollback failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-17 18:36:10 +08:00
}
}
throw ; // 重新抛出异常
}
return lastQuery ;
}
2025-03-31 16:01:49 +08:00
//获取表的字段类型信息( 目前只针对PostgerSQL)
2025-04-01 14:37:41 +08:00
QHash < QString , QString > SqlQueryExecutor : : getFiledType ( const QString & connectionName , const QString & table , const QString & schema )
2025-03-31 16:01:49 +08:00
{
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
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL , params ) ;
2025-03-31 16:01:49 +08:00
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 ;
}
2025-03-14 16:06:20 +08:00
//具体业务查询接口
2025-04-01 14:37:41 +08:00
const QVector < Model > SqlQueryExecutor : : getModels ( const QString & connectionName )
2025-03-14 16:06:20 +08:00
{
QVector < Model > models ;
QString strSQL = " SELECT id, model_type, model_name, remark FROM basic.model_type ORDER BY id ASC " ;
try
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL ) ;
2025-03-14 16:06:20 +08:00
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 ( ) ;
2025-04-01 14:37:41 +08:00
QVector < int > groups = getModelGroups ( connectionName , id ) ;
2025-03-14 16:06:20 +08:00
models . emplace_back ( id , name , type , remark , groups ) ;
}
}
catch ( const DatabaseException & e )
{
emit errorOccurred ( QString : : fromWCharArray ( L " 获取模型信息失败,详情可见日志文件 " ) ) ;
}
return models ; //编译器的RVO/NRVO会自动优化、避免临时拷贝
}
2025-04-29 17:54:44 +08:00
int SqlQueryExecutor : : getModelCount ( const QString & connectionName )
{
int count = 0 ;
QString strSQL = QString ( " SELECT COUNT(*) FROM basic.model_type " ) ;
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 ;
}
2025-04-01 14:37:41 +08:00
QVector < int > SqlQueryExecutor : : getModelGroups ( const QString & connectionName , int modelID )
2025-03-14 16:06:20 +08:00
{
QVector < int > groups ;
2025-05-07 17:34:27 +08:00
QString strSQL = " SELECT attribute_group_id FROM basic.model_group WHERE model_type_id = " + QString : : number ( modelID ) + " ORDER BY id ASC " ;
2025-03-14 16:06:20 +08:00
try
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL ) ;
2025-03-14 16:06:20 +08:00
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 )
{
2025-03-17 18:36:10 +08:00
//属于批量操作, 需要开启事务, 因为后续插入映射表时需要先插入进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 ;
}
2025-03-14 16:06:20 +08:00
int modelID = - 1 ;
//先向model_type中插入一条记录
2025-03-17 14:46:52 +08:00
QString strSQL = " INSERT INTO basic.model_type (model_type, model_name, remark) VALUES "
2025-03-14 16:06:20 +08:00
" (:type, :name, :remark) " ;
QVariantHash params ;
params . insert ( " :type " , model . type ) ;
params . insert ( " :name " , model . name ) ;
2025-03-17 14:46:52 +08:00
params . insert ( " :remark " , model . remark ) ;
2025-03-14 16:06:20 +08:00
try
{
2025-03-17 14:46:52 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL , params ) ;
2025-03-14 16:06:20 +08:00
modelID = query . lastInsertId ( ) . toInt ( ) ; //lasatInsertId()会返回最近插入行的自增id
model . id = modelID ;
}
catch ( const DatabaseException & e )
{
2025-04-01 14:37:41 +08:00
LOG_INFO ( " DB " , QString ( " DB Rollback " ) ) ;
2025-03-17 18:36:10 +08:00
if ( ! db . rollback ( ) ) // 回滚失败时记录警告
{
LOG_ERROR ( " DB " , QString ( " Rollback failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
}
2025-03-14 16:06:20 +08:00
return false ;
}
2025-03-17 18:36:10 +08:00
//然后向model_group中插入记录, 采用批量接口
2025-04-18 18:44:26 +08:00
/*QStringList sqlStatements;
2025-03-17 18:36:10 +08:00
QList < QVariantHash > paramsList ;
2025-03-14 16:06:20 +08:00
for ( int groupID : model . groups )
{
2025-03-17 18:36:10 +08:00
sqlStatements < < " INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES "
" (:modelID, :groupID) " ;
2025-03-14 16:06:20 +08:00
params . clear ( ) ;
params . insert ( " :modelID " , modelID ) ;
2025-03-17 14:46:52 +08:00
params . insert ( " :groupID " , groupID ) ;
2025-03-17 18:36:10 +08:00
paramsList < < params ;
}
try
{
executeBatchSQL ( connectionName , sqlStatements , paramsList ) ;
}
catch ( const DatabaseException & e )
2025-04-18 18:44:26 +08:00
{
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 ( ) )
2025-03-17 18:36:10 +08:00
{
2025-04-01 14:37:41 +08:00
LOG_INFO ( " DB " , QString ( " DB Rollback " ) ) ;
2025-03-17 18:36:10 +08:00
if ( ! db . rollback ( ) ) // 回滚失败时记录警告
2025-03-14 16:06:20 +08:00
{
2025-03-17 18:36:10 +08:00
LOG_ERROR ( " DB " , QString ( " Rollback failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
2025-03-14 16:06:20 +08:00
}
2025-03-17 18:36:10 +08:00
return false ;
}
if ( ! db . commit ( ) ) // 提交
{
LOG_ERROR ( " DB " , QString ( " Commit transaction failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
return false ;
2025-03-14 16:06:20 +08:00
}
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 ;
}
2025-03-24 18:13:06 +08:00
bool SqlQueryExecutor : : removeModel ( const QString & connectionName , int modelID )
2025-03-14 18:08:43 +08:00
{
2025-04-17 15:34:43 +08:00
//数据库中有级联删除, 只需要从model_type中删除即可
2025-03-17 14:46:52 +08:00
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 ;
2025-03-14 18:08:43 +08:00
}
2025-03-14 16:06:20 +08:00
2025-04-18 18:44:26 +08:00
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 ;
}
2025-04-01 14:37:41 +08:00
const QVector < AttributeGroup > SqlQueryExecutor : : getAttributeGroup ( const QString & connectionName )
2025-03-14 16:06:20 +08:00
{
QVector < AttributeGroup > groupList ;
QString strSQL = " SELECT id, group_type, group_name, remark, is_public FROM basic.attribute_group ORDER BY id ASC " ;
try
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL ) ;
2025-03-14 16:06:20 +08:00
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 ;
}
2025-04-02 15:57:00 +08:00
const QString SqlQueryExecutor : : getAttributeGroupName ( const QString & connectionName , int groupID )
2025-03-14 16:06:20 +08:00
{
2025-04-02 15:57:00 +08:00
QString name = " " ;
2025-03-17 17:20:10 +08:00
QString strSQL = " SELECT group_name FROM basic.attribute_group WHERE id = :id " ;
QVariantHash params ;
params . insert ( " :id " , groupID ) ;
2025-03-14 16:06:20 +08:00
try
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL , params ) ;
2025-03-14 16:06:20 +08:00
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 ;
}
2025-03-24 18:13:06 +08:00
2025-04-02 15:57:00 +08:00
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 ;
}
2025-04-22 17:45:37 +08:00
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 ;
}
2025-04-17 15:34:43 +08:00
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:%1, attribute_group_id:%2 " ) . arg ( modelID , groupID ) ) ;
return false ;
}
return true ;
}
2025-04-01 16:45:30 +08:00
int SqlQueryExecutor : : getAttributeCount ( const QString & connectionName , int modelID , int groupID )
2025-03-24 18:13:06 +08:00
{
int count = 0 ;
2025-04-28 14:25:45 +08:00
//利用短路机制, 当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 ) ;
2025-03-24 18:13:06 +08:00
try
{
2025-04-01 14:37:41 +08:00
QSqlQuery query = executeSQL ( connectionName , strSQL ) ;
2025-03-24 18:13:06 +08:00
if ( query . next ( ) )
count = query . value ( 0 ) . toInt ( ) ;
}
catch ( const DatabaseException & e )
{
LOG_ERROR ( " SQL " , QString : : fromWCharArray ( L " 获取属性数量失败 " ) ) ;
}
return count ;
}
2025-04-01 14:37:41 +08:00
2025-04-11 17:14:17 +08:00
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 ;
}
2025-04-08 20:02:38 +08:00
bool SqlQueryExecutor : : getAttributeInfo ( const QString & connectionName , const QString & columns , Attribute & attribute )
2025-04-01 16:45:30 +08:00
{
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 ( ) ;
2025-04-27 16:24:13 +08:00
attribute . isVisible = query . value ( 5 ) . toInt ( ) ;
2025-04-01 16:45:30 +08:00
}
else
return false ;
}
catch ( const DatabaseException & e )
{
LOG_ERROR ( " SQL " , QString : : fromWCharArray ( L " 获取属性数量失败 " ) ) ;
return false ;
}
return true ;
}
2025-05-07 17:34:27 +08:00
int SqlQueryExecutor : : getAttributeID ( const QString & connectionName , const QString & type )
2025-04-08 20:02:38 +08:00
{
2025-04-11 17:14:17 +08:00
int id = - 1 ;
2025-04-08 20:02:38 +08:00
QString strSQL = " SELECT id FROM basic.attribute WHERE attribute = \' " + type + " \' " ;
try
{
QSqlQuery query = executeSQL ( connectionName , strSQL ) ;
if ( query . next ( ) )
2025-04-11 17:14:17 +08:00
id = query . value ( 0 ) . toInt ( ) ;
2025-04-08 20:02:38 +08:00
}
catch ( const DatabaseException & e )
{
2025-04-11 17:14:17 +08:00
id = - 1 ;
2025-04-08 20:02:38 +08:00
}
2025-04-11 17:14:17 +08:00
return id ;
}
bool SqlQueryExecutor : : attributeTypeUseByModelGroup ( const QString & connectionName , int attributeID , int modelID , int groupID )
{
2025-05-07 17:34:27 +08:00
QString strSQL ;
2025-04-11 17:14:17 +08:00
QVariantHash params ;
2025-05-07 17:34:27 +08:00
bool isPublicGroup = isPublicAttributeGroup ( connectionName , groupID ) ;
if ( isPublicGroup )
{
strSQL = " SELECT id FROM basic.model_attribute_public WHERE attribute_group_id = :groupID AND attribute_id = :attributeID " ;
params . insert ( " :groupID " , groupID ) ;
params . insert ( " :attributeID " , attributeID ) ;
}
else
{
strSQL = " SELECT id FROM basic.model_attribute WHERE model_type_id = :modelID AND attribute_group_id = :groupID AND attribute_id = :attributeID " ;
params . insert ( " :modelID " , modelID ) ;
params . insert ( " :groupID " , groupID ) ;
params . insert ( " :attributeID " , attributeID ) ;
}
2025-04-11 17:14:17 +08:00
try
{
QSqlQuery query = executeSQL ( connectionName , strSQL , params ) ;
if ( query . next ( ) )
return true ;
}
catch ( const DatabaseException & e )
{
return false ;
}
return false ;
2025-04-08 20:02:38 +08:00
}
2025-04-02 10:44:52 +08:00
bool SqlQueryExecutor : : batchInsertAttributes ( const QString & connectionName , int modelID , int attributeGroupID , QList < Attribute > attributes )
2025-04-01 14:37:41 +08:00
{
//属于批量操作,需要开启事务
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 ;
2025-04-02 14:58:42 +08:00
for ( const Attribute & attribute : attributes )
2025-04-01 14:37:41 +08:00
{
2025-04-11 17:14:17 +08:00
if ( attribute . id ! = - 1 ) //新建条目是通过选择已有的记录完成,此类不再做重复插入
{
attributeIDList . append ( attribute . id ) ;
continue ;
}
2025-04-01 14:37:41 +08:00
qint64 attributeID = QDateTime : : currentDateTime ( ) . toMSecsSinceEpoch ( ) ;
//先向model_type中插入一条记录
2025-04-27 16:24:13 +08:00
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) " ;
2025-04-01 14:37:41 +08:00
QVariantHash params ;
2025-04-02 14:58:42 +08:00
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 ) ;
2025-04-27 16:24:13 +08:00
params . insert ( " :isVisible " , attribute . isVisible ) ;
2025-04-01 14:37:41 +08:00
try
{
QSqlQuery query = executeSQL ( connectionName , strSQL , params ) ;
attributeID = query . lastInsertId ( ) . toInt ( ) ; //lasatInsertId()会返回最近插入行的自增id
}
catch ( const DatabaseException & e )
{
LOG_INFO ( " DB " , QString ( " DB Rollback " ) ) ;
2025-04-02 10:44:52 +08:00
if ( ! db . rollback ( ) ) // 回滚
2025-04-01 14:37:41 +08:00
{
LOG_ERROR ( " DB " , QString ( " Rollback failed. connectionName: %1. error: %2 " ) . arg ( connectionName , db . lastError ( ) . databaseText ( ) ) ) ;
}
return false ;
}
attributeIDList . append ( attributeID ) ;
}
//插入数据到关联表
QSqlQuery linkQuery ( db ) ;
2025-04-22 17:45:37 +08:00
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 (?, ?, ?) " ;
2025-04-02 10:44:52 +08:00
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 ;
}
2025-04-01 14:37:41 +08:00
QVariantList modelIds , groupIds , attributeIds ;
for ( const qint64 & attributeID : attributeIDList )
{
2025-04-22 17:45:37 +08:00
if ( ! isPublicGroup )
modelIds < < modelID ;
2025-04-01 14:37:41 +08:00
groupIds < < attributeGroupID ;
attributeIds < < attributeID ;
}
2025-04-22 17:45:37 +08:00
if ( ! isPublicGroup )
linkQuery . addBindValue ( modelIds ) ;
2025-04-01 14:37:41 +08:00
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 " ) ) ;
2025-04-02 10:44:52 +08:00
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 ) ;
2025-04-22 17:45:37 +08:00
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 = ? " ;
2025-04-02 10:44:52 +08:00
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 )
{
2025-04-22 17:45:37 +08:00
if ( ! isPublicGroup )
modelIds < < modelID ;
2025-04-02 10:44:52 +08:00
groupIds < < attributeGroupID ;
attributeIds < < attributeID ;
}
2025-04-22 17:45:37 +08:00
if ( ! isPublicGroup )
query . addBindValue ( modelIds ) ;
2025-04-02 10:44:52 +08:00
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 ( ) ) // 回滚
2025-04-01 14:37:41 +08:00
{
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 ;
}
2025-04-02 14:58:42 +08:00
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 ) ;
2025-04-27 16:24:13 +08:00
QString strSQL = " UPDATE basic.attribute SET attribute = ?, attribute_name = ?, data_type_id = ?, length_precision = ?, default_value = ?, is_visible = ? WHERE id = ? " ;
2025-04-02 14:58:42 +08:00
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 ;
}
2025-04-27 16:24:13 +08:00
QVariantList types , names , dataTypes , lengths , defaults , isVisibles , ids ;
2025-04-02 14:58:42 +08:00
for ( const Attribute & attribute : attributes )
{
types < < attribute . type ;
names < < attribute . name ;
dataTypes < < attribute . dataTypeID ;
lengths < < attribute . dataLength ;
defaults < < attribute . defaultValue ;
2025-04-27 16:24:13 +08:00
isVisibles < < attribute . isVisible ;
2025-04-02 14:58:42 +08:00
ids < < attribute . id ;
}
query . addBindValue ( types ) ;
query . addBindValue ( names ) ;
query . addBindValue ( dataTypes ) ;
query . addBindValue ( lengths ) ;
query . addBindValue ( defaults ) ;
2025-04-27 16:24:13 +08:00
query . addBindValue ( isVisibles ) ;
2025-04-02 14:58:42 +08:00
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 ;
}