1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/main/client_context.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/catalog/catalog_set.hpp"
12#include "duckdb/catalog/catalog_entry/schema_catalog_entry.hpp"
13#include "duckdb/execution/execution_context.hpp"
14#include "duckdb/main/query_profiler.hpp"
15#include "duckdb/main/stream_query_result.hpp"
16#include "duckdb/main/prepared_statement.hpp"
17#include "duckdb/main/table_description.hpp"
18#include "duckdb/transaction/transaction_context.hpp"
19#include "duckdb/common/unordered_set.hpp"
20#include <random>
21
22namespace duckdb {
23class Appender;
24class Catalog;
25class DuckDB;
26class PreparedStatementData;
27class Relation;
28
29//! The ClientContext holds information relevant to the current client session
30//! during execution
31class ClientContext {
32public:
33 ClientContext(DuckDB &database);
34
35 //! Query profiler
36 QueryProfiler profiler;
37 //! The database that this client is connected to
38 DuckDB &db;
39 //! Data for the currently running transaction
40 TransactionContext transaction;
41 //! Whether or not the query is interrupted
42 bool interrupted;
43 //! Whether or not the ClientContext has been invalidated because the underlying database is destroyed
44 bool is_invalidated = false;
45 //! Lock on using the ClientContext in parallel
46 std::mutex context_lock;
47
48 ExecutionContext execution_context;
49
50 Catalog &catalog;
51 unique_ptr<SchemaCatalogEntry> temporary_objects;
52 unique_ptr<CatalogSet> prepared_statements;
53
54 // Whether or not aggressive query verification is enabled
55 bool query_verification_enabled = false;
56 //! Enable the running of optimizers
57 bool enable_optimizer = true;
58
59 //! The random generator used by random(). Its seed value can be set by setseed().
60 std::mt19937 random_engine;
61
62public:
63 Transaction &ActiveTransaction() {
64 return transaction.ActiveTransaction();
65 }
66
67 //! Interrupt execution of a query
68 void Interrupt();
69 //! Enable query profiling
70 void EnableProfiling();
71 //! Disable query profiling
72 void DisableProfiling();
73
74 //! Issue a query, returning a QueryResult. The QueryResult can be either a StreamQueryResult or a
75 //! MaterializedQueryResult. The StreamQueryResult will only be returned in the case of a successful SELECT
76 //! statement.
77 unique_ptr<QueryResult> Query(string query, bool allow_stream_result);
78 //! Fetch a query from the current result set (if any)
79 unique_ptr<DataChunk> Fetch();
80 //! Cleanup the result set (if any).
81 void Cleanup();
82 //! Invalidate the client context. The current query will be interrupted and the client context will be invalidated,
83 //! making it impossible for future queries to run.
84 void Invalidate();
85
86 //! Get the table info of a specific table, or nullptr if it cannot be found
87 unique_ptr<TableDescription> TableInfo(string schema_name, string table_name);
88 //! Appends a DataChunk to the specified table. Returns whether or not the append was successful.
89 void Append(TableDescription &description, DataChunk &chunk);
90 //! Try to bind a relation in the current client context; either throws an exception or fills the result_columns
91 //! list with the set of returned columns
92 void TryBindRelation(Relation &relation, vector<ColumnDefinition> &result_columns);
93
94 //! Execute a relation
95 unique_ptr<QueryResult> Execute(shared_ptr<Relation> relation);
96
97 //! Prepare a query
98 unique_ptr<PreparedStatement> Prepare(string query);
99 //! Execute a prepared statement with the given name and set of parameters
100 unique_ptr<QueryResult> Execute(string name, vector<Value> &values, bool allow_stream_result = true,
101 string query = string());
102 //! Removes a prepared statement from the set of prepared statements in the client context
103 void RemovePreparedStatement(PreparedStatement *statement);
104
105 void RegisterAppender(Appender *appender);
106 void RemoveAppender(Appender *appender);
107
108private:
109 //! Perform aggressive query verification of a SELECT statement. Only called when query_verification_enabled is
110 //! true.
111 string VerifyQuery(string query, unique_ptr<SQLStatement> statement);
112
113 void InitialCleanup();
114 //! Internal clean up, does not lock. Caller must hold the context_lock.
115 void CleanupInternal();
116 string FinalizeQuery(bool success);
117 //! Internal fetch, does not lock. Caller must hold the context_lock.
118 unique_ptr<DataChunk> FetchInternal();
119 //! Internally execute a set of SQL statement. Caller must hold the context_lock.
120 unique_ptr<QueryResult> RunStatements(const string &query, vector<unique_ptr<SQLStatement>> &statements,
121 bool allow_stream_result);
122 //! Internally prepare and execute a prepared SQL statement. Caller must hold the context_lock.
123 unique_ptr<QueryResult> RunStatement(const string &query, unique_ptr<SQLStatement> statement,
124 bool allow_stream_result);
125
126 //! Internally prepare a SQL statement. Caller must hold the context_lock.
127 unique_ptr<PreparedStatementData> CreatePreparedStatement(const string &query, unique_ptr<SQLStatement> statement);
128 //! Internally execute a prepared SQL statement. Caller must hold the context_lock.
129 unique_ptr<QueryResult> ExecutePreparedStatement(const string &query, PreparedStatementData &statement,
130 vector<Value> bound_values, bool allow_stream_result);
131 //! Call CreatePreparedStatement() and ExecutePreparedStatement() without any bound values
132 unique_ptr<QueryResult> RunStatementInternal(const string &query, unique_ptr<SQLStatement> statement,
133 bool allow_stream_result);
134
135 template <class T> void RunFunctionInTransaction(T &&fun);
136
137private:
138 idx_t prepare_count = 0;
139 //! The currently opened StreamQueryResult (if any)
140 StreamQueryResult *open_result = nullptr;
141 //! Prepared statement objects that were created using the ClientContext::Prepare method
142 unordered_set<PreparedStatement *> prepared_statement_objects;
143 //! Appenders that were attached to this client context
144 unordered_set<Appender *> appenders;
145};
146} // namespace duckdb
147