ちゃんと追ってないけど、print()
するにせよcollect()
するにせよ結局collect.tbl_sql()
が呼ばれるっぽい。
その実装はこう。dbSendQuery()
とかdbFetch
が実質的なやりとりをする。
collect.tbl_sql <- function(x, ..., n = 1e5, warn_incomplete = TRUE) { assert_that(length(n) == 1, n > 0L) if (n == Inf) { n <- -1 } sql <- sql_render(x) res <- dbSendQuery(x$src$con, sql) on.exit(dbClearResult(res)) out <- dbFetch(res, n) if (warn_incomplete) { res_warn_incomplete(res, "n = Inf") } grouped_df(out, groups(x)) }
sql_render
はgeneric functionで、tbl_sql()
の場合はsql_render.tbl_sql
が呼ばれる。
なので、独自の処理をしたければ、S3のクラスとして独自のクラスをtbl_sql
より先において、sql_render.独自のクラス()
というメソッドをつくればこっちがdispatchされる。なのでこのsql
にはたぶん文字列だけじゃなくて任意のオブジェクトを含めることができる。
問題は次の行。DBIはS4なので結構縛りが厳しい。dbSendQuery()
が受け付ける引数の型も固定されてそう、と思って調べると、案の定。characterしか受け付けない。
setMethod( "dbSendStatement", signature("DBIConnection", "character"), function(conn, statement, ...) { dbSendQuery(conn, statement, ...) } )
つまり、dbSendQuery()
に任意のパラメータを指定したい場合はcollect()
の処理自体を変える必要があるのでcollect.独自クラス()
をつくる必要がある。
指定するのが文字列だけでいいならdbSendQuery()
の中でごにょごにょやれば大丈夫。たぶん。なので、SQLへの変換部分さえがんばることができれば↓これはdplyrでうまく動く可能性がある。