Skip to content

Commit ad65976

Browse files
authored
feat: New rel_explain_df() and rel_tostring() (#587)
1 parent ea8cb5f commit ad65976

File tree

7 files changed

+340
-29
lines changed

7 files changed

+340
-29
lines changed

R/cpp11.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,16 @@ rapi_rel_to_df <- function(rel) {
116116
.Call(`_duckdb_rapi_rel_to_df`, rel)
117117
}
118118

119-
rapi_rel_tostring <- function(rel) {
120-
.Call(`_duckdb_rapi_rel_tostring`, rel)
119+
rapi_rel_tostring <- function(rel, format) {
120+
.Call(`_duckdb_rapi_rel_tostring`, rel, format)
121121
}
122122

123123
rapi_rel_to_sql <- function(rel) {
124124
.Call(`_duckdb_rapi_rel_to_sql`, rel)
125125
}
126126

127-
rapi_rel_explain <- function(rel) {
128-
.Call(`_duckdb_rapi_rel_explain`, rel)
127+
rapi_rel_explain <- function(rel, type, format) {
128+
.Call(`_duckdb_rapi_rel_explain`, rel, type, format)
129129
}
130130

131131
rapi_rel_alias <- function(rel) {

R/relational.R

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ rel_from_df <- function(con, df, experimental=FALSE) {
8686

8787
#' @export
8888
print.duckdb_relation <- function(x, ...) {
89-
message("DuckDB Relation: \n", rethrow_rapi_rel_tostring(x))
89+
message("DuckDB Relation: \n", rapi_rel_tostring(x))
9090
}
9191

9292
#' @export
@@ -347,10 +347,40 @@ rel_sql <- function(rel, sql) {
347347
#' rel <- rel_from_df(con, mtcars)
348348
#' rel_explain(rel)
349349
rel_explain <- function(rel) {
350-
cat(rethrow_rapi_rel_explain(rel)[[2]][[1]])
350+
# Legacy
351+
cat(rethrow_rapi_rel_explain(rel, "EXPLAIN_STANDARD", "DEFAULT")[[2]][[1]])
351352
invisible(NULL)
352353
}
353354

355+
#' Return the EXPLAIN output for a DuckDB relation object as a data frame
356+
#' @param rel the DuckDB relation object
357+
#' @noRd
358+
#' @examples
359+
#' con <- DBI::dbConnect(duckdb())
360+
#' rel <- rel_from_df(con, mtcars)
361+
#' rel_explain(rel)
362+
rel_explain_df <- function(
363+
rel,
364+
type = c("standard", "analyze"),
365+
format = c("default", "text", "json", "html", "graphviz")
366+
) {
367+
type <- match.arg(type)
368+
format <- match.arg(format)
369+
rethrow_rapi_rel_explain(rel, paste0("EXPLAIN_", toupper(type)), toupper(format))
370+
}
371+
372+
#' Format a DuckDB relation object as a string
373+
#' @param rel the DuckDB relation object
374+
#' @noRd
375+
#' @examples
376+
#' con <- DBI::dbConnect(duckdb())
377+
#' rel <- rel_from_df(con, mtcars)
378+
#' rel_tostring(rel)
379+
rel_tostring <- function(rel, format = c("full", "tree")) {
380+
format <- match.arg(format)
381+
rethrow_rapi_rel_tostring(rel, format)
382+
}
383+
354384
#' Get the internal alias for a DuckDB relation object
355385
#' @param rel the DuckDB relation object
356386
#' @noRd

R/rethrow-gen.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,9 +261,9 @@ rethrow_rapi_rel_to_df <- function(rel, call = parent.frame(2)) {
261261
)
262262
}
263263

264-
rethrow_rapi_rel_tostring <- function(rel, call = parent.frame(2)) {
264+
rethrow_rapi_rel_tostring <- function(rel, format, call = parent.frame(2)) {
265265
rlang::try_fetch(
266-
rapi_rel_tostring(rel),
266+
rapi_rel_tostring(rel, format),
267267
error = function(e) {
268268
rethrow_error_from_rapi(e, call)
269269
}
@@ -279,9 +279,9 @@ rethrow_rapi_rel_to_sql <- function(rel, call = parent.frame(2)) {
279279
)
280280
}
281281

282-
rethrow_rapi_rel_explain <- function(rel, call = parent.frame(2)) {
282+
rethrow_rapi_rel_explain <- function(rel, type, format, call = parent.frame(2)) {
283283
rlang::try_fetch(
284-
rapi_rel_explain(rel),
284+
rapi_rel_explain(rel, type, format),
285285
error = function(e) {
286286
rethrow_error_from_rapi(e, call)
287287
}

src/cpp11.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ extern "C" SEXP _duckdb_rapi_rel_to_df(SEXP rel) {
217217
END_CPP11
218218
}
219219
// relational.cpp
220-
std::string rapi_rel_tostring(duckdb::rel_extptr_t rel);
221-
extern "C" SEXP _duckdb_rapi_rel_tostring(SEXP rel) {
220+
std::string rapi_rel_tostring(duckdb::rel_extptr_t rel, std::string format);
221+
extern "C" SEXP _duckdb_rapi_rel_tostring(SEXP rel, SEXP format) {
222222
BEGIN_CPP11
223-
return cpp11::as_sexp(rapi_rel_tostring(cpp11::as_cpp<cpp11::decay_t<duckdb::rel_extptr_t>>(rel)));
223+
return cpp11::as_sexp(rapi_rel_tostring(cpp11::as_cpp<cpp11::decay_t<duckdb::rel_extptr_t>>(rel), cpp11::as_cpp<cpp11::decay_t<std::string>>(format)));
224224
END_CPP11
225225
}
226226
// relational.cpp
@@ -231,10 +231,10 @@ extern "C" SEXP _duckdb_rapi_rel_to_sql(SEXP rel) {
231231
END_CPP11
232232
}
233233
// relational.cpp
234-
SEXP rapi_rel_explain(duckdb::rel_extptr_t rel);
235-
extern "C" SEXP _duckdb_rapi_rel_explain(SEXP rel) {
234+
SEXP rapi_rel_explain(duckdb::rel_extptr_t rel, std::string type, std::string format);
235+
extern "C" SEXP _duckdb_rapi_rel_explain(SEXP rel, SEXP type, SEXP format) {
236236
BEGIN_CPP11
237-
return cpp11::as_sexp(rapi_rel_explain(cpp11::as_cpp<cpp11::decay_t<duckdb::rel_extptr_t>>(rel)));
237+
return cpp11::as_sexp(rapi_rel_explain(cpp11::as_cpp<cpp11::decay_t<duckdb::rel_extptr_t>>(rel), cpp11::as_cpp<cpp11::decay_t<std::string>>(type), cpp11::as_cpp<cpp11::decay_t<std::string>>(format)));
238238
END_CPP11
239239
}
240240
// relational.cpp
@@ -470,7 +470,7 @@ static const R_CallMethodDef CallEntries[] = {
470470
{"_duckdb_rapi_rel_aggregate", (DL_FUNC) &_duckdb_rapi_rel_aggregate, 3},
471471
{"_duckdb_rapi_rel_alias", (DL_FUNC) &_duckdb_rapi_rel_alias, 1},
472472
{"_duckdb_rapi_rel_distinct", (DL_FUNC) &_duckdb_rapi_rel_distinct, 1},
473-
{"_duckdb_rapi_rel_explain", (DL_FUNC) &_duckdb_rapi_rel_explain, 1},
473+
{"_duckdb_rapi_rel_explain", (DL_FUNC) &_duckdb_rapi_rel_explain, 3},
474474
{"_duckdb_rapi_rel_filter", (DL_FUNC) &_duckdb_rapi_rel_filter, 2},
475475
{"_duckdb_rapi_rel_from_altrep_df", (DL_FUNC) &_duckdb_rapi_rel_from_altrep_df, 3},
476476
{"_duckdb_rapi_rel_from_df", (DL_FUNC) &_duckdb_rapi_rel_from_df, 3},
@@ -491,7 +491,7 @@ static const R_CallMethodDef CallEntries[] = {
491491
{"_duckdb_rapi_rel_to_df", (DL_FUNC) &_duckdb_rapi_rel_to_df, 1},
492492
{"_duckdb_rapi_rel_to_parquet", (DL_FUNC) &_duckdb_rapi_rel_to_parquet, 2},
493493
{"_duckdb_rapi_rel_to_sql", (DL_FUNC) &_duckdb_rapi_rel_to_sql, 1},
494-
{"_duckdb_rapi_rel_tostring", (DL_FUNC) &_duckdb_rapi_rel_tostring, 1},
494+
{"_duckdb_rapi_rel_tostring", (DL_FUNC) &_duckdb_rapi_rel_tostring, 2},
495495
{"_duckdb_rapi_rel_union_all", (DL_FUNC) &_duckdb_rapi_rel_union_all, 2},
496496
{"_duckdb_rapi_release", (DL_FUNC) &_duckdb_rapi_release, 1},
497497
{"_duckdb_rapi_shutdown", (DL_FUNC) &_duckdb_rapi_shutdown, 1},

src/relational.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
#include "cpp11.hpp"
2-
#include "duckdb.hpp"
1+
#include "rapi.hpp"
32
#include "signal.hpp"
43
#include "typesr.hpp"
5-
#include "rapi.hpp"
64

75
#include "R_ext/Random.h"
86

@@ -12,9 +10,6 @@
1210
#include "duckdb/parser/expression/function_expression.hpp"
1311
#include "duckdb/parser/expression/comparison_expression.hpp"
1412
#include "duckdb/parser/expression/conjunction_expression.hpp"
15-
#include "duckdb/parser/expression/operator_expression.hpp"
16-
#include "duckdb/parser/expression/cast_expression.hpp"
17-
#include "duckdb/parser/expression/case_expression.hpp"
1813
#include "duckdb/parser/expression/window_expression.hpp"
1914

2015
#include "duckdb/main/relation/filter_relation.hpp"
@@ -26,8 +21,8 @@
2621
#include "duckdb/main/relation/setop_relation.hpp"
2722
#include "duckdb/main/relation/limit_relation.hpp"
2823
#include "duckdb/main/relation/distinct_relation.hpp"
29-
#include "duckdb/main/relation/table_function_relation.hpp"
3024

25+
#include "duckdb/common/enum_util.hpp"
3126
#include "duckdb/common/enums/joinref_type.hpp"
3227

3328
using namespace duckdb;
@@ -432,16 +427,22 @@ static SEXP result_to_df(duckdb::unique_ptr<QueryResult> res) {
432427
return result_to_df(std::move(res));
433428
}
434429

435-
[[cpp11::register]] std::string rapi_rel_tostring(duckdb::rel_extptr_t rel) {
436-
return rel->rel->ToString();
430+
[[cpp11::register]] std::string rapi_rel_tostring(duckdb::rel_extptr_t rel, std::string format) {
431+
if (format == "tree") {
432+
return rel->rel->ToString(0);
433+
} else {
434+
return rel->rel->ToString();
435+
}
437436
}
438437

439438
[[cpp11::register]] std::string rapi_rel_to_sql(duckdb::rel_extptr_t rel) {
440439
return rel->rel->GetQueryNode()->ToString();
441440
}
442441

443-
[[cpp11::register]] SEXP rapi_rel_explain(duckdb::rel_extptr_t rel) {
444-
return result_to_df(rel->rel->Explain());
442+
[[cpp11::register]] SEXP rapi_rel_explain(duckdb::rel_extptr_t rel, std::string type, std::string format) {
443+
auto type_enum = EnumUtil::FromString<ExplainType>(type);
444+
auto format_enum = EnumUtil::FromString<ExplainFormat>(format);
445+
return result_to_df(rel->rel->Explain(type_enum, format_enum));
445446
}
446447

447448
[[cpp11::register]] std::string rapi_rel_alias(duckdb::rel_extptr_t rel) {

0 commit comments

Comments
 (0)