Database.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Copyright (c) 2022-2023, Tim Flynn <trflynn89@serenityos.org>
  3. * Copyright (c) 2023, Jelle Raaijmakers <jelle@gmta.nl>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/Error.h>
  9. #include <AK/Function.h>
  10. #include <AK/HashMap.h>
  11. #include <AK/NonnullRefPtr.h>
  12. #include <AK/Optional.h>
  13. #include <AK/RefCounted.h>
  14. #include <AK/StringView.h>
  15. #include <AK/Vector.h>
  16. #include <LibCore/Promise.h>
  17. #include <LibSQL/SQLClient.h>
  18. #include <LibSQL/Type.h>
  19. #include <LibSQL/Value.h>
  20. namespace WebView {
  21. class Database : public RefCounted<Database> {
  22. using OnResult = Function<void(ReadonlySpan<SQL::Value>)>;
  23. using OnComplete = Function<void()>;
  24. using OnError = Function<void(StringView)>;
  25. public:
  26. static ErrorOr<NonnullRefPtr<Database>> create();
  27. #if !defined(AK_OS_SERENITY)
  28. static ErrorOr<NonnullRefPtr<Database>> create(Vector<String> candidate_sql_server_paths);
  29. #endif
  30. ErrorOr<SQL::StatementID> prepare_statement(StringView statement);
  31. template<typename... PlaceholderValues>
  32. void execute_statement(SQL::StatementID statement_id, OnResult on_result, OnComplete on_complete, OnError on_error, PlaceholderValues&&... placeholder_values)
  33. {
  34. auto sync_promise = Core::Promise<Empty>::construct();
  35. PendingExecution pending_execution {
  36. .on_result = move(on_result),
  37. .on_complete = [sync_promise, on_complete = move(on_complete)] {
  38. if (on_complete)
  39. on_complete();
  40. sync_promise->resolve({}); },
  41. .on_error = [sync_promise, on_error = move(on_error)](auto message) {
  42. if (on_error)
  43. on_error(message);
  44. sync_promise->resolve({}); },
  45. };
  46. Vector<SQL::Value> values { SQL::Value(forward<PlaceholderValues>(placeholder_values))... };
  47. execute_statement(statement_id, move(values), move(pending_execution));
  48. MUST(sync_promise->await());
  49. }
  50. private:
  51. static ErrorOr<NonnullRefPtr<Database>> create(NonnullRefPtr<SQL::SQLClient>);
  52. struct ExecutionKey {
  53. constexpr bool operator==(ExecutionKey const&) const = default;
  54. SQL::StatementID statement_id { 0 };
  55. SQL::ExecutionID execution_id { 0 };
  56. };
  57. struct PendingExecution {
  58. OnResult on_result { nullptr };
  59. OnComplete on_complete { nullptr };
  60. OnError on_error { nullptr };
  61. };
  62. struct ExecutionKeyTraits : public Traits<ExecutionKey> {
  63. static constexpr unsigned hash(ExecutionKey const& key)
  64. {
  65. return pair_int_hash(u64_hash(key.statement_id), u64_hash(key.execution_id));
  66. }
  67. };
  68. Database(NonnullRefPtr<SQL::SQLClient> sql_client, SQL::ConnectionID connection_id);
  69. void execute_statement(SQL::StatementID statement_id, Vector<SQL::Value> placeholder_values, PendingExecution pending_execution);
  70. template<typename ResultData>
  71. auto take_pending_execution(ResultData const& result_data)
  72. {
  73. return m_pending_executions.take({ result_data.statement_id, result_data.execution_id });
  74. }
  75. NonnullRefPtr<SQL::SQLClient> m_sql_client;
  76. SQL::ConnectionID m_connection_id { 0 };
  77. HashMap<ExecutionKey, PendingExecution, ExecutionKeyTraits> m_pending_executions;
  78. };
  79. }