1#include "duckdb/main/capi/capi_internal.hpp"
2#include "duckdb/main/query_result.hpp"
3#include "duckdb/main/pending_query_result.hpp"
4#include "duckdb/common/preserved_error.hpp"
5
6using duckdb::make_uniq;
7using duckdb::PendingExecutionResult;
8using duckdb::PendingQueryResult;
9using duckdb::PendingStatementWrapper;
10using duckdb::PreparedStatementWrapper;
11
12duckdb_state duckdb_pending_prepared_internal(duckdb_prepared_statement prepared_statement,
13 duckdb_pending_result *out_result, bool allow_streaming) {
14 if (!prepared_statement || !out_result) {
15 return DuckDBError;
16 }
17 auto wrapper = reinterpret_cast<PreparedStatementWrapper *>(prepared_statement);
18 auto result = new PendingStatementWrapper();
19 result->allow_streaming = allow_streaming;
20 try {
21 result->statement = wrapper->statement->PendingQuery(values&: wrapper->values, allow_stream_result: allow_streaming);
22 } catch (const duckdb::Exception &ex) {
23 result->statement = make_uniq<PendingQueryResult>(args: duckdb::PreservedError(ex));
24 } catch (std::exception &ex) {
25 result->statement = make_uniq<PendingQueryResult>(args: duckdb::PreservedError(ex));
26 }
27 duckdb_state return_value = !result->statement->HasError() ? DuckDBSuccess : DuckDBError;
28 *out_result = reinterpret_cast<duckdb_pending_result>(result);
29
30 return return_value;
31}
32
33duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, duckdb_pending_result *out_result) {
34 return duckdb_pending_prepared_internal(prepared_statement, out_result, allow_streaming: false);
35}
36
37duckdb_state duckdb_pending_prepared_streaming(duckdb_prepared_statement prepared_statement,
38 duckdb_pending_result *out_result) {
39 return duckdb_pending_prepared_internal(prepared_statement, out_result, allow_streaming: true);
40}
41
42void duckdb_destroy_pending(duckdb_pending_result *pending_result) {
43 if (!pending_result || !*pending_result) {
44 return;
45 }
46 auto wrapper = reinterpret_cast<PendingStatementWrapper *>(*pending_result);
47 if (wrapper->statement) {
48 wrapper->statement->Close();
49 }
50 delete wrapper;
51 *pending_result = nullptr;
52}
53
54const char *duckdb_pending_error(duckdb_pending_result pending_result) {
55 if (!pending_result) {
56 return nullptr;
57 }
58 auto wrapper = reinterpret_cast<PendingStatementWrapper *>(pending_result);
59 if (!wrapper->statement) {
60 return nullptr;
61 }
62 return wrapper->statement->GetError().c_str();
63}
64
65duckdb_pending_state duckdb_pending_execute_task(duckdb_pending_result pending_result) {
66 if (!pending_result) {
67 return DUCKDB_PENDING_ERROR;
68 }
69 auto wrapper = reinterpret_cast<PendingStatementWrapper *>(pending_result);
70 if (!wrapper->statement) {
71 return DUCKDB_PENDING_ERROR;
72 }
73 if (wrapper->statement->HasError()) {
74 return DUCKDB_PENDING_ERROR;
75 }
76 PendingExecutionResult return_value;
77 try {
78 return_value = wrapper->statement->ExecuteTask();
79 } catch (const duckdb::Exception &ex) {
80 wrapper->statement->SetError(duckdb::PreservedError(ex));
81 return DUCKDB_PENDING_ERROR;
82 } catch (std::exception &ex) {
83 wrapper->statement->SetError(duckdb::PreservedError(ex));
84 return DUCKDB_PENDING_ERROR;
85 }
86 switch (return_value) {
87 case PendingExecutionResult::RESULT_READY:
88 return DUCKDB_PENDING_RESULT_READY;
89 case PendingExecutionResult::RESULT_NOT_READY:
90 return DUCKDB_PENDING_RESULT_NOT_READY;
91 default:
92 return DUCKDB_PENDING_ERROR;
93 }
94}
95
96duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb_result *out_result) {
97 if (!pending_result || !out_result) {
98 return DuckDBError;
99 }
100 auto wrapper = reinterpret_cast<PendingStatementWrapper *>(pending_result);
101 if (!wrapper->statement) {
102 return DuckDBError;
103 }
104
105 duckdb::unique_ptr<duckdb::QueryResult> result;
106 result = wrapper->statement->Execute();
107 wrapper->statement.reset();
108 return duckdb_translate_result(result: std::move(result), out: out_result);
109}
110