update and fix MySQL UID feature.
Also added a port setting, a test connection button and a connection status label
This commit is contained in:
@@ -13,25 +13,119 @@ namespace
|
||||
std::unique_ptr<sql::Connection> connect()
|
||||
{
|
||||
QSettings settings;
|
||||
std::unique_ptr<sql::Connection> Con
|
||||
(get_driver_instance()->connect
|
||||
( settings.value("project/mysql/server").toString().toStdString()
|
||||
, settings.value("project/mysql/user").toString().toStdString()
|
||||
, settings.value("project/mysql/pwd").toString().toStdString()
|
||||
)
|
||||
);
|
||||
Con->setSchema(settings.value("project/mysql/db").toString().toStdString());
|
||||
|
||||
return Con;
|
||||
// if using release SQL binaries in debug mode it will crash https://bugs.mysql.com/bug.php?id=91238 unless using sql strings
|
||||
// tcp://127.0.0.1:3306
|
||||
sql::SQLString hostname = "tcp://" + settings.value("project/mysql/server").toString().toStdString() + ":" + settings.value("project/mysql/port", "3306").toString().toStdString();
|
||||
sql::SQLString userName = settings.value("project/mysql/user").toString().toStdString();
|
||||
sql::SQLString password = settings.value("project/mysql/pwd").toString().toStdString();
|
||||
sql::SQLString schema = settings.value("project/mysql/db").toString().toStdString();
|
||||
|
||||
try
|
||||
{
|
||||
std::unique_ptr<sql::Connection> Con(get_driver_instance()->connect(hostname, userName, password));
|
||||
|
||||
// crete database if it deosn't exist
|
||||
std::string createdb_statement = "CREATE DATABASE IF NOT EXISTS " + schema;
|
||||
std::unique_ptr<sql::PreparedStatement> dbpstmt(Con->prepareStatement(createdb_statement));
|
||||
std::unique_ptr<sql::ResultSet> res(dbpstmt->executeQuery());
|
||||
|
||||
Con->setSchema(schema);
|
||||
|
||||
// create table if it doesn't exist, querries from src/sql
|
||||
std::unique_ptr<sql::PreparedStatement> tablepstmt(Con->prepareStatement("CREATE TABLE IF NOT EXISTS `UIDs` ("
|
||||
"`_map_id` int(11) NOT NULL,"
|
||||
"`UID` int(11) NOT NULL,"
|
||||
"PRIMARY KEY(`_map_id`)"
|
||||
") ENGINE = InnoDB DEFAULT CHARSET = latin1;"));
|
||||
std::unique_ptr<sql::ResultSet> tableres(tablepstmt->executeQuery());
|
||||
|
||||
// std::unique_ptr<sql::PreparedStatement> alterpstmt(Con->prepareStatement("ALTER TABLE `UIDs` ADD PRIMARY KEY(`_map_id`);"));
|
||||
// std::unique_ptr<sql::ResultSet> altres(alterpstmt->executeQuery());
|
||||
|
||||
return Con;
|
||||
}
|
||||
catch (sql::SQLException& e)
|
||||
{
|
||||
/*
|
||||
// prompt would pop on every model spawn
|
||||
QMessageBox prompt;
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setText("Failed to load MySQL database, check your settings.");
|
||||
prompt.setWindowTitle("Noggit Database Error");
|
||||
std::stringstream promptText;
|
||||
|
||||
promptText << "\n# ERR: " << e.what();
|
||||
promptText << "\n (MySQL error code: " << e.getErrorCode();
|
||||
|
||||
prompt.setInformativeText(promptText.str().c_str());
|
||||
prompt.exec();
|
||||
*/
|
||||
|
||||
std::stringstream test3;
|
||||
// test1 << "\n# ERR: SQLException in " << __FILE__;
|
||||
// test2 << "\n(" << __FUNCTION__ << ") on line " << __LINE__ << endl;
|
||||
// /* what() (derived from std::runtime_error) fetches error message */
|
||||
test3 << "\n# ERR: " << e.what();
|
||||
// test4 << "\n (MySQL error code: " << e.getErrorCode();
|
||||
// test5 << "\n, SQLState: " << e.getSQLState() << " )" << endl;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace mysql
|
||||
{
|
||||
bool testConnection(bool report_only_err)
|
||||
{
|
||||
QSettings settings;
|
||||
// if using release SQL binaries in debug mode it will crash https://bugs.mysql.com/bug.php?id=91238 unless using sql strings
|
||||
// tcp://127.0.0.1:3306
|
||||
sql::SQLString hostname = "tcp://" + settings.value("project/mysql/server").toString().toStdString() + ":" + settings.value("project/mysql/port", "3306").toString().toStdString();
|
||||
sql::SQLString userName = settings.value("project/mysql/user").toString().toStdString();
|
||||
sql::SQLString password = settings.value("project/mysql/pwd").toString().toStdString();
|
||||
sql::SQLString schema = settings.value("project/mysql/db").toString().toStdString();
|
||||
|
||||
QMessageBox prompt;
|
||||
prompt.setWindowFlag(Qt::WindowStaysOnTopHint);
|
||||
try
|
||||
{
|
||||
std::unique_ptr<sql::Connection> Con(get_driver_instance()->connect(hostname, userName, password));
|
||||
|
||||
prompt.setIcon(QMessageBox::Information);
|
||||
prompt.setText("Succesfully connected to MySQL database.");
|
||||
prompt.setWindowTitle("Success");
|
||||
|
||||
if (!report_only_err)
|
||||
prompt.exec();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (sql::SQLException& e)
|
||||
{
|
||||
|
||||
prompt.setIcon(QMessageBox::Warning);
|
||||
prompt.setText("Failed to load MySQL database, check your settings.");
|
||||
prompt.setWindowTitle("Noggit Database Error");
|
||||
std::stringstream promptText;
|
||||
|
||||
promptText << "\n# ERR: " << e.what();
|
||||
promptText << "\n (MySQL error code: " << e.getErrorCode() + ")";
|
||||
|
||||
prompt.setInformativeText(promptText.str().c_str());
|
||||
prompt.exec();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasMaxUIDStoredDB(std::size_t mapID)
|
||||
{
|
||||
auto Con(connect());
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("SELECT * FROM UIDs WHERE MapId=(?)"));
|
||||
if (Con == nullptr)
|
||||
return false;
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("SELECT * FROM `UIDs` WHERE `_map_id`=(?)"));
|
||||
pstmt->setInt(1, mapID);
|
||||
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||
return res->rowsCount();
|
||||
@@ -40,7 +134,9 @@ namespace mysql
|
||||
std::uint32_t getGUIDFromDB(std::size_t mapID)
|
||||
{
|
||||
auto Con(connect());
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("SELECT UID FROM UIDs WHERE MapId=(?)"));
|
||||
if (Con == nullptr)
|
||||
return 0;
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("SELECT `UID` FROM `UIDs` WHERE `_map_id`=(?)"));
|
||||
pstmt->setInt(1, mapID);
|
||||
std::unique_ptr<sql::ResultSet> res(pstmt->executeQuery());
|
||||
|
||||
@@ -60,7 +156,9 @@ namespace mysql
|
||||
void insertUIDinDB(std::size_t mapID, std::uint32_t NewUID)
|
||||
{
|
||||
auto Con(connect());
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("INSERT INTO UIDs SET MapId=(?), UID=(?)"));
|
||||
if (Con == nullptr)
|
||||
return;
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("INSERT INTO `UIDs` SET `_map_id`=(?), `UID`=(?)"));
|
||||
pstmt->setInt(1, mapID);
|
||||
pstmt->setInt(2, NewUID);
|
||||
pstmt->executeUpdate();
|
||||
@@ -69,7 +167,9 @@ namespace mysql
|
||||
void updateUIDinDB (std::size_t mapID, std::uint32_t NewUID)
|
||||
{
|
||||
auto Con(connect());
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("UPDATE UIDs SET UID=(?) WHERE MapId=(?)"));
|
||||
if (Con == nullptr)
|
||||
return;
|
||||
std::unique_ptr<sql::PreparedStatement> pstmt(Con->prepareStatement("UPDATE `UIDs` SET `UID`=(?) WHERE `_map_id`=(?)"));
|
||||
pstmt->setInt(1, NewUID);
|
||||
pstmt->setInt(2, mapID);
|
||||
pstmt->executeUpdate();
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
namespace mysql
|
||||
{
|
||||
bool testConnection(bool report_only_err = false);
|
||||
bool hasMaxUIDStoredDB(std::size_t mapID);
|
||||
std::uint32_t getGUIDFromDB(std::size_t mapID);
|
||||
void insertUIDinDB(std::size_t mapID, std::uint32_t NewUID);
|
||||
|
||||
@@ -50,6 +50,12 @@
|
||||
#include <variant>
|
||||
#include <noggit/Selection.h>
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#endif
|
||||
|
||||
#include <noggit/scripting/scripting_tool.hpp>
|
||||
#include <noggit/scripting/script_settings.hpp>
|
||||
|
||||
@@ -2597,6 +2603,19 @@ void MapView::createGUI()
|
||||
connect(_main_window, &Noggit::Ui::Windows::NoggitWindow::exitPromptOpened, this, &MapView::on_exit_prompt);
|
||||
|
||||
set_editing_mode (editing_mode::ground);
|
||||
|
||||
// do we need to do this every tick ?
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
if (_settings->value("project/mysql/enabled").toBool())
|
||||
{
|
||||
if (mysql::hasMaxUIDStoredDB(_world->getMapID()))
|
||||
{
|
||||
_status_database->setText("MySQL UID sync enabled: "
|
||||
+ _settings->value("project/mysql/server").toString() + ":"
|
||||
+ _settings->value("project/mysql/port").toString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MapView::on_exit_prompt()
|
||||
@@ -2638,6 +2657,7 @@ MapView::MapView( math::degrees camera_yaw0
|
||||
, _status_time (new QLabel (this))
|
||||
, _status_fps (new QLabel (this))
|
||||
, _status_culling (new QLabel (this))
|
||||
, _status_database(new QLabel(this))
|
||||
, _texBrush{new OpenGL::texture{}}
|
||||
, _transform_gizmo(Noggit::Ui::Tools::ViewportGizmo::GizmoContext::MAP_VIEW)
|
||||
, _tablet_manager(Noggit::TabletManager::instance()),
|
||||
@@ -2695,6 +2715,12 @@ MapView::MapView( math::degrees camera_yaw0
|
||||
, _main_window
|
||||
, [=] { _main_window->statusBar()->removeWidget (_status_culling); }
|
||||
);
|
||||
_main_window->statusBar()->addWidget(_status_database);
|
||||
connect(this
|
||||
, &QObject::destroyed
|
||||
, _main_window
|
||||
, [=] { _main_window->statusBar()->removeWidget(_status_database); }
|
||||
);
|
||||
|
||||
moving = strafing = updown = lookat = turn = 0.0f;
|
||||
|
||||
@@ -3974,6 +4000,18 @@ void MapView::tick (float dt)
|
||||
|
||||
updateDetailInfos();
|
||||
|
||||
/*
|
||||
// do we need to do this every tick ?
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
if (_settings->value("project/mysql/enabled").toBool())
|
||||
{
|
||||
_status_database->setText("MySQL UID sync enabled: "
|
||||
+ _settings->value("project/mysql/server").toString() + ":"
|
||||
+ _settings->value("project/mysql/port").toString());
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
_status_area->setText
|
||||
(QString::fromStdString (gAreaDB.getAreaName (_world->getAreaID (_camera.position))));
|
||||
|
||||
|
||||
@@ -367,6 +367,7 @@ private:
|
||||
QLabel* _status_time;
|
||||
QLabel* _status_fps;
|
||||
QLabel* _status_culling;
|
||||
QLabel* _status_database;
|
||||
|
||||
Noggit::BoolToggleProperty _locked_cursor_mode = {false};
|
||||
Noggit::BoolToggleProperty _move_model_to_cursor_position = {true};
|
||||
|
||||
@@ -681,7 +681,7 @@ uint32_t MapIndex::newGUID()
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
QSettings settings;
|
||||
|
||||
if (settings->value ("project/mysql/enabled", false).toBool())
|
||||
if (settings.value ("project/mysql/enabled", false).toBool())
|
||||
{
|
||||
mysql::updateUIDinDB(_map_id, highestGUID + 1); // update the highest uid in db, note that if the user don't save these uid won't be used (not really a problem tho)
|
||||
}
|
||||
@@ -1025,7 +1025,7 @@ void MapIndex::saveMaxUID()
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
QSettings settings;
|
||||
|
||||
if (settings->value ("project/mysql/enabled", false).toBool())
|
||||
if (settings.value ("project/mysql/enabled", false).toBool())
|
||||
{
|
||||
if (mysql::hasMaxUIDStoredDB(_map_id))
|
||||
{
|
||||
@@ -1047,9 +1047,9 @@ void MapIndex::loadMaxUID()
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
QSettings settings;
|
||||
|
||||
if (settings->value ("project/mysql/enabled", false).toBool())
|
||||
if (settings.value ("project/mysql/enabled", false).toBool())
|
||||
{
|
||||
highestGUID = std::max(mysql::getGUIDFromDB(map_id), highestGUID);
|
||||
highestGUID = std::max(mysql::getGUIDFromDB(_map_id), highestGUID);
|
||||
// save to make sure the db and disk uid are synced
|
||||
saveMaxUID();
|
||||
}
|
||||
|
||||
@@ -126,12 +126,14 @@ namespace Noggit::Ui::Windows
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
bool use_mysql = settings.value("project/mysql/enabled", false).toBool();
|
||||
|
||||
if ((use_myqsl && mysql::hasMaxUIDStoredDB(_world->getMapID()))
|
||||
mysql::testConnection(true);
|
||||
|
||||
if ((use_mysql && mysql::hasMaxUIDStoredDB(_world->getMapID()))
|
||||
|| uid_storage::hasMaxUIDStored(_world->getMapID())
|
||||
)
|
||||
{
|
||||
_world->mapIndex.loadMaxUID();
|
||||
enterMapAt(pos, camera_pitch, camera_yaw, from_bookmark);
|
||||
enterMapAt(pos, camera_pitch, camera_yaw, uid_fix_mode::none, from_bookmark);
|
||||
}
|
||||
#else
|
||||
if (uid_storage::hasMaxUIDStored(_world->getMapID()))
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#include <QDir>
|
||||
#include <QApplication>
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
#include <mysql/mysql.h>
|
||||
#endif
|
||||
|
||||
#include <ui_SettingsPanel.h>
|
||||
#include <ui_TitleBar.h>
|
||||
|
||||
@@ -85,6 +89,7 @@ namespace Noggit
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
ui->MySQL_box->setEnabled(true);
|
||||
ui->MySQL_box->setCheckable(true);
|
||||
ui->mysql_warning->setVisible(false);
|
||||
#endif
|
||||
|
||||
@@ -157,6 +162,13 @@ namespace Noggit
|
||||
}
|
||||
);
|
||||
|
||||
connect(ui->mysql_connect_test, &QPushButton::clicked, [this]
|
||||
{
|
||||
save_changes();
|
||||
mysql::testConnection();
|
||||
}
|
||||
);
|
||||
|
||||
// load the values in the fields
|
||||
discard_changes();
|
||||
}
|
||||
@@ -200,11 +212,31 @@ namespace Noggit
|
||||
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
ui->_mysql_box->setChecked (_settings->value ("project/mysql/enabled").toBool());
|
||||
ui->_mysql_server_field->setText (_settings->value ("project/mysql/server").toString());
|
||||
ui->_mysql_user_field->setText(_settings->value ("project/mysql/user").toString());
|
||||
ui->_mysql_pwd_field->setText (_settings->value ("project/mysql/pwd").toString());
|
||||
ui->_mysql_db_field->setText (_settings->value ("project/mysql/db").toString());
|
||||
ui->MySQL_box->setChecked (_settings->value ("project/mysql/enabled").toBool());
|
||||
|
||||
auto server_str = _settings->value("project/mysql/server", "127.0.0.1").toString();
|
||||
auto user_str = _settings->value("project/mysql/user", "127.0.0.1").toString();
|
||||
auto pwd_str = _settings->value("project/mysql/pwd", "127.0.0.1").toString();
|
||||
auto db_str = _settings->value("project/mysql/db", "127.0.0.1").toString();
|
||||
auto port_int = _settings->value("project/mysql/port", "127.0.0.1").toInt();
|
||||
|
||||
// set some default
|
||||
if (server_str.isEmpty())
|
||||
server_str = "127.0.0.1";
|
||||
if (user_str.isEmpty())
|
||||
user_str = "root";
|
||||
if (pwd_str.isEmpty())
|
||||
pwd_str = "root";
|
||||
if (db_str.isEmpty())
|
||||
db_str = "noggit";
|
||||
if (!port_int)
|
||||
port_int = 3306;
|
||||
|
||||
ui->_mysql_server_field->setText (server_str);
|
||||
ui->_mysql_user_field->setText(user_str);
|
||||
ui->_mysql_pwd_field->setText (pwd_str);
|
||||
ui->_mysql_db_field->setText (db_str);
|
||||
ui->_mysql_port_field->setValue (port_int);
|
||||
#endif
|
||||
|
||||
int wireframe_type = _settings->value("wireframe/type", 0).toInt();
|
||||
@@ -245,11 +277,12 @@ namespace Noggit
|
||||
_settings->setValue("nativeMenubar", ui->_nativeMenubar->isChecked());
|
||||
|
||||
#ifdef USE_MYSQL_UID_STORAGE
|
||||
_settings->setValue ("project/mysql/enabled", _mysql_box->isChecked());
|
||||
_settings->setValue ("project/mysql/server", _mysql_server_field->text());
|
||||
_settings->setValue ("project/mysql/user", _mysql_user_field->text());
|
||||
_settings->setValue ("project/mysql/pwd", _mysql_pwd_field->text());
|
||||
_settings->setValue ("project/mysql/db", _mysql_db_field->text());
|
||||
_settings->setValue ("project/mysql/enabled", ui->MySQL_box->isChecked());
|
||||
_settings->setValue ("project/mysql/server", ui->_mysql_server_field->text());
|
||||
_settings->setValue ("project/mysql/user", ui->_mysql_user_field->text());
|
||||
_settings->setValue ("project/mysql/pwd", ui->_mysql_pwd_field->text());
|
||||
_settings->setValue ("project/mysql/db", ui->_mysql_db_field->text());
|
||||
_settings->setValue ("project/mysql/port", ui->_mysql_port_field->text());
|
||||
#endif
|
||||
|
||||
_settings->setValue("wireframe/type", ui->radio_wire_cursor->isChecked());
|
||||
|
||||
@@ -1295,6 +1295,26 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_66">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_48">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="_mysql_port_field"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="mysql_warning">
|
||||
<property name="minimumSize">
|
||||
|
||||
Reference in New Issue
Block a user