123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- /*
- * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/LexicalPath.h>
- #include <SQLServer/ConnectionFromClient.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(DeprecatedString database_name, int client_id)
- : Object()
- , m_database_name(move(database_name))
- , m_connection_id(s_next_connection_id++)
- , m_client_id(client_id)
- {
- if (LexicalPath path(m_database_name); (path.title() != m_database_name) || (path.dirname() != ".")) {
- auto client_connection = ConnectionFromClient::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([this]() {
- m_database = SQL::Database::construct(DeprecatedString::formatted("/home/anon/sql/{}.db", m_database_name));
- auto client_connection = ConnectionFromClient::client_connection_for(m_client_id);
- if (auto maybe_error = m_database->open(); maybe_error.is_error()) {
- client_connection->async_connection_error(m_connection_id, to_underlying(maybe_error.error().error()), maybe_error.error().error_string());
- return;
- }
- m_accept_statements = true;
- if (client_connection)
- client_connection->async_connected(m_connection_id, m_database_name);
- 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([this]() {
- m_database = nullptr;
- s_connections.remove(m_connection_id);
- auto client_connection = ConnectionFromClient::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");
- });
- }
- SQL::ResultOr<int> DatabaseConnection::prepare_statement(StringView sql)
- {
- dbgln_if(SQLSERVER_DEBUG, "DatabaseConnection::prepare_statement(connection_id {}, database '{}', sql '{}'", connection_id(), m_database_name, sql);
- if (!m_accept_statements)
- return SQL::Result { SQL::SQLCommand::Unknown, SQL::SQLErrorCode::DatabaseUnavailable };
- auto client_connection = ConnectionFromClient::client_connection_for(client_id());
- if (!client_connection) {
- warnln("Cannot notify client of database disconnection. Client disconnected");
- return SQL::Result { SQL::SQLCommand::Unknown, SQL::SQLErrorCode::InternalError, "Client disconnected"sv };
- }
- auto statement = TRY(SQLStatement::create(*this, sql));
- return statement->statement_id();
- }
- }
|