вызов функции SQL в функции R

Мне интересно, можно ли вызвать функцию SQL внутри функции R?

Скажем, например, что у меня есть эти фиктивные данные и функция SQL, написанная на Postgres 9.3

CREATE TABLE tbl (
   id VARCHAR(2) PRIMARY KEY
   ,name TEXT
   ,year_born NUMERIC
   ,nationality TEXT
);

INSERT INTO tbl(id, name, year_born, nationality)
VALUES ('A1','Bill',2001,'American')
      ,('B1','Anna',1997,'Swedish')
      ,('A2','Bill',1991,'American')
      ,('B2','Anna',2004,'Swedish')
      ,('B3','Anna',1989,'Swedish')
      ,('A3','Bill',1995,'American');


CREATE FUNCTION retrieve_data(TEXT) 
RETURNS TABLE ( id VARCHAR(2), name TEXT, year_born NUMERIC, nationality TEXT ) AS 
$func$
SELECT id, name, year_born, nationality
FROM tbl
WHERE name=$1 OR nationality=$1
GROUP BY 1
ORDER BY 1
$func$ LANGUAGE sql

Я могу получить доступ к этим данным и запустить функцию в среде R через пакеты RPostgreSQL и sqldf, как показано ниже;

require(RPostgreSQL)
require(sqldf)

options(sqldf.RPostgreSQL.user = "****", 
        sqldf.RPostgreSQL.password = "****",
        sqldf.RPostgreSQL.dbname = "test_db",
        sqldf.RPostgreSQL.host = "localhost", 
        sqldf.RPostgreSQL.port = 5432)

sqldf("select * from retrieve_data('Bill')")

Но есть ли способ вызвать указанную выше функцию SQL внутри функции R, например. как;

myfunc <- function(name) {
sqldf("select * from retrieve_data(name)")
}

myfunc('Bill')

Любые указатели будут очень признательны, спасибо!

ОБНОВЛЕНИЕ

Использование префикса $fn в пакете sqldf, предложенное @G. Гротендик

myfunc2 <- function(name){
   fn$sqldf("select * from retrieve_data('$name')")
}

Или замените приведенный выше options на приведенный ниже код, чтобы он соответствовал предложенному ответу @dickoa.

require(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv,
                 user="****",
                 password="****",
                 dbname="test_db",
                 host="localhost",
                 port=5432)

person jO.    schedule 23.01.2014    source источник
comment
Попробуйте fn$sqldf("select * from retrieve_data($name)") как в примере 5 на главной странице sqldf: code.google.com/p /sqldf/#Example_5._Insert_Variables   -  person G. Grothendieck    schedule 24.01.2014


Ответы (1)


Хитрость заключается в использовании shQuote и sprintf, но я уверен, что есть умный способ сделать это.

library(sqldf)
library(RPostgreSQL)

options(sqldf.RPostgreSQL.user = "****",
        sqldf.RPostgreSQL.dbname = "****",
        sqldf.RPostgreSQL.host = "localhost",
        sqldf.RPostgreSQL.port = 5432)

myfunc <- function(name)
    sqldf(sprintf("select * from retrieve_data(%s)", shQuote(name)))

myfunc('Bill')
##   id name year_born nationality
## 1 A1 Bill      2001    American
## 2 A2 Bill      1991    American
## 3 A3 Bill      1995    American

Если вы хотите избежать цитирования строки, вы можете использовать

drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname = "tempdb")
myfunc2 <- function(name)
    dbGetQuery(con, "select * from retrieve_data($1)", name)

myfunc2("Bill")
##   id name year_born nationality
## 1 A1 Bill      2001    American
## 2 A2 Bill      1991    American
## 3 A3 Bill      1995    American
person dickoa    schedule 23.01.2014
comment
Я думаю, вы бы предпочли postgresqlEscapeStrings вместо shQuote, потому что вам нужны кавычки, специфичные для SQL (и postgresql), а не для оболочки командной строки. (Хотя я не уверен, что вы используете в качестве аргумента con в этом случае.) - person Brian Diggs; 23.01.2014
comment
@BrianDiggs Это основная проблема, я не знаю, как найти объект типа con, используя sqlf. Я отредактировал и предложил более чистый подход - person dickoa; 23.01.2014