Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In memory db #553

Merged
merged 3 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion SDK/include/Server/Components/Databases/databases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ struct IDatabasesComponent : public IComponent
/// Opens a new database connection
/// @param path Path to the database
/// @returns Database if successful, otherwise "nullptr"
virtual IDatabaseConnection* open(StringView path) = 0;
virtual IDatabaseConnection* open(StringView path, int flags = 0) = 0;

/// Closes the specified database connection
/// @param connection Database connection
Expand Down
9 changes: 7 additions & 2 deletions Server/Components/Databases/databases_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,16 @@ void DatabasesComponent::onLoad(ICore* c) { }
/// Opens a new database connection
/// @param path Path to the database
/// @returns Database if successful, otherwise "nullptr"
IDatabaseConnection* DatabasesComponent::open(StringView path)
IDatabaseConnection* DatabasesComponent::open(StringView path, int flags)
{
if (flags == 0)
{
// Defaults.
flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
}
DatabaseConnection* ret(nullptr);
sqlite3* database_connection_handle(nullptr);
if (sqlite3_open_v2(path.data(), &database_connection_handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) == SQLITE_OK)
if (sqlite3_open_v2(path.data(), &database_connection_handle, flags, nullptr) == SQLITE_OK)
{
ret = databaseConnections.emplace(this, database_connection_handle);
if (!ret)
Expand Down
2 changes: 1 addition & 1 deletion Server/Components/Databases/databases_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class DatabasesComponent final : public IDatabasesComponent, public NoCopy
/// @param path Path to the database
/// @param outDatabaseConnectionID Database connection ID (out)
/// @returns Database if successful, otherwise "nullptr"
IDatabaseConnection* open(StringView path) override;
IDatabaseConnection* open(StringView path, int flags = 0) override;

/// Closes the specified database connection
/// @returns "true" if database connection has been successfully closed, otherwise "false"
Expand Down
95 changes: 91 additions & 4 deletions Server/Components/Pawn/Scripting/Database/Natives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,95 @@
#include <ghc/filesystem.hpp>
#include "../../format.hpp"

static int getFlags(cell* params)
{
// Get the flags.
if (params[0] >= 2 * sizeof(cell))
{
// Optional parameter.
return params[2];
}
else
{
// Defer the defaults to the implementation.
return 0;
AmyrAhmady marked this conversation as resolved.
Show resolved Hide resolved
}
}

static IDatabaseConnection* doDBOpen(const std::string& name, int flags)
{
size_t start;
size_t end;

// Get the protocol.
String protocol = name.substr(0, 5);
if (protocol == "file:")
{
// We always use an aboslute path, even when a relative path is given.
protocol = "file:///";
// URI mode.
if (name[5] == '/' && name[6] == '/')
{
// Skip the next `/`.
start = name.find('/', 7) + 1;
if (start == 0)
{
return 0;
}
}
else
{
start = 5;
}
}
else
{
protocol = "";
start = 0;
}

// Get the parameters.
String parameters;
end = name.find('?', start);
if (end == std::string::npos)
{
parameters = "";
end = name.length();
}
else
{
// There are parameters.
parameters = name.substr(end);
}

// Get the path.
String path = name.substr(start, end - start);

// Get the database.
if ((flags & 0x80 /* SQLITE_OPEN_MEMORY */) != 0 || path == ":memory:" || path == "" || parameters.find("mode=memory") != std::string::npos)
{
// All the ways of opening an in-memory database that I know of.
return PawnManager::Get()->databases->open(name, flags);
}
// Should we allow this?
AmyrAhmady marked this conversation as resolved.
Show resolved Hide resolved
//else if (protocol == "file:///")
//{
// return PawnManager::Get()->databases->open(name, flags);
//}
else
{
// TODO: Pass in the flags.
ghc::filesystem::path dbFilePath = ghc::filesystem::absolute("scriptfiles/" + path);
return PawnManager::Get()->databases->open(protocol + dbFilePath.string() + parameters, flags);
}
}

SCRIPT_API(db_open, int(const std::string& name))
{
ghc::filesystem::path dbFilePath = ghc::filesystem::absolute("scriptfiles/" + name);
IDatabaseConnection* database_connection(PawnManager::Get()->databases->open(dbFilePath.string()));
// Get the flags.
auto params = GetParams();
int flags = getFlags(params);
IDatabaseConnection* database_connection = doDBOpen(name, flags);
return database_connection ? database_connection->getID() : 0;
}

Expand Down Expand Up @@ -123,8 +208,10 @@ SCRIPT_API(db_debug_openresults, int())

SCRIPT_API(DB_Open, int(const std::string& name))
{
ghc::filesystem::path dbFilePath = ghc::filesystem::absolute("scriptfiles/" + name);
IDatabaseConnection* database_connection(PawnManager::Get()->databases->open(dbFilePath.string()));
// Get the flags.
auto params = GetParams();
int flags = getFlags(params);
IDatabaseConnection* database_connection = doDBOpen(name, flags);
return database_connection ? database_connection->getID() : 0;
}

Expand Down