Changed database structure from default UTC_TIMESTAMP() which are not supposed to be supported to triggers

update transaction database method
This commit is contained in:
Blue 2024-04-14 21:16:36 -03:00
parent 973deaefd9
commit c2d4bf5ccb
Signed by: blue
GPG Key ID: 9B203B252A63EE38
3 changed files with 130 additions and 49 deletions

View File

@ -18,7 +18,7 @@ CREATE TABLE IF NOT EXISTS accounts (
`nick` VARCHAR(256), `nick` VARCHAR(256),
`type` INTEGER UNSIGNED NOT NULL, `type` INTEGER UNSIGNED NOT NULL,
`password` VARCHAR(128), `password` VARCHAR(128),
`created` TIMESTAMP DEFAULT UTC_TIMESTAMP() `created` TIMESTAMP
); );
--creating role bindings table --creating role bindings table
@ -31,12 +31,12 @@ CREATE TABLE IF NOT EXISTS roleBindings (
FOREIGN KEY (role) REFERENCES roles(id) FOREIGN KEY (role) REFERENCES roles(id)
); );
--creating sessings table --creating sessions table
CREATE TABLE IF NOT EXISTS sessions ( CREATE TABLE IF NOT EXISTS sessions (
`id` INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY, `id` INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`owner` INTEGER UNSIGNED NOT NULL, `owner` INTEGER UNSIGNED NOT NULL,
`started` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `started` TIMESTAMP,
`latest` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `latest` TIMESTAMP,
`access` CHAR(32) NOT NULL UNIQUE, `access` CHAR(32) NOT NULL UNIQUE,
`renew` CHAR(32), `renew` CHAR(32),
`persist` BOOLEAN NOT NULL, `persist` BOOLEAN NOT NULL,
@ -51,7 +51,7 @@ CREATE TABLE IF NOT EXISTS currencies (
`code` VARCHAR(16) NOT NULL UNIQUE, `code` VARCHAR(16) NOT NULL UNIQUE,
`title` VARCHAR(256), `title` VARCHAR(256),
`manual` BOOLEAN NOT NULL, `manual` BOOLEAN NOT NULL,
`added` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `created` TIMESTAMP,
`type` INTEGER UNSIGNED NOT NULL, `type` INTEGER UNSIGNED NOT NULL,
`value` DECIMAL (20, 5) NOT NULL, `value` DECIMAL (20, 5) NOT NULL,
`source` TEXT, `source` TEXT,
@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS currencies (
INDEX manual_idx (manual) INDEX manual_idx (manual)
); );
--creating assests table --creating assets table
CREATE TABLE IF NOT EXISTS assets ( CREATE TABLE IF NOT EXISTS assets (
`id` INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY, `id` INTEGER UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`owner` INTEGER UNSIGNED NOT NULL, `owner` INTEGER UNSIGNED NOT NULL,
@ -72,7 +72,7 @@ CREATE TABLE IF NOT EXISTS assets (
`balance` DECIMAL (20, 5) DEFAULT 0, `balance` DECIMAL (20, 5) DEFAULT 0,
`type` INTEGER UNSIGNED NOT NULL, `type` INTEGER UNSIGNED NOT NULL,
`archived` BOOLEAN DEFAULT FALSE, `archived` BOOLEAN DEFAULT FALSE,
`created` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `created` TIMESTAMP,
INDEX owner_idx (owner), INDEX owner_idx (owner),
INDEX archived_idx (archived), INDEX archived_idx (archived),
@ -96,8 +96,8 @@ CREATE TABLE IF NOT EXISTS transactions (
`parent` INTEGER UNSIGNED, `parent` INTEGER UNSIGNED,
`value` DECIMAL (20, 5) NOT NULL, `value` DECIMAL (20, 5) NOT NULL,
`state` INTEGER UNSIGNED DEFAULT 0, `state` INTEGER UNSIGNED DEFAULT 0,
`modified` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `modified` TIMESTAMP,
`performed` TIMESTAMP DEFAULT UTC_TIMESTAMP(), `performed` TIMESTAMP,
`party` INTEGER UNSIGNED, `party` INTEGER UNSIGNED,
`notes` TEXT, `notes` TEXT,
@ -114,7 +114,63 @@ CREATE TABLE IF NOT EXISTS transactions (
FOREIGN KEY (party) REFERENCES parties(id) FOREIGN KEY (party) REFERENCES parties(id)
); );
--creating defailt roles --creating trigger before insert accounts
CREATE TRIGGER before_insert_accounts
BEFORE INSERT ON accounts
FOR EACH ROW
BEGIN
SET NEW.created = UTC_TIMESTAMP();
END;
--creating trigger before insert sessions
CREATE TRIGGER before_insert_sessions
BEFORE INSERT ON sessions
FOR EACH ROW
BEGIN
SET NEW.started = UTC_TIMESTAMP();
SET NEW.latest = UTC_TIMESTAMP();
END;
--creating trigger before insert currencies
CREATE TRIGGER before_insert_currencies
BEFORE INSERT ON currencies
FOR EACH ROW
BEGIN
IF NEW.created IS NULL THEN
SET NEW.created = UTC_TIMESTAMP();
END IF;
END;
--creating trigger before insert assets
CREATE TRIGGER before_insert_assets
BEFORE INSERT ON assets
FOR EACH ROW
BEGIN
IF NEW.created IS NULL THEN
SET NEW.created = UTC_TIMESTAMP();
END IF;
END;
--creating trigger before insert transactions
CREATE TRIGGER before_insert_transactions
BEFORE INSERT ON transactions
FOR EACH ROW
BEGIN
SET NEW.modified = UTC_TIMESTAMP();
IF NEW.performed IS NULL THEN
SET NEW.performed = UTC_TIMESTAMP();
END IF;
END;
--creating trigger before update transactions
CREATE TRIGGER before_update_transactions
BEFORE UPDATE ON transactions
FOR EACH ROW
BEGIN
SET NEW.modified = UTC_TIMESTAMP();
END;
--creating default roles
INSERT IGNORE INTO INSERT IGNORE INTO
roles (`name`) roles (`name`)
VALUES ('root'), VALUES ('root'),

View File

@ -5,6 +5,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <chrono>
#include "mysqld_error.h" #include "mysqld_error.h"
@ -34,6 +35,10 @@ constexpr const char* selectUsedCurrencies = "SELECT DISTINCT c.id, c.code, c.ti
constexpr const char* addTransactionQuery = "INSERT INTO transactions" constexpr const char* addTransactionQuery = "INSERT INTO transactions"
" (`initiator`, `type`, `asset`, `parent`, `value`, `performed`)" " (`initiator`, `type`, `asset`, `parent`, `value`, `performed`)"
" VALUES (?, 1, ?, ?, ?, ?)"; " VALUES (?, 1, ?, ?, ?, ?)";
constexpr const char* updateTransactionQuery = "UPDATE transactions SET"
" `initiator` = ?, `type` = 1, `asset` = ?,"
" `parent` = ?, `value` = ?, `performed` = ?"
" WHERE `id` = ?";
static const std::filesystem::path buildSQLPath = "database"; static const std::filesystem::path buildSQLPath = "database";
@ -131,17 +136,15 @@ void DB::MySQL::executeFile (const std::filesystem::path& relativePath) {
std::cout << "Executing file " << path << std::endl; std::cout << "Executing file " << path << std::endl;
std::ifstream inputFile(path); std::ifstream inputFile(path);
std::string query; std::string block, comment;
while (std::getline(inputFile, query, ';')) { while (getBlock(inputFile, block, comment)) {
std::optional<std::string> comment = getComment(query); if (!comment.empty())
while (comment) { std::cout << '\t' << comment << std::endl;
std::cout << '\t' << comment.value() << std::endl;
comment = getComment(query); if (block.empty())
}
if (query.empty())
continue; continue;
int result = mysql_query(con, query.c_str()); int result = mysql_query(con, block.c_str());
if (result != 0) { if (result != 0) {
int errcode = mysql_errno(con); int errcode = mysql_errno(con);
if (errcode == ER_EMPTY_QUERY) if (errcode == ER_EMPTY_QUERY)
@ -153,6 +156,39 @@ void DB::MySQL::executeFile (const std::filesystem::path& relativePath) {
} }
} }
bool DB::MySQL::getBlock(std::ifstream& file, std::string& block, std::string& name) {
if (file.eof())
return false;
block.clear();
name.clear();
if (file.peek() == '-') {
file.get();
if (file.peek() == '-') {
file.get();
std::getline(file, name);
} else {
file.unget();
}
}
std::string line;
while (!file.eof()) {
if (file.peek() == '-')
return true;
if (!std::getline(file, line))
break;
if (!block.empty())
block.append(1, '\n');
block += line;
}
return !block.empty() || !name.empty();
}
uint8_t DB::MySQL::getVersion () { uint8_t DB::MySQL::getVersion () {
MYSQL* con = &connection; MYSQL* con = &connection;
int result = mysql_query(con, versionQuery); int result = mysql_query(con, versionQuery);
@ -205,34 +241,6 @@ void DB::MySQL::migrate (uint8_t targetVersion) {
std::cout << "Database is now on actual version " << std::to_string(targetVersion) << std::endl; std::cout << "Database is now on actual version " << std::to_string(targetVersion) << std::endl;
} }
std::optional<std::string> DB::MySQL::getComment (std::string& string) {
ltrim(string);
if (string.length() < 2)
return std::nullopt;
if (string[0] == '-') {
if (string[1] == '-') {
string.erase(0, 2);
std::string::size_type eol = string.find('\n');
return extract(string, 0, eol);
}
} else if (string[0] == '/') {
if (string[1] == '*') {
string.erase(0, 2);
std::string::size_type end = 0;
do {
end = string.find(end, '*');
} while (end != std::string::npos && end < string.size() - 1 && string[end + 1] == '/');
if (end < string.size() - 1)
end = std::string::npos;
return extract(string, 0, end);
}
}
return std::nullopt;
}
uint32_t DB::MySQL::registerAccount (const std::string& login, const std::string& hash) { uint32_t DB::MySQL::registerAccount (const std::string& login, const std::string& hash) {
//TODO validate filed lengths! //TODO validate filed lengths!
MYSQL* con = &connection; MYSQL* con = &connection;
@ -429,12 +437,29 @@ DB::Transaction DB::MySQL::addTransaction(const DB::Transaction& transaction) {
add.execute(); add.execute();
result.id = lastInsertedId(); result.id = lastInsertedId();
//todo retreive timestamp and actual value which could have changed after insertion std::chrono::time_point currently = std::chrono::time_point_cast<std::chrono::seconds>(
std::chrono::system_clock::now()
);
result.modified = currently.time_since_epoch().count();
//todo actual value which could have changed after insertion
return result; return result;
} }
void DB::MySQL::updateTransaction(const DB::Transaction& transaction) { void DB::MySQL::updateTransaction(const DB::Transaction& transaction) {
MYSQL* con = &connection;
DB::Transaction result = transaction;
std::string value = std::to_string(result.value);
Statement upd(con, updateTransactionQuery);
upd.bind(&result.initiator, MYSQL_TYPE_LONG, true);
upd.bind(&result.asset, MYSQL_TYPE_LONG, true);
upd.bind(&result.parent, MYSQL_TYPE_LONG, true);
upd.bind(value.data(), MYSQL_TYPE_STRING);
upd.bind(&result.performed, MYSQL_TYPE_LONG, true);
upd.bind(&result.id, MYSQL_TYPE_LONG, true);
upd.execute();
} }
std::vector<DB::Transaction> DB::MySQL::listTransactions(uint32_t owner) { std::vector<DB::Transaction> DB::MySQL::listTransactions(uint32_t owner) {

View File

@ -49,7 +49,7 @@ public:
private: private:
void executeFile (const std::filesystem::path& relativePath); void executeFile (const std::filesystem::path& relativePath);
static std::optional<std::string> getComment (std::string& string); bool getBlock (std::ifstream& file, std::string& block, std::string& name);
uint32_t lastInsertedId (); uint32_t lastInsertedId ();
protected: protected: