feat: redcap server side export filter validation

This commit is contained in:
Andreas Gammelgaard Damsbo 2026-03-30 20:19:52 +02:00
commit c28a3d0a6d
No known key found for this signature in database
2 changed files with 471 additions and 12 deletions

View file

@ -0,0 +1,72 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/redcap_read_shiny_module.R
\name{validate_redcap_filter}
\alias{validate_redcap_filter}
\title{Validate a REDCap server-side filter string against a data dictionary}
\usage{
validate_redcap_filter(filter, dictionary)
}
\arguments{
\item{filter}{A single character string containing the filter expression,
e.g. \code{"[age] > 18"} or \code{"[cohabitation] = '1' AND [age] > 18"}.}
\item{dictionary}{A data frame representing the REDCap data dictionary in
API export format, as returned by e.g. \code{REDCapCAST::get_redcap_metadata()}.
Must contain at least the columns \code{field_name} and \code{field_type}.
The columns \code{text_validation_type_or_show_slider_number} and
\code{select_choices_or_calculations} are used when present for stricter
type and choice validation.}
}
\value{
A named list with two elements:
\describe{
\item{\code{valid}}{Logical. \code{TRUE} if the filter passes all checks.}
\item{\code{message}}{Character. \code{"Filter is valid."} on success, or
a newline-separated string of error messages describing every problem
found.}
}
}
\description{
Checks that a REDCap filter expression is syntactically correct and
consistent with the field types defined in the project data dictionary.
Plain text without field references is always rejected. Multi-clause
filters joined by \code{AND} or \code{OR} are supported.
}
\details{
Validation rules by field type:
\describe{
\item{\code{calc}}{Numeric fields. Value must be an unquoted number.
All comparison operators (\code{=}, \code{!=}, \code{<}, \code{>},
\code{<=}, \code{>=}) are accepted.}
\item{\code{text} with date validation}{Fields with validation type
\code{date_ymd}, \code{date_dmy}, \code{datetime_*}, etc. Value must be
a quoted date/datetime string in \code{'YYYY-MM-DD'} format. All
comparison operators are accepted.}
\item{\code{text} with time validation}{Fields with validation type
\code{time_hh_mm_ss} or \code{time_mm_ss}. Value must be a quoted time
string, e.g. \code{'14:30:00'}. All comparison operators are accepted.}
\item{\code{radio} / \code{dropdown}}{Categorical fields. Value must be a
quoted choice code (e.g. \code{'1'}) that exists in the field's choice
list. Only \code{=} and \code{!=} are accepted.}
\item{\code{text} (plain)}{Free-text fields. Value must be a quoted string.
Only \code{=} and \code{!=} are accepted.}
}
}
\examples{
\dontrun{
dict <- REDCapCAST::get_redcap_metadata(
uri = "https://redcap.example.com/api/",
token = Sys.getenv("REDCAP_TOKEN")
)
validate_redcap_filter("[age] > 18", dict)
#> list(valid = TRUE, message = "Filter is valid.")
validate_redcap_filter("only plain text", dict)
#> list(valid = FALSE, message = "Filter must contain at least one field ...")
validate_redcap_filter("[cohabitation] = '1' AND [age] > 18", dict)
#> list(valid = TRUE, message = "Filter is valid.")
}
}