summaryrefslogtreecommitdiff
path: root/Userland/Services/SQLServer/DatabaseConnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Services/SQLServer/DatabaseConnection.cpp')
-rw-r--r--Userland/Services/SQLServer/DatabaseConnection.cpp83
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();
+}
+
+}