1#include "duckdb/main/materialized_query_result.hpp"
2#include "duckdb/common/to_string.hpp"
3#include "duckdb/main/client_context.hpp"
4#include "duckdb/common/box_renderer.hpp"
5
6namespace duckdb {
7
8MaterializedQueryResult::MaterializedQueryResult(StatementType statement_type, StatementProperties properties,
9 vector<string> names_p, unique_ptr<ColumnDataCollection> collection_p,
10 ClientProperties client_properties)
11 : QueryResult(QueryResultType::MATERIALIZED_RESULT, statement_type, std::move(properties), collection_p->Types(),
12 std::move(names_p), std::move(client_properties)),
13 collection(std::move(collection_p)), scan_initialized(false) {
14}
15
16MaterializedQueryResult::MaterializedQueryResult(PreservedError error)
17 : QueryResult(QueryResultType::MATERIALIZED_RESULT, std::move(error)), scan_initialized(false) {
18}
19
20string MaterializedQueryResult::ToString() {
21 string result;
22 if (success) {
23 result = HeaderToString();
24 result += "[ Rows: " + to_string(val: collection->Count()) + "]\n";
25 auto &coll = Collection();
26 for (auto &row : coll.Rows()) {
27 for (idx_t col_idx = 0; col_idx < coll.ColumnCount(); col_idx++) {
28 if (col_idx > 0) {
29 result += "\t";
30 }
31 auto val = row.GetValue(column_index: col_idx);
32 result += val.IsNull() ? "NULL" : StringUtil::Replace(source: val.ToString(), from: string("\0", 1), to: "\\0");
33 }
34 result += "\n";
35 }
36 result += "\n";
37 } else {
38 result = GetError() + "\n";
39 }
40 return result;
41}
42
43string MaterializedQueryResult::ToBox(ClientContext &context, const BoxRendererConfig &config) {
44 if (!success) {
45 return GetError() + "\n";
46 }
47 if (!collection) {
48 return "Internal error - result was successful but there was no collection";
49 }
50 BoxRenderer renderer(config);
51 return renderer.ToString(context, names, op: Collection());
52}
53
54Value MaterializedQueryResult::GetValue(idx_t column, idx_t index) {
55 if (!row_collection) {
56 row_collection = make_uniq<ColumnDataRowCollection>(args: collection->GetRows());
57 }
58 return row_collection->GetValue(column, index);
59}
60
61idx_t MaterializedQueryResult::RowCount() const {
62 return collection ? collection->Count() : 0;
63}
64
65ColumnDataCollection &MaterializedQueryResult::Collection() {
66 if (HasError()) {
67 throw InvalidInputException("Attempting to get collection from an unsuccessful query result\n: Error %s",
68 GetError());
69 }
70 if (!collection) {
71 throw InternalException("Missing collection from materialized query result");
72 }
73 return *collection;
74}
75
76unique_ptr<DataChunk> MaterializedQueryResult::Fetch() {
77 return FetchRaw();
78}
79
80unique_ptr<DataChunk> MaterializedQueryResult::FetchRaw() {
81 if (HasError()) {
82 throw InvalidInputException("Attempting to fetch from an unsuccessful query result\nError: %s", GetError());
83 }
84 auto result = make_uniq<DataChunk>();
85 collection->InitializeScanChunk(chunk&: *result);
86 if (!scan_initialized) {
87 // we disallow zero copy so the chunk is independently usable even after the result is destroyed
88 collection->InitializeScan(state&: scan_state, properties: ColumnDataScanProperties::DISALLOW_ZERO_COPY);
89 scan_initialized = true;
90 }
91 collection->Scan(state&: scan_state, result&: *result);
92 if (result->size() == 0) {
93 return nullptr;
94 }
95 return result;
96}
97
98} // namespace duckdb
99