Skip to content

Commit 87079b0

Browse files
committed
fix(dataview): map R date/datetime and integer64 values to ag-grid data types
- use dateString and dateTimeString for R Date and POSIX values - use bigint for R integer64 values - make bit64 an optional package dependency
1 parent 9c7f25e commit 87079b0

3 files changed

Lines changed: 86 additions & 22 deletions

File tree

sess/DESCRIPTION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Imports:
1616
methods,
1717
rstudioapi
1818
Suggests:
19+
bit64,
1920
jgd,
2021
svglite,
2122
tinytest

sess/R/handlers.R

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -329,14 +329,22 @@ get_column_def <- function(name, field, value) {
329329
if (!is.null(units)) {
330330
tooltip <- sprintf("%s, units: %s", tooltip, toString(units))
331331
}
332-
if (is.numeric(value)) {
332+
if (inherits(value, "integer64")) {
333+
if (!requireNamespace("bit64", quietly = TRUE)) {
334+
stop("Viewing integer64 columns requires the optional 'bit64' package")
335+
}
336+
type <- "bigintColumn"
337+
filter <- "agBigIntColumnFilter"
338+
} else if (is.numeric(value)) {
333339
type <- "numericColumn"
334340
filter <- "agNumberColumnFilter"
335-
} else if (inherits(value, "Date") ||
336-
inherits(value, "POSIXct") ||
337-
inherits(value, "POSIXlt")) {
341+
} else if (inherits(value, "Date")) {
338342
type <- "dateColumn"
339343
filter <- "agDateColumnFilter"
344+
} else if (inherits(value, "POSIXct") ||
345+
inherits(value, "POSIXlt")) {
346+
type <- "datetimeColumn"
347+
filter <- "agDateColumnFilter"
340348
} else if (is.logical(value)) {
341349
type <- "booleanColumn"
342350
filter <- TRUE
@@ -549,9 +557,22 @@ dataview_match_condition <- function(values, cond) {
549557
} else if (inherits(values, "Date") ||
550558
inherits(values, "POSIXct") ||
551559
inherits(values, "POSIXlt")) {
552-
ds <- as.Date(values)
553-
d1 <- as.Date(if (is.null(cond$dateFrom)) cond$filter else cond$dateFrom)
554-
d2 <- as.Date(if (is.null(cond$dateTo)) cond$filterTo else cond$dateTo)
560+
if (inherits(values, "Date")) {
561+
ds <- as.Date(values)
562+
d1 <- as.Date(if (is.null(cond$dateFrom)) cond$filter else cond$dateFrom)
563+
d2 <- as.Date(if (is.null(cond$dateTo)) cond$filterTo else cond$dateTo)
564+
} else {
565+
ds <- as.POSIXct(values)
566+
tz <- attr(ds, "tzone", exact = TRUE) %||% ""
567+
d1 <- as.POSIXct(
568+
if (is.null(cond$dateFrom)) cond$filter else cond$dateFrom,
569+
tz = tz
570+
)
571+
d2 <- as.POSIXct(
572+
if (is.null(cond$dateTo)) cond$filterTo else cond$dateTo,
573+
tz = tz
574+
)
575+
}
555576
result <- switch(cond_type,
556577
equals = ds == d1,
557578
notEqual = ds != d1,
@@ -563,9 +584,15 @@ dataview_match_condition <- function(values, cond) {
563584
rep(TRUE, length(values))
564585
)
565586
} else if (is.numeric(values) || is.logical(values)) {
566-
nums <- as.numeric(values)
567-
f1 <- suppressWarnings(as.numeric(cond$filter))
568-
f2 <- suppressWarnings(as.numeric(cond$filterTo))
587+
if (inherits(values, "integer64")) {
588+
nums <- values
589+
f1 <- bit64::as.integer64(cond$filter)
590+
f2 <- bit64::as.integer64(cond$filterTo)
591+
} else {
592+
nums <- as.numeric(values)
593+
f1 <- suppressWarnings(as.numeric(cond$filter))
594+
f2 <- suppressWarnings(as.numeric(cond$filterTo))
595+
}
569596
result <- switch(cond_type,
570597
equals = nums == f1,
571598
notEqual = nums != f1,
@@ -686,16 +713,27 @@ dataview_apply_sort_model <- function(state, sort_model, row_idx) {
686713
return(row_idx)
687714
}
688715

689-
order_args <- lapply(sort_specs, function(spec) spec$values)
690-
order_args[[length(order_args) + 1L]] <- row_idx
691-
decreasing <- vapply(sort_specs, function(spec) spec$decreasing, logical(1L))
692-
decreasing <- c(decreasing, FALSE)
693-
args <- c(order_args, list(
694-
na.last = TRUE,
695-
decreasing = decreasing,
696-
method = "radix"
697-
))
698-
row_idx[do.call(order, args)]
716+
row_order <- seq_along(row_idx)
717+
for (i in rev(seq_along(sort_specs))) {
718+
spec <- sort_specs[[i]]
719+
values <- spec$values[row_order]
720+
order_index <- if (inherits(values, "integer64")) {
721+
bit64::order(
722+
values,
723+
na.last = TRUE,
724+
decreasing = spec$decreasing
725+
)
726+
} else {
727+
order(
728+
values,
729+
na.last = TRUE,
730+
decreasing = spec$decreasing,
731+
method = "radix"
732+
)
733+
}
734+
row_order <- row_order[order_index]
735+
}
736+
row_idx[row_order]
699737
}
700738

701739
dataview_query_key <- function(sort_model, filter_model) {
@@ -723,6 +761,16 @@ dataview_query_indices <- function(state, sort_model, filter_model) {
723761

724762
dataview_rows <- function(state, row_idx) {
725763
page <- dataview_slice(state$data, row_idx)
764+
if (is.data.frame(page)) {
765+
for (position in seq_len(ncol(page))) {
766+
if (inherits(page[[position]], "POSIXct") ||
767+
inherits(page[[position]], "POSIXlt")) {
768+
page[[position]] <- format(page[[position]], "%Y-%m-%dT%H:%M:%S")
769+
} else if (inherits(page[[position]], "integer64")) {
770+
page[[position]] <- as.character(page[[position]])
771+
}
772+
}
773+
}
726774
rows <- cbind(
727775
data.frame(
728776
dataview_column_values(state, 1L, row_idx),

src/session.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,16 +1051,23 @@ export async function getTableHtml(webview: Webview, file: string | undefined, t
10511051
let filteredRows = init.totalRows;
10521052
let totalRows = init.totalRows;
10531053
let isFiltered = false;
1054+
const bigintFields = [];
10541055
10551056
columns.forEach((column) => {
10561057
if (column.field === '0') {
10571058
column.headerValueGetter = () =>
10581059
isFiltered ? '(' + filteredRows + '/' + totalRows + ')' : '';
10591060
}
1060-
if (column.type === 'dateColumn') {
1061+
if (column.type === 'dateColumn' || column.type === 'datetimeColumn') {
1062+
column.cellDataType =
1063+
column.type === 'dateColumn' ? 'dateString' : 'dateTimeString';
10611064
column.filter = 'agDateColumnFilter';
10621065
column.filterParams = dateFilterParams;
10631066
column.width = 200;
1067+
} else if (column.type === 'bigintColumn') {
1068+
column.cellDataType = 'bigint';
1069+
column.filter = 'agBigIntColumnFilter';
1070+
bigintFields.push(column.field);
10641071
}
10651072
if (column.type !== 'numericColumn') {
10661073
delete column.type;
@@ -1084,7 +1091,15 @@ export async function getTableHtml(webview: Webview, file: string | undefined, t
10841091
isFiltered = Object.keys(params.filterModel || {}).length > 0;
10851092
gridApi?.refreshHeader();
10861093
const resolvedLastRow = Number.isFinite(result.totalRows) ? result.totalRows : result.lastRow;
1087-
params.successCallback(result.rows || [], resolvedLastRow);
1094+
const rows = result.rows || [];
1095+
rows.forEach((row) => {
1096+
bigintFields.forEach((field) => {
1097+
if (row[field] != null) {
1098+
row[field] = BigInt(row[field]);
1099+
}
1100+
});
1101+
});
1102+
params.successCallback(rows, resolvedLastRow);
10881103
finishFetch(true);
10891104
} catch (e) {
10901105
console.error('[dataview] Failed to load page', e);

0 commit comments

Comments
 (0)