Serenity Operating System
at master 100 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Vector.h> 8#include <LibCore/StandardPaths.h> 9#include <LibSQL/Result.h> 10#include <SQLServer/ConnectionFromClient.h> 11#include <SQLServer/DatabaseConnection.h> 12#include <SQLServer/SQLStatement.h> 13 14namespace SQLServer { 15 16static HashMap<int, RefPtr<ConnectionFromClient>> s_connections; 17 18RefPtr<ConnectionFromClient> ConnectionFromClient::client_connection_for(int client_id) 19{ 20 if (s_connections.contains(client_id)) 21 return *s_connections.get(client_id).value(); 22 dbgln_if(SQLSERVER_DEBUG, "Invalid client_id {}", client_id); 23 return nullptr; 24} 25 26void ConnectionFromClient::set_database_path(DeprecatedString database_path) 27{ 28 m_database_path = move(database_path); 29} 30 31ConnectionFromClient::ConnectionFromClient(NonnullOwnPtr<Core::LocalSocket> socket, int client_id) 32 : IPC::ConnectionFromClient<SQLClientEndpoint, SQLServerEndpoint>(*this, move(socket), client_id) 33 , m_database_path(DeprecatedString::formatted("{}/sql", Core::StandardPaths::data_directory())) 34{ 35 s_connections.set(client_id, *this); 36} 37 38void ConnectionFromClient::die() 39{ 40 s_connections.remove(client_id()); 41 42 if (on_disconnect) 43 on_disconnect(); 44} 45 46Messages::SQLServer::ConnectResponse ConnectionFromClient::connect(DeprecatedString const& database_name) 47{ 48 dbgln_if(SQLSERVER_DEBUG, "ConnectionFromClient::connect(database_name: {})", database_name); 49 50 if (auto database_connection = DatabaseConnection::create(m_database_path, database_name, client_id()); !database_connection.is_error()) 51 return { database_connection.value()->connection_id() }; 52 return Optional<SQL::ConnectionID> {}; 53} 54 55void ConnectionFromClient::disconnect(SQL::ConnectionID connection_id) 56{ 57 dbgln_if(SQLSERVER_DEBUG, "ConnectionFromClient::disconnect(connection_id: {})", connection_id); 58 auto database_connection = DatabaseConnection::connection_for(connection_id); 59 if (database_connection) 60 database_connection->disconnect(); 61 else 62 dbgln("Database connection has disappeared"); 63} 64 65Messages::SQLServer::PrepareStatementResponse ConnectionFromClient::prepare_statement(SQL::ConnectionID connection_id, DeprecatedString const& sql) 66{ 67 dbgln_if(SQLSERVER_DEBUG, "ConnectionFromClient::prepare_statement(connection_id: {}, sql: '{}')", connection_id, sql); 68 69 auto database_connection = DatabaseConnection::connection_for(connection_id); 70 if (!database_connection) { 71 dbgln("Database connection has disappeared"); 72 return Optional<SQL::StatementID> {}; 73 } 74 75 auto result = database_connection->prepare_statement(sql); 76 if (result.is_error()) { 77 dbgln_if(SQLSERVER_DEBUG, "Could not parse SQL statement: {}", result.error().error_string()); 78 return Optional<SQL::StatementID> {}; 79 } 80 81 dbgln_if(SQLSERVER_DEBUG, "ConnectionFromClient::prepare_statement -> statement_id = {}", result.value()); 82 return { result.value() }; 83} 84 85Messages::SQLServer::ExecuteStatementResponse ConnectionFromClient::execute_statement(SQL::StatementID statement_id, Vector<SQL::Value> const& placeholder_values) 86{ 87 dbgln_if(SQLSERVER_DEBUG, "ConnectionFromClient::execute_query_statement(statement_id: {})", statement_id); 88 89 auto statement = SQLStatement::statement_for(statement_id); 90 if (statement && statement->connection()->client_id() == client_id()) { 91 // FIXME: Support taking parameters from IPC requests. 92 return statement->execute(move(const_cast<Vector<SQL::Value>&>(placeholder_values))); 93 } 94 95 dbgln_if(SQLSERVER_DEBUG, "Statement has disappeared"); 96 async_execution_error(statement_id, -1, SQL::SQLErrorCode::StatementUnavailable, DeprecatedString::formatted("{}", statement_id)); 97 return Optional<SQL::ExecutionID> {}; 98} 99 100}