diff options
Diffstat (limited to 'Userland/Services/SQLServer/DatabaseConnection.cpp')
-rw-r--r-- | Userland/Services/SQLServer/DatabaseConnection.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/Userland/Services/SQLServer/DatabaseConnection.cpp b/Userland/Services/SQLServer/DatabaseConnection.cpp new file mode 100644 index 0000000000..e1ffebeec9 --- /dev/null +++ b/Userland/Services/SQLServer/DatabaseConnection.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, Jan de Visser <jan@de-visser.net> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/LexicalPath.h> +#include <SQLServer/ClientConnection.h> +#include <SQLServer/DatabaseConnection.h> +#include <SQLServer/SQLStatement.h> + +namespace SQLServer { + +static HashMap<int, NonnullRefPtr<DatabaseConnection>> s_connections; + +RefPtr<DatabaseConnection> DatabaseConnection::connection_for(int 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; +} + +static int s_next_connection_id = 0; + +DatabaseConnection::DatabaseConnection(String database_name, int client_id) + : Object() + , m_database_name(move(database_name)) + , m_connection_id(s_next_connection_id++) + , m_client_id(client_id) +{ + LexicalPath path(database_name); + if (path.title() != database_name) { + auto client_connection = ClientConnection::client_connection_for(m_client_id); + client_connection->async_connection_error(m_connection_id, (int)SQL::SQLErrorCode::InvalidDatabaseName, m_database_name); + return; + } + + dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection {} initiating connection with database '{}'", connection_id(), m_database_name); + s_connections.set(m_connection_id, *this); + deferred_invoke([&](Object&) { + m_database = SQL::Database::construct(String::formatted("/home/anon/sql/{}.db", m_database_name)); + m_accept_statements = true; + auto client_connection = ClientConnection::client_connection_for(client_id); + if (client_connection) + client_connection->async_connected(m_connection_id); + else + warnln("Cannot notify client of database connection. Client disconnected"); + }); +} + +void DatabaseConnection::disconnect() +{ + dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection::disconnect(connection_id {}, database '{}'", connection_id(), m_database_name); + m_accept_statements = false; + deferred_invoke([&](Object&) { + m_database = nullptr; + s_connections.remove(m_connection_id); + auto client_connection = ClientConnection::client_connection_for(client_id()); + if (client_connection) + client_connection->async_disconnected(m_connection_id); + else + warnln("Cannot notify client of database disconnection. Client disconnected"); + }); +} + +int DatabaseConnection::sql_statement(String const& sql) +{ + dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection::sql_statement(connection_id {}, database '{}', sql '{}'", connection_id(), m_database_name, sql); + auto client_connection = ClientConnection::client_connection_for(client_id()); + if (!client_connection) { + warnln("Cannot notify client of database disconnection. Client disconnected"); + return -1; + } + if (!m_accept_statements) { + client_connection->async_execution_error(-1, (int)SQL::SQLErrorCode::DatabaseUnavailable, m_database_name); + return -1; + } + auto statement = SQLStatement::construct(*this, sql); + return statement->statement_id(); +} + +} |