Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions R/data.table.R
Original file line number Diff line number Diff line change
Expand Up @@ -2986,20 +2986,33 @@ setcolorder = function(x, neworder=key(x), before=NULL, after=NULL, skip_absent=
invisible(x)
}

.set_needs_alloccol = function(x, value) {
.set_needs_alloccol = function(x, j, value) {
# set() will try to resize x when adding or removing columns
# when removing a column, value can be NULL or list with NULLs inside
removing = is.null(value) || (is.list(value) && length(value) == length(j) && any(vapply_1b(value, is.null)))
# columns can be created by name
adding = if (is.character(j)) {
jexists = j %chin% names(x)
!all(jexists)
} else FALSE

if (!(removing || adding)) return(FALSE)

# automatically allocate more space when tl <= ncol (either full or loaded from disk)
if (truelength(x) <= length(x)) return(TRUE)
if (selfrefok(x, verbose=FALSE) >= 1L) return(FALSE)
# value can be NULL or list with NULLs inside
if (is.null(value)) return(TRUE)
if (!is.list(value)) return(FALSE)
any(vapply_1b(value, is.null))
# (or if a resize operation would otherwise fail)
if (selfrefok(x, verbose=FALSE) < 1L || truelength(x) <= length(x))
return(TRUE)

if (adding)
return(truelength(x) < length(x) + sum(!jexists))

FALSE
}

set = function(x,i=NULL,j,value) # low overhead, loopable
{
# If removing columns from a table that's not selfrefok, need to call setalloccol first, #7488
if (.set_needs_alloccol(x, value)) {
if (.set_needs_alloccol(x, j, value)) {
name = substitute(x)
setalloccol(x, verbose=FALSE)
if (is.name(name)) {
Expand Down
12 changes: 12 additions & 0 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -21497,3 +21497,15 @@ test(2363.1, foverlaps(x, y, by.x, by.y), foverlaps(x, y2, by.x, by.y))
test(2363.2, foverlaps(x, y2, by.x, by.y, type="any", mult="all"), foverlaps(x, y2, by.x, by.y, type="any", mult="first"))
test(2363.3, foverlaps(x, y, by.x, by.y, which=TRUE, mult="first", nomatch=NULL), foverlaps(x, y2, by.x, by.y, which=TRUE, mult="first", nomatch=NULL))
rm(x, y, y2)

# internal use of set() causes non-resizable data.tables to be re-assigned in the wrong frame, #7604
# bmerge -> coerce_col
x = structure(list(a = as.double(2:3), b = list("foo", "bar")), class = c("data.table", "data.frame"))
y = structure(list(a = 1:3), class = c("data.table", "data.frame"))
test(2364.1, x[y, on = "a"], data.table(a = 1:3, b = list(NULL, "foo", "bar")))
x = structure(list(a = factor("a", levels = letters)), class = c("data.table", "data.frame"))
y = data.table(a = factor("a", levels = letters))
setdroplevels(x)
setdroplevels(y)
test(2364.2, levels(x$a), levels(y$a))
rm(x, y)
Loading