@@ -13,7 +13,7 @@ rollup.data.table = function(x, j, by, .SDcols, id = FALSE, label = NULL, ...) {
1313 sets = lapply(length(by ): 0L , function (i ) by [0L : i ])
1414 # redirect to workhorse function
1515 jj = substitute(j )
16- groupingsets.data.table(x , by = by , sets = sets , .SDcols = .SDcols , id = id , jj = jj , label = label )
16+ groupingsets.data.table(x , by = by , sets = sets , .SDcols = .SDcols , id = id , jj = jj , label = label , enclos = parent.frame() )
1717}
1818
1919cube = function (x , ... ) {
@@ -35,13 +35,13 @@ cube.data.table = function(x, j, by, .SDcols, id = FALSE, label = NULL, ...) {
3535 sets = lapply((2L ^ n ): 1L , function (jj ) by [keepBool [jj , ]])
3636 # redirect to workhorse function
3737 jj = substitute(j )
38- groupingsets.data.table(x , by = by , sets = sets , .SDcols = .SDcols , id = id , jj = jj , label = label )
38+ groupingsets.data.table(x , by = by , sets = sets , .SDcols = .SDcols , id = id , jj = jj , label = label , enclos = parent.frame() )
3939}
4040
4141groupingsets = function (x , ... ) {
4242 UseMethod(" groupingsets" )
4343}
44- groupingsets.data.table = function (x , j , by , sets , .SDcols , id = FALSE , jj , label = NULL , ... ) {
44+ groupingsets.data.table = function (x , j , by , sets , .SDcols , id = FALSE , jj , label = NULL , enclos = parent.frame(), ... ) {
4545 # input data type basic validation
4646 if (! is.data.table(x ))
4747 stopf(" Argument 'x' must be a data.table object" )
@@ -112,7 +112,10 @@ groupingsets.data.table = function(x, j, by, sets, .SDcols, id = FALSE, jj, labe
112112 .SDcols = if (" .SD" %chin % av ) setdiff(names(x ), by ) else NULL
113113 if (length(names(by ))) by = unname(by )
114114 # 0 rows template data.table to keep colorder and type
115- empty = if (length(.SDcols )) x [0L , eval(jj ), by , .SDcols = .SDcols ] else x [0L , eval(jj ), by ]
115+ # inline all arguments that might clash with enclosing environment
116+ pcall = substitute(x [0L , jj , by ], list (x = x , jj = jj , by = by ))
117+ if (length(.SDcols )) pcall $ .SDcols = .SDcols
118+ empty = eval(pcall , list (.datatable.aware = TRUE ), enclos )
116119 if (id && " grouping" %chin % names(empty )) # `j` could have been evaluated to `grouping` field
117120 stopf(" When using `id=TRUE` the 'j' expression must not evaluate to a column named 'grouping'." )
118121 if (anyDuplicated(names(empty )) > 0L )
@@ -150,8 +153,12 @@ groupingsets.data.table = function(x, j, by, sets, .SDcols, id = FALSE, jj, labe
150153 stopf(" Using integer64 class columns require to have 'bit64' package installed." ) # nocov
151154 int64.by.cols = intersect(int64.cols , by )
152155 # aggregate function called for each grouping set
156+ # inline all arguments that might clash with enclosing environment
157+ pcall = substitute(x [, jj ], list (x = x , jj = jj ))
158+ if (length(.SDcols )) pcall $ .SDcols = .SDcols
153159 aggregate.set = function (by.set ) {
154- r = if (length(.SDcols )) x [, eval(jj ), by.set , .SDcols = .SDcols ] else x [, eval(jj ), by.set ]
160+ pcall $ by = by.set
161+ r = eval(pcall , list (.datatable.aware = TRUE ), enclos )
155162 if (id ) {
156163 # integer bit mask of aggregation levels: http://www.postgresql.org/docs/9.5/static/functions-aggregate.html#FUNCTIONS-GROUPING-TABLE
157164 # 3267: strtoi("", base = 2L) output apparently unstable across platforms
0 commit comments