Skip to content

Commit 3e63790

Browse files
committed
Merge branch 'r-0.7-13' into production
2 parents b18a6d1 + 4a72fb5 commit 3e63790

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+17629
-27560
lines changed

.Rbuildignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ inst\/doc\/DBI\.b..$
2323
^scripts$
2424
^tic\.R$
2525
^_pkgdown\.yml$
26+
^revdep/
27+
^API$

API

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# API for DBI package
2+
3+
## Exported functions
4+
5+
ANSI()
6+
SQL(x)
7+
SQLKeywords(dbObj, ...)
8+
dbBegin(conn, ...)
9+
dbBind(res, params, ...)
10+
dbBreak()
11+
dbCallProc(conn, ...)
12+
dbClearResult(res, ...)
13+
dbColumnInfo(res, ...)
14+
dbCommit(conn, ...)
15+
dbConnect(drv, ...)
16+
dbDataType(dbObj, obj, ...)
17+
dbDisconnect(conn, ...)
18+
dbDriver(drvName, ...)
19+
dbExecute(conn, statement, ...)
20+
dbExistsTable(conn, name, ...)
21+
dbFetch(res, n = -1, ...)
22+
dbGetDBIVersion()
23+
dbGetException(conn, ...)
24+
dbGetInfo(dbObj, ...)
25+
dbGetQuery(conn, statement, ...)
26+
dbGetRowCount(res, ...)
27+
dbGetRowsAffected(res, ...)
28+
dbGetStatement(res, ...)
29+
dbHasCompleted(res, ...)
30+
dbIsValid(dbObj, ...)
31+
dbListConnections(drv, ...)
32+
dbListFields(conn, name, ...)
33+
dbListResults(conn, ...)
34+
dbListTables(conn, ...)
35+
dbQuoteIdentifier(conn, x, ...)
36+
dbQuoteLiteral(conn, x, ...)
37+
dbQuoteString(conn, x, ...)
38+
dbReadTable(conn, name, ...)
39+
dbRemoveTable(conn, name, ...)
40+
dbRollback(conn, ...)
41+
dbSendQuery(conn, statement, ...)
42+
dbSendStatement(conn, statement, ...)
43+
dbSetDataMappings(res, flds, ...)
44+
dbUnloadDriver(drv, ...)
45+
dbWithTransaction(conn, code, ...)
46+
dbWriteTable(conn, name, value, ...)
47+
fetch(res, n = -1, ...)
48+
isSQLKeyword(dbObj, name, keywords = .SQL92Keywords, case = c("lower", "upper", "any")[3], ...)
49+
isSQLKeyword.default(name, keywords = .SQL92Keywords, case = c("lower", "upper", "any")[3])
50+
make.db.names(dbObj, snames, keywords = .SQL92Keywords, unique = TRUE, allow.keywords = TRUE, ...)
51+
make.db.names.default(snames, keywords = .SQL92Keywords, unique = TRUE, allow.keywords = TRUE)
52+
sqlAppendTable(con, table, values, row.names = NA, ...)
53+
sqlAppendTableTemplate(con, table, values, row.names = NA, prefix = "?", ...)
54+
sqlColumnToRownames(df, row.names = NA)
55+
sqlCommentSpec(start, end, endRequired)
56+
sqlCreateTable(con, table, fields, row.names = NA, temporary = FALSE, ...)
57+
sqlData(con, value, row.names = NA, ...)
58+
sqlInterpolate(conn, sql, ..., .dots = list())
59+
sqlParseVariables(conn, sql, ...)
60+
sqlParseVariablesImpl(sql, quotes, comments)
61+
sqlQuoteSpec(start, end, escape, doubleEscape = TRUE)
62+
sqlRownamesToColumn(df, row.names = NA)
63+
64+
## Exported data
65+
66+
.SQL92Keywords: character (character[220])

DESCRIPTION

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: DBI
2-
Version: 0.7-12
3-
Date: 2017-08-10
2+
Version: 0.7-13
3+
Date: 2017-11-27
44
Title: R Database Interface
55
Description: A database interface definition for communication
66
between R and relational database management systems. All
@@ -27,9 +27,9 @@ Suggests:
2727
xml2
2828
Encoding: UTF-8
2929
License: LGPL (>= 2)
30-
URL: http://rstats-db.github.io/DBI
31-
URLNote: https://github.com/rstats-db/DBI
32-
BugReports: https://github.com/rstats-db/DBI/issues
30+
URL: http://r-dbi.github.io/DBI
31+
URLNote: https://github.com/r-dbi/DBI
32+
BugReports: https://github.com/r-dbi/DBI/issues
3333
Collate:
3434
'DBObject.R'
3535
'DBDriver.R'
@@ -48,7 +48,6 @@ Collate:
4848
'table-insert.R'
4949
'table.R'
5050
'transactions.R'
51-
'util.R'
5251
VignetteBuilder: knitr
53-
Roxygen: list(markdown = TRUE)
52+
Roxygen: list(markdown = TRUE, roclets = c("collate", "namespace", "rd", "pkgapi::api_roclet"))
5453
RoxygenNote: 6.0.1

NAMESPACE

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export(dbListFields)
3232
export(dbListResults)
3333
export(dbListTables)
3434
export(dbQuoteIdentifier)
35+
export(dbQuoteLiteral)
3536
export(dbQuoteString)
3637
export(dbReadTable)
3738
export(dbRemoveTable)
@@ -47,7 +48,6 @@ export(isSQLKeyword)
4748
export(isSQLKeyword.default)
4849
export(make.db.names)
4950
export(make.db.names.default)
50-
export(print.list.pairs)
5151
export(sqlAppendTable)
5252
export(sqlAppendTableTemplate)
5353
export(sqlColumnToRownames)
@@ -70,6 +70,7 @@ exportMethods(dbFetch)
7070
exportMethods(dbGetQuery)
7171
exportMethods(dbListFields)
7272
exportMethods(dbQuoteIdentifier)
73+
exportMethods(dbQuoteLiteral)
7374
exportMethods(dbQuoteString)
7475
exportMethods(dbReadTable)
7576
exportMethods(dbSendStatement)

NEWS.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## DBI 0.7-13 (2017-11-27)
2+
3+
- The deprecated `print.list.pairs()` has been removed.
4+
- Fix `dbDataType()` for `AsIs` object (#198, @yutannihilation).
5+
- Point to db.rstudio.com (@wibeasley, #209).
6+
- Reflect new 'r-dbi' organization in `DESCRIPTION` (@wibeasley, #207).
7+
- Using switchpatch on the second argument for default implementations of `dbQuoteString()` and `dbQuoteIdentifier()`.
8+
- New `dbQuoteLiteral()` generic. The default implementation uses switchpatch to avoid dispatch ambiguities, and forwards to `dbQuoteString()` for character vectors. Backends may override methods that also dispatch on the second argument, but in this case also an override for the `"SQL"` class is necessary (#172).
9+
- Fix `dbQuoteString()` and `dbQuoteIdentifier()` to ignore invalid UTF-8 strings (r-dbi/DBItest#156).
10+
11+
112
## DBI 0.7-12 (2017-08-10)
213

314
- Add default implementation of `dbListFields()`.

R/data-types.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ check_raw_list <- function(x) {
2323
}
2424

2525
as_is_data_type <- function(x) {
26-
dbiDataType(unclass(x))
26+
oldClass(x) <- oldClass(x)[-1]
27+
dbiDataType(x)
2728
}
2829

2930
setOldClass("difftime")

R/quote.R

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,19 @@ setGeneric("dbQuoteIdentifier",
9090

9191
#' @rdname hidden_aliases
9292
#' @export
93-
setMethod("dbQuoteIdentifier", c("DBIConnection", "character"),
93+
setMethod("dbQuoteIdentifier", "DBIConnection",
9494
function(conn, x, ...) {
95+
if (is(x, "SQL")) return(x)
96+
if (is(x, "Table")) {
97+
return(SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = ".")))
98+
}
99+
if (!is.character(x)) stop("x must be character or SQL", call. = FALSE)
100+
95101
if (any(is.na(x))) {
96102
stop("Cannot pass NA to dbQuoteIdentifier()", call. = FALSE)
97103
}
98-
x <- gsub('"', '""', x, fixed = TRUE)
104+
# Avoid fixed = TRUE due to https://github.com/r-dbi/DBItest/issues/156
105+
x <- gsub('"', '""', enc2utf8(x))
99106
if (length(x) == 0L) {
100107
SQL(character())
101108
} else {
@@ -105,14 +112,6 @@ setMethod("dbQuoteIdentifier", c("DBIConnection", "character"),
105112
}
106113
)
107114

108-
#' @rdname hidden_aliases
109-
#' @export
110-
setMethod("dbQuoteIdentifier", c("DBIConnection", "SQL"),
111-
function(conn, x, ...) {
112-
x
113-
}
114-
)
115-
116115
#' Quote literal strings
117116
#'
118117
#' Call this method to generate a string that is suitable for
@@ -150,9 +149,13 @@ setGeneric("dbQuoteString",
150149

151150
#' @rdname hidden_aliases
152151
#' @export
153-
setMethod("dbQuoteString", c("DBIConnection", "character"),
152+
setMethod("dbQuoteString", "DBIConnection",
154153
function(conn, x, ...) {
155-
x <- gsub("'", "''", x, fixed = TRUE)
154+
if (is(x, "SQL")) return(x)
155+
if (!is.character(x)) stop("x must be character or SQL", call. = FALSE)
156+
157+
# Avoid fixed = TRUE due to https://github.com/r-dbi/DBItest/issues/156
158+
x <- gsub("'", "''", enc2utf8(x))
156159

157160
if (length(x) == 0L) {
158161
SQL(character())
@@ -166,10 +169,77 @@ setMethod("dbQuoteString", c("DBIConnection", "character"),
166169
}
167170
)
168171

172+
#' Quote literal values
173+
#'
174+
#' @description
175+
#' Call these methods to generate a string that is suitable for
176+
#' use in a query as a literal value of the correct type, to make sure that you
177+
#' generate valid SQL and avoid SQL injection.
178+
#'
179+
#' @inheritParams dbQuoteString
180+
#' @param x A vector to quote as string.
181+
#'
182+
#' @inherit DBItest::spec_sql_quote_literal return
183+
#' @inheritSection DBItest::spec_sql_quote_literal Specification
184+
#'
185+
#' @family DBIResult generics
186+
#' @export
187+
#' @examples
188+
#' # Quoting ensures that arbitrary input is safe for use in a query
189+
#' name <- "Robert'); DROP TABLE Students;--"
190+
#' dbQuoteLiteral(ANSI(), name)
191+
#'
192+
#' # NAs become NULL
193+
#' dbQuoteLiteral(ANSI(), c(1:3, NA))
194+
#'
195+
#' # Logicals become integers by default
196+
#' dbQuoteLiteral(ANSI(), c(TRUE, FALSE, NA))
197+
#'
198+
#' # Raw vectors become hex strings by default
199+
#' dbQuoteLiteral(ANSI(), list(as.raw(1:3), NULL))
200+
#'
201+
#' # SQL vectors are always passed through as is
202+
#' var_name <- SQL("select")
203+
#' var_name
204+
#' dbQuoteLiteral(ANSI(), var_name)
205+
#'
206+
#' # This mechanism is used to prevent double escaping
207+
#' dbQuoteLiteral(ANSI(), dbQuoteLiteral(ANSI(), name))
208+
setGeneric("dbQuoteLiteral",
209+
def = function(conn, x, ...) standardGeneric("dbQuoteLiteral")
210+
)
211+
212+
213+
169214
#' @rdname hidden_aliases
170215
#' @export
171-
setMethod("dbQuoteString", c("DBIConnection", "SQL"),
216+
setMethod("dbQuoteLiteral", "DBIConnection",
172217
function(conn, x, ...) {
173-
x
218+
# Switchpatching to avoid ambiguous S4 dispatch, so that our method
219+
# is used only if no alternatives are available.
220+
221+
if (is(x, "SQL")) return(x)
222+
223+
if (is.character(x)) return(dbQuoteString(conn, x))
224+
225+
if (is.list(x)) {
226+
blob_data <- vapply(
227+
x,
228+
function(x) {
229+
if (is.null(x)) "NULL"
230+
else if (is.raw(x)) paste0("X'", paste(format(x), collapse = ""), "'")
231+
else {
232+
stop("Lists must contain raw vectors or NULL", call. = FALSE)
233+
}
234+
},
235+
character(1)
236+
)
237+
return(SQL(blob_data))
238+
}
239+
240+
if (is.logical(x)) x <- as.numeric(x)
241+
x <- as.character(x)
242+
x[is.na(x)] <- "NULL"
243+
SQL(x)
174244
}
175245
)

R/table.R

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@ Table <- function(...) {
1111
new("Table", name = c(...))
1212
}
1313

14-
#' @rdname hidden_aliases
15-
#' @param conn,x Connection and Table used when escaping.
16-
#' @export
17-
setMethod("dbQuoteIdentifier", c("DBIConnection", "Table"),
18-
function(conn, x, ...) {
19-
SQL(paste0(dbQuoteIdentifier(conn, x@name), collapse = "."))
20-
}
21-
)
22-
2314
#' @rdname hidden_aliases
2415
#' @param object Table object to print
2516
#' @export

R/util.R

Lines changed: 0 additions & 23 deletions
This file was deleted.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# DBI
22

3-
[![Build Status](https://travis-ci.org/rstats-db/DBI.png?branch=master)](https://travis-ci.org/rstats-db/DBI) [![Coverage Status](https://codecov.io/gh/rstats-db/DBI/branch/master/graph/badge.svg)](https://codecov.io/github/rstats-db/DBI?branch=master) [![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/DBI)](https://cran.r-project.org/package=DBI)
3+
[![Build Status](https://travis-ci.org/r-dbi/DBI.png?branch=master)](https://travis-ci.org/r-dbi/DBI) [![Coverage Status](https://codecov.io/gh/r-dbi/DBI/branch/master/graph/badge.svg)](https://codecov.io/github/r-dbi/DBI?branch=master) [![CRAN_Status_Badge](http://www.r-pkg.org/badges/version/DBI)](https://cran.r-project.org/package=DBI)
44

55
The DBI package defines a common interface between the R and database management systems (DBMS). The interface defines a small set of classes and methods similar in spirit to Perl's [DBI](http://dbi.perl.org/), Java's [JDBC](http://www.oracle.com/technetwork/java/javase/jdbc/index.html), Python's [DB-API](http://www.python.org/dev/peps/pep-0249/), and Microsoft's [ODBC](http://en.wikipedia.org/wiki/ODBC). It defines a set of classes and methods defines what operations are possible and how they are performed:
66

@@ -46,9 +46,9 @@ dbDisconnect(con)
4646
To install DBI:
4747

4848
* Get the released version from CRAN: `install.packages("DBI")`
49-
* Get the development version from github: `devtools::install_github("rstats-db/DBI")`
49+
* Get the development version from github: `devtools::install_github("r-dbi/DBI")`
5050

51-
Discussions associated with DBI and related database packages take place on [R-SIG-DB](https://stat.ethz.ch/mailman/listinfo/r-sig-db).
51+
Discussions associated with DBI and related database packages take place on [R-SIG-DB](https://stat.ethz.ch/mailman/listinfo/r-sig-db). The website [Databases using R](http://db.rstudio.com/) describes the tools and best practices in this ecosystem.
5252

5353
## Class structure
5454

0 commit comments

Comments
 (0)