#define DROP_INDEX2R(tblName, rowName1, rowName2) EXECUTE_("Failed to drop old indexes", "DROP INDEX IF EXISTS `idx_" tblName "_" rowName1 "_" rowName2 "`;", "");
CREATE_TABLE("servers","`serverId` INT NOT NULL, `host` TEXT NOT NULL, `port` INT",command_append_utf8);
CREATE_TABLE("assignedGroups","`serverId` INT NOT NULL, `cldbid` INT NOT NULL, `groupId` INT, `channelId` INT DEFAULT -1, `until` BIGINT DEFAULT -1",command_append_utf8);
CREATE_TABLE("groups","`serverId` INT NOT NULL, `groupId` INTEGER, `target` INT, `type` INT, `displayName` VARCHAR("CLIENT_NAME_LENGTH")",command_append_utf8);
CREATE_TABLE("permissions","`serverId` INT NOT NULL, `type` INT, `id` INT, `channelId` INT, `permId` VARCHAR("UNKNOWN_KEY_LENGTH"), `value` INT, `grant` INT",command_append_utf8);
CREATE_TABLE("bannedClients","`banId` INTEGER NOT NULL PRIMARY KEY, `serverId` INT NOT NULL, `invokerDbId` INT NOT NULL, `reason` TEXT, `hwid` VARCHAR("CLIENT_UID_LENGTH"), `uid` VARCHAR("CLIENT_UID_LENGTH"), `name` VARCHAR("CLIENT_NAME_LENGTH"), `ip` VARCHAR(128), `strType` VARCHAR(32), `created` BIGINT DEFAULT -1, `until` BIGINT DEFAULT -1",command_append_utf8);
CREATE_TABLE("tokens","`serverId` INT NOT NULL, `type` INT NOT NULL, `token` VARCHAR(128), `targetGroup` INT NOT NULL, `targetChannel` INT, `description` TEXT , `created` INT",command_append_utf8);
CREATE_TABLE("complains","`serverId` INT NOT NULL, `targetId` INT NOT NULL, `reporterId` INT NOT NULL, `reason` TEXT, `created` INT",command_append_utf8);
CREATE_TABLE("letters","`serverId` INT NOT NULL, `letterId` INTEGER NOT NULL PRIMARY KEY, `sender` VARCHAR("CLIENT_UID_LENGTH"), `receiver` VARCHAR("CLIENT_UID_LENGTH"), `created` INT, `subject` TEXT, `message` TEXT, `read` INT",command_append_utf8);
sql::command(this->sql(),"UPDATE `properties` SET `type` = :type WHERE `serverId` = 0 AND `id` = 0",variable{":type",property::PropertyType::PROP_TYPE_INSTANCE}).execute();
error="Failed to create new permission table ("+result.fmtStr()+")";
returnfalse;
}
result=sql::command(this->sql(),"INSERT INTO `permissions` SELECT * FROM `permissions_v6` GROUP BY `serverId`, `type`, `id`, `channelId`, `permId`;").execute();
if(!result){
error="Failed to insert unique permissions ("+result.fmtStr()+")";
result=sql::command(this->sql(),"INSERT INTO `properties` SELECT * FROM `properties_v6` GROUP BY `serverId`, `type`, `id`, `key`;").execute();
if(!result){
error="Failed to insert unique properties ("+result.fmtStr()+")";
returnfalse;
}
if(manager->getType()==sql::TYPE_SQLITE){
DROP_INDEX("properties","serverId");
DROP_INDEX2R("properties","serverId","id");
}
CREATE_INDEX("properties","serverId");
CREATE_INDEX2R("properties","serverId","id");
/* SELECT * FROM `permissions` WHERE `type` = 1 AND (`serverId`, `channelId`) IN (SELECT `serverId`, `channelId` FROM `channels`) */
/* Channel permission cleanup: DELETE FROM `permissions` WHERE `type` = 1 AND NOT (`serverId`, `channelId`) IN (SELECT `serverId`, `channelId` FROM `channels`) */
sql::command(this->sql(),"DELETE FROM `permissions` WHERE (`type` = 1 OR `type` = 2) AND NOT ((`serverId`, `channelId`) IN (SELECT `serverId`, `channelId` FROM `channels`) OR `channelId` = 0);").execute();
sql::command(this->sql(),"DELETE FROM `permissions` WHERE `type` = 0 AND NOT (`serverId`, `id`) IN (SELECT `serverId`, `groupId` FROM `groups`);").execute();
sql::command(this->sql(),"DELETE FROM `permissions` WHERE `type` = 2 AND NOT (`serverId`, `id`) IN (SELECT `serverId`, `cldbid` FROM `clients`);").execute();
sql::command(this->sql(),"DELETE FROM `properties` WHERE `type` = 1 AND NOT (`serverId` IN (SELECT `serverId` FROM servers) OR `serverId` = 0);").execute();
}
this->changeVersion(8);
case8:
result=sql::command(this->sql(),"UPDATE `queries` SET `server` = 0 WHERE `server` IS NULL").execute();
if(!result){
error="Failed to drop null query entries ("+result.fmtStr()+")";
returnfalse;
}
this->changeVersion(9);
case9:
//
//"UPDATE `permissions` SET `id` = :id WHERE `type` = :channel_type" ;permission::SQL_PERM_CHANNEL
result=sql::command(this->sql(),"UPDATE `permissions` SET `id` = :id WHERE `type` = :channel_type;",variable{":channel_type",permission::SQL_PERM_CHANNEL},variable{":id",0}).execute();
if(!result){
if(result.code()==1){//constraint failed => duplicated ids for example
size_tcount=0;
result=sql::command(this->sql(),"SELECT COUNT(*) FROM `permissions` WHERE NOT `id` = :id AND `type` = :type",variable{":type",permission::SQL_PERM_CHANNEL},variable{":id",0}).query([&](int,std::string*values,std::string*){
result=sql::command(this->sql(),"DELETE FROM `permissions` WHERE NOT `id` = :id AND `type` = :type",variable{":channel_type",permission::SQL_PERM_CHANNEL},variable{":id",0}).execute();
}
if(!result){
error="Failed to fix channel properties ("+result.fmtStr()+")";
rollback_watch.do_notify=false;/* transaction was successful */
break;
}
autotimestamp_end=system_clock::now();
logMessage(LOG_GENERAL,"Database upgrade took {}ms",duration_cast<milliseconds>(timestamp_end-timestamp_start).count());
}
//Advanced locked test
{
boolproperty_exists=false;
sql::command(this->sql(),"SELECT * FORM `general` WHERE `key` = :key",variable{":key","lock_test"}).query([](bool&flag,int,string*,string*){flag=true;},property_exists);
sql::resultres;
if(!property_exists){
res=sql::command(this->sql(),"INSERT INTO `general` (`key`, `value`) VALUES (:key, :value);",variable{":key","lock_test"},variable{":value","UPDATE ME!"}).execute();
}else{
res=sql::command(this->sql(),"UPDATE `general` SET `value`= :value WHERE `key`= :key;",variable{":key","lock_test"},variable{":value","TeaSpeak created by WolverinDEV <3"}).execute();
}
if(!res){
if(res.msg().find("database is locked")!=string::npos)error="database is locked";
elseerror="Failed to execute lock test! Command result: "+res.fmtStr();
returnfalse;
}
}
returntrue;
}
voidSqlDataManager::finalize(){
if(this->manager)this->manager->disconnect();
deletethis->manager;
this->manager=nullptr;
}
voidSqlDataManager::detectVersion(){
sql::command(this->manager,"SELECT `value` FROM `general` WHERE `key`= :key",variable{":key","data_version"}).query([&](intlength,char**values,char**){
this->version=atoi(values[0]);
this->version_present=false;
return0;
});
}
voidSqlDataManager::changeVersion(intversion){
stringcommand;
if(this->version_present)
command="UPDATE `general` SET `value`= :version WHERE `key`= :key;";
else
command="INSERT INTO `general` (`key`, `value`) VALUES (:key, :version);";