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 | |
22 | namespace duckdb { |
23 | class Appender; |
24 | class Catalog; |
25 | class DuckDB; |
26 | class PreparedStatementData; |
27 | class Relation; |
28 | |
29 | //! The ClientContext holds information relevant to the current client session |
30 | //! during execution |
31 | class ClientContext { |
32 | public: |
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 | |
62 | public: |
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 | |
108 | private: |
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 | |
137 | private: |
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 | |