也许让您感到困惑的是 dplyr 函数tbl
并且filter
实际上并没有将任何代码发送到数据库以供执行。当你跑
tbl(con, "table1") %>% filter(col1 > 12)
返回的是一个包含 sql 查询的 tbl_dbi 对象。当您在 R 中以交互方式运行这行代码时,返回的 tbl_dbi 对象随后被传递给print
函数。为了打印 tbl_dbi,必须在数据库中执行查询。您可以通过将输出保存到变量来看到这一点。
q <- tbl(con, "table1") %>% filter(col1 > 12)
class(q)
在上述两行中,没有任何内容发送到数据库。该tbl
函数返回一个 tbl_dbi 对象并过滤器修改了该 tbl_dbi 对象。最后将结果保存到变量q
中。当我们打印时q
,SQL 被发送到数据库。所以该tbl
函数不需要知道在它之后调用的任何其他 dplyr 函数(就像filter
在这种情况下)。无论如何,它的行为都是一样的。它总是返回一个 tbl_dbi 对象。
现在 dbplyr 如何从更简单的查询构建更复杂的查询已经超出了我的理解。
这是一些实现您的示例的代码。
library(dplyr)
shoppingList <- function(x){
stopifnot(is.character(x))
class(x) <- c("first", "shoppingList", class(x))
x
}
item <- function(x, y){
if("first" %in% class(x)){
out <- paste(x, y)
} else {
out <- paste0(x, " and ", y)
}
class(out) <- c("shoppingList", class(out))
out
}
print.shoppingList <- function(x){
# code that only runs when we print an object of class shoppingList
if("first" %in% class(x)) x <- paste(x, "nothing")
print(paste0("***", x, "***"))
}
shoppingList("I need to get")
#> [1] "***I need to get nothing***"
shoppingList("I need to get") %>% item("apples") %>% item("oranges")
#> [1] "***I need to get apples and oranges***"
但是怎么print
知道向数据库发送SQL呢?我的(过于简单化的)概念性答案是,它print
是一个通用函数,其行为会根据传入的对象类而有所不同。实际上有很多print
函数。在上面的示例中,我为shoppingList类的对象创建了一个特殊的打印函数。您可以想象一个特殊的print.tbl_dbi
函数,它知道如何处理 tbl_dbi 对象,方法是将它们包含的查询发送到它们连接的数据库,然后打印结果。我认为实际的实现更复杂,但希望这能提供一些直觉。