mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-07 19:57:45 +03:00
12152a4556
Currently, we create a new SQL::Database object for each database we are requested to open. When multiple clients connect to the same database, the same underlying database file is opened and cached each time. This results in updates from one client not being propagated to others. To prevent this, when a database is requested to be open, check if it is already open. We can then re-use that SQL::Database object for the new connection.
76 lines
2.8 KiB
C++
76 lines
2.8 KiB
C++
/*
|
|
* Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/LexicalPath.h>
|
|
#include <SQLServer/DatabaseConnection.h>
|
|
#include <SQLServer/SQLStatement.h>
|
|
|
|
namespace SQLServer {
|
|
|
|
static HashMap<SQL::ConnectionID, NonnullRefPtr<DatabaseConnection>> s_connections;
|
|
static SQL::ConnectionID s_next_connection_id = 0;
|
|
|
|
static ErrorOr<NonnullRefPtr<SQL::Database>> find_or_create_database(StringView database_path, StringView database_name)
|
|
{
|
|
for (auto const& connection : s_connections) {
|
|
if (connection.value->database_name() == database_name)
|
|
return connection.value->database();
|
|
}
|
|
|
|
auto database_file = DeprecatedString::formatted("{}/{}.db", database_path, database_name);
|
|
return SQL::Database::try_create(move(database_file));
|
|
}
|
|
|
|
RefPtr<DatabaseConnection> DatabaseConnection::connection_for(SQL::ConnectionID connection_id)
|
|
{
|
|
if (s_connections.contains(connection_id))
|
|
return *s_connections.get(connection_id).value();
|
|
dbgln_if(SQLSERVER_DEBUG, "Invalid connection_id {}", connection_id);
|
|
return nullptr;
|
|
}
|
|
|
|
ErrorOr<NonnullRefPtr<DatabaseConnection>> DatabaseConnection::create(StringView database_path, DeprecatedString database_name, int client_id)
|
|
{
|
|
if (LexicalPath path(database_name); (path.title() != database_name) || (path.dirname() != "."))
|
|
return Error::from_string_view("Invalid database name"sv);
|
|
|
|
auto database = TRY(find_or_create_database(database_path, database_name));
|
|
|
|
if (auto result = database->open(); result.is_error()) {
|
|
warnln("Could not open database: {}", result.error().error_string());
|
|
return Error::from_string_view("Could not open database"sv);
|
|
}
|
|
|
|
return adopt_nonnull_ref_or_enomem(new (nothrow) DatabaseConnection(move(database), move(database_name), client_id));
|
|
}
|
|
|
|
DatabaseConnection::DatabaseConnection(NonnullRefPtr<SQL::Database> database, DeprecatedString database_name, int client_id)
|
|
: Object()
|
|
, m_database(move(database))
|
|
, m_database_name(move(database_name))
|
|
, m_connection_id(s_next_connection_id++)
|
|
, m_client_id(client_id)
|
|
{
|
|
dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection {} initiatedconnection with database '{}'", connection_id(), m_database_name);
|
|
s_connections.set(m_connection_id, *this);
|
|
}
|
|
|
|
void DatabaseConnection::disconnect()
|
|
{
|
|
dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection::disconnect(connection_id {}, database '{}'", connection_id(), m_database_name);
|
|
s_connections.remove(connection_id());
|
|
}
|
|
|
|
SQL::ResultOr<SQL::StatementID> DatabaseConnection::prepare_statement(StringView sql)
|
|
{
|
|
dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection::prepare_statement(connection_id {}, database '{}', sql '{}'", connection_id(), m_database_name, sql);
|
|
|
|
auto statement = TRY(SQLStatement::create(*this, sql));
|
|
return statement->statement_id();
|
|
}
|
|
|
|
}
|