Skip to content

Commit 20993de

Browse files
authored
feat: Try materialization only once (#1066)
1 parent 1de98d4 commit 20993de

File tree

2 files changed

+40
-24
lines changed

2 files changed

+40
-24
lines changed

src/include/reltoaltrep.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,19 @@ struct AltrepRelationWrapper {
1515

1616
MaterializedQueryResult *GetQueryResult();
1717

18-
duckdb::unique_ptr<QueryResult> Materialize();
18+
void Materialize();
1919

2020
const bool allow_materialization;
2121
const size_t n_rows;
2222
const size_t n_cells;
2323

2424
rel_extptr_t rel_eptr;
2525
duckdb::shared_ptr<Relation> rel;
26-
duckdb::unique_ptr<QueryResult> res;
26+
duckdb::unique_ptr<QueryResult> mat_result;
27+
std::string mat_error;
2728
};
2829

29-
}
30+
} // namespace duckdb
3031

3132
struct RelToAltrep {
3233
static void Initialize(DllInfo *dll);

src/reltoaltrep.cpp

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#include "duckdb/main/query_result.hpp"
1717
#include "duckdb/main/relation/limit_relation.hpp"
1818

19+
#include "fmt/format.h"
20+
1921
#ifdef TRUE
2022
#undef TRUE
2123
#endif
@@ -100,16 +102,22 @@ AltrepRelationWrapper *AltrepRelationWrapper::Get(SEXP x) {
100102
return GetFromExternalPtr<AltrepRelationWrapper>(x);
101103
}
102104

103-
AltrepRelationWrapper::AltrepRelationWrapper(rel_extptr_t rel_, bool allow_materialization_, size_t n_rows_, size_t n_cells_)
104-
: allow_materialization(allow_materialization_), n_rows(n_rows_), n_cells(n_cells_), rel_eptr(rel_), rel(rel_->rel) {
105+
AltrepRelationWrapper::AltrepRelationWrapper(rel_extptr_t rel_, bool allow_materialization_, size_t n_rows_,
106+
size_t n_cells_)
107+
: allow_materialization(allow_materialization_), n_rows(n_rows_), n_cells(n_cells_), rel_eptr(rel_),
108+
rel(rel_->rel) {
105109
}
106110

107111
bool AltrepRelationWrapper::HasQueryResult() const {
108-
return (bool)res;
112+
return (bool)mat_result;
109113
}
110114

111115
MaterializedQueryResult *AltrepRelationWrapper::GetQueryResult() {
112-
if (!res) {
116+
if (!mat_error.empty()) {
117+
cpp11::stop(mat_error);
118+
}
119+
120+
if (!mat_result) {
113121
if (!allow_materialization || n_cells == 0) {
114122
cpp11::stop("Materialization is disabled, use collect() or as_tibble() to materialize.");
115123
}
@@ -121,7 +129,8 @@ MaterializedQueryResult *AltrepRelationWrapper::GetQueryResult() {
121129
}
122130

123131
auto materialize_message = Rf_GetOption(RStrings::get().materialize_message_sym, R_BaseEnv);
124-
if (Rf_isLogical(materialize_message) && Rf_length(materialize_message) == 1 && LOGICAL_ELT(materialize_message, 0) == true) {
132+
if (Rf_isLogical(materialize_message) && Rf_length(materialize_message) == 1 &&
133+
LOGICAL_ELT(materialize_message, 0) == true) {
125134
// Legacy
126135
Rprintf("duckplyr: materializing\n");
127136
}
@@ -135,12 +144,16 @@ MaterializedQueryResult *AltrepRelationWrapper::GetQueryResult() {
135144
duckdb_httplib::detail::scope_exit reset_max_expression_depth(
136145
[&]() { rel->context->GetContext()->config.max_expression_depth = old_depth; });
137146

138-
res = Materialize();
147+
Materialize();
148+
149+
if (!mat_error.empty()) {
150+
cpp11::stop(mat_error);
151+
}
139152

140153
// FIXME: Use std::experimental::scope_exit
141154
if (rel->context->GetContext()->config.max_expression_depth != old_depth * 2) {
142-
Rprintf("Internal error: max_expression_depth was changed from %" PRIu64 " to %" PRIu64 "\n",
143-
old_depth * 2, rel->context->GetContext()->config.max_expression_depth);
155+
Rprintf("Internal error: max_expression_depth was changed from %" PRIu64 " to %" PRIu64 "\n", old_depth * 2,
156+
rel->context->GetContext()->config.max_expression_depth);
144157
}
145158
rel->context->GetContext()->config.max_expression_depth = old_depth;
146159
reset_max_expression_depth.release();
@@ -151,11 +164,11 @@ MaterializedQueryResult *AltrepRelationWrapper::GetQueryResult() {
151164

152165
signal_handler.Disable();
153166
}
154-
D_ASSERT(res);
155-
return (MaterializedQueryResult *)res.get();
167+
D_ASSERT(mat_result);
168+
return (MaterializedQueryResult *)mat_result.get();
156169
}
157170

158-
duckdb::unique_ptr<QueryResult> AltrepRelationWrapper::Materialize() {
171+
void AltrepRelationWrapper::Materialize() {
159172
// Init with max value
160173
size_t max_rows = MAX_SIZE_T;
161174

@@ -178,20 +191,22 @@ duckdb::unique_ptr<QueryResult> AltrepRelationWrapper::Materialize() {
178191
auto local_res = local_rel->Execute();
179192

180193
if (local_res->HasError()) {
181-
cpp11::stop("Error evaluating duckdb query: %s", local_res->GetError().c_str());
194+
mat_error = duckdb_fmt::format("Error evaluating duckdb query: {}", local_res->GetError().c_str());
195+
return;
182196
}
183197
D_ASSERT(local_res->type == QueryResultType::MATERIALIZED_RESULT);
184198

185199
if (max_rows < MAX_SIZE_T) {
186-
auto mat_res = (MaterializedQueryResult *)local_res.get();
187-
if (mat_res->RowCount() > max_rows) {
188-
cpp11::stop("Materialization would result in more than %" PRIu64
189-
" rows. Use collect() or as_tibble() to materialize.",
190-
max_rows);
200+
auto local_mat_res = (MaterializedQueryResult *)local_res.get();
201+
if (local_mat_res->RowCount() > max_rows) {
202+
mat_error = duckdb_fmt::format(
203+
"Materialization would result in more than {} rows. Use collect() or as_tibble() to materialize.",
204+
max_rows);
205+
return;
191206
}
192207
}
193208

194-
return std::move(local_res);
209+
mat_result = std::move(local_res);
195210
}
196211

197212
struct AltrepRownamesWrapper {
@@ -403,8 +418,8 @@ size_t DoubleToSize(double d) {
403418

404419
// FIXME: Remove allow_materialization
405420
auto allow_materialization = true;
406-
auto relation_wrapper = make_shared_ptr<AltrepRelationWrapper>(rel, allow_materialization, DoubleToSize(n_rows),
407-
DoubleToSize(n_cells));
421+
auto relation_wrapper =
422+
make_shared_ptr<AltrepRelationWrapper>(rel, allow_materialization, DoubleToSize(n_rows), DoubleToSize(n_cells));
408423

409424
cpp11::writable::list data_frame;
410425
data_frame.reserve(ncols);
@@ -479,7 +494,7 @@ size_t DoubleToSize(double d) {
479494

480495
auto wrapper = GetFromExternalPtr<AltrepRownamesWrapper>(row_names);
481496
if (!allow_materialized) {
482-
if (wrapper->rel->res.get()) {
497+
if (wrapper->rel->mat_result.get()) {
483498
// We return NULL here even for strict = true
484499
// because this is expected from df_is_materialized()
485500
return R_NilValue;

0 commit comments

Comments
 (0)