Add Visione backend foundation
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
#include "repositories/MigrationRunner.h"
|
||||
|
||||
#include <drogon/drogon.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace visione::repositories
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::string trim(std::string value)
|
||||
{
|
||||
auto notSpace = [](unsigned char ch) { return !std::isspace(ch); };
|
||||
value.erase(value.begin(),
|
||||
std::find_if(value.begin(), value.end(), notSpace));
|
||||
value.erase(std::find_if(value.rbegin(), value.rend(), notSpace).base(),
|
||||
value.end());
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<std::string> splitStatements(const std::string &sql)
|
||||
{
|
||||
std::vector<std::string> statements;
|
||||
std::string current;
|
||||
bool inSingleQuote = false;
|
||||
bool inDoubleQuote = false;
|
||||
|
||||
for (char ch : sql)
|
||||
{
|
||||
if (ch == '\'' && !inDoubleQuote)
|
||||
{
|
||||
inSingleQuote = !inSingleQuote;
|
||||
}
|
||||
else if (ch == '"' && !inSingleQuote)
|
||||
{
|
||||
inDoubleQuote = !inDoubleQuote;
|
||||
}
|
||||
|
||||
if (ch == ';' && !inSingleQuote && !inDoubleQuote)
|
||||
{
|
||||
auto statement = trim(current);
|
||||
if (!statement.empty())
|
||||
{
|
||||
statements.push_back(std::move(statement));
|
||||
}
|
||||
current.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
current.push_back(ch);
|
||||
}
|
||||
|
||||
auto statement = trim(current);
|
||||
if (!statement.empty())
|
||||
{
|
||||
statements.push_back(std::move(statement));
|
||||
}
|
||||
return statements;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void MigrationRunner::run(const std::string &directory)
|
||||
{
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::vector<fs::path> files;
|
||||
if (!fs::exists(directory))
|
||||
{
|
||||
LOG_WARN << "Migration directory not found: " << directory;
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &entry : fs::directory_iterator(directory))
|
||||
{
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".sql")
|
||||
{
|
||||
files.push_back(entry.path());
|
||||
}
|
||||
}
|
||||
std::sort(files.begin(), files.end());
|
||||
|
||||
auto db = drogon::app().getDbClient();
|
||||
for (const auto &file : files)
|
||||
{
|
||||
std::ifstream input(file);
|
||||
std::stringstream buffer;
|
||||
buffer << input.rdbuf();
|
||||
|
||||
for (const auto &statement : splitStatements(buffer.str()))
|
||||
{
|
||||
db->execSqlSync(statement);
|
||||
}
|
||||
LOG_INFO << "Applied migration " << file.string();
|
||||
}
|
||||
}
|
||||
} // namespace visione::repositories
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace visione::repositories
|
||||
{
|
||||
class MigrationRunner
|
||||
{
|
||||
public:
|
||||
static void run(const std::string &directory);
|
||||
};
|
||||
} // namespace visione::repositories
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "repositories/Sql.h"
|
||||
|
||||
#include <drogon/orm/Field.h>
|
||||
#include <drogon/orm/ResultIterator.h>
|
||||
#include <drogon/orm/RowIterator.h>
|
||||
|
||||
namespace visione::repositories
|
||||
{
|
||||
Json::Value rowToJson(const drogon::orm::Row &row)
|
||||
{
|
||||
Json::Value object(Json::objectValue);
|
||||
for (const auto &field : row)
|
||||
{
|
||||
if (field.isNull())
|
||||
{
|
||||
object[field.name()] = Json::nullValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
object[field.name()] = field.as<std::string>();
|
||||
}
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
Json::Value resultToJson(const drogon::orm::Result &result)
|
||||
{
|
||||
Json::Value array(Json::arrayValue);
|
||||
for (const auto &row : result)
|
||||
{
|
||||
array.append(rowToJson(row));
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
std::string nullableString(const Json::Value &value, const std::string &key)
|
||||
{
|
||||
if (!value.isMember(key) || value[key].isNull())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return value[key].asString();
|
||||
}
|
||||
} // namespace visione::repositories
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <drogon/orm/Result.h>
|
||||
|
||||
#include <json/json.h>
|
||||
#include <string>
|
||||
|
||||
namespace visione::repositories
|
||||
{
|
||||
Json::Value rowToJson(const drogon::orm::Row &row);
|
||||
Json::Value resultToJson(const drogon::orm::Result &result);
|
||||
std::string nullableString(const Json::Value &value, const std::string &key);
|
||||
} // namespace visione::repositories
|
||||
|
||||
Reference in New Issue
Block a user