diff --git a/Rlabkey/DESCRIPTION b/Rlabkey/DESCRIPTION index 62beef7..fe58ab1 100755 --- a/Rlabkey/DESCRIPTION +++ b/Rlabkey/DESCRIPTION @@ -1,6 +1,6 @@ Package: Rlabkey -Version: 3.4.5 -Date: 2026-01-20 +Version: 3.4.6 +Date: 2026-02-17 Title: Data Exchange Between R and 'LabKey' Server Authors@R: c(person(given = "Peter", family = "Hussey", diff --git a/Rlabkey/NEWS b/Rlabkey/NEWS index 7c08239..c804471 100644 --- a/Rlabkey/NEWS +++ b/Rlabkey/NEWS @@ -1,3 +1,7 @@ +Changes in 3.4.6 + o Incorporate new filter types for Array (Multi-value text choice) fields + o Update listToMatrix to handle cases where the list elements are an array of strings, which will return a comma separated string in the response + Changes in 3.4.5 o Switch to using path first URLs for LabKey server requests. o Utilize httr to generate request query parameters. diff --git a/Rlabkey/R/makeFilter.R b/Rlabkey/R/makeFilter.R index b815936..758b486 100755 --- a/Rlabkey/R/makeFilter.R +++ b/Rlabkey/R/makeFilter.R @@ -32,6 +32,13 @@ makeFilter <- function(..., asList=FALSE) # These operators require a data value # + # Array-valued column operators + "ARRAY_CONTAINS_ALL"="arraycontainsall", + "ARRAY_CONTAINS_ANY"="arraycontainsany", + "ARRAY_CONTAINS_EXACT"="arraymatches", + "ARRAY_CONTAINS_NOT_EXACT"="arraynotmatches", + "ARRAY_CONTAINS_NONE"="arraycontainsnone", + "EQUALS"="eq", "EQUAL"="eq", "DATE_EQUAL"="dateeq", @@ -90,6 +97,9 @@ makeFilter <- function(..., asList=FALSE) # These are the "no data value" operators # + "ARRAY_ISEMPTY"="arrayisempty", + "ARRAY_ISNOTEMPTY"="arrayisnotempty", + "ISBLANK"="isblank", "IS_MISSING"="isblank", "MISSING"="isblank", diff --git a/Rlabkey/man/Rlabkey-package.Rd b/Rlabkey/man/Rlabkey-package.Rd index 475fc05..8355fa8 100755 --- a/Rlabkey/man/Rlabkey-package.Rd +++ b/Rlabkey/man/Rlabkey-package.Rd @@ -18,8 +18,8 @@ schema objects (\code{labkey.getSchema}). \tabular{ll}{ Package: \tab Rlabkey\cr Type: \tab Package\cr -Version: \tab 3.4.5\cr -Date: \tab 2026-01-20\cr +Version: \tab 3.4.6\cr +Date: \tab 2026-02-17\cr License: \tab Apache License 2.0\cr LazyLoad: \tab yes\cr } diff --git a/Rlabkey/man/makeFilter.Rd b/Rlabkey/man/makeFilter.Rd index 28bc877..f14a171 100755 --- a/Rlabkey/man/makeFilter.Rd +++ b/Rlabkey/man/makeFilter.Rd @@ -23,6 +23,13 @@ the column name, operator and value. } Operator values:\cr +ARRAY_CONTAINS_ALL\cr +ARRAY_CONTAINS_ANY\cr +ARRAY_CONTAINS_EXACT\cr +ARRAY_CONTAINS_NOT_EXACT\cr +ARRAY_CONTAINS_NONE\cr +ARRAY_ISEMPTY\cr +ARRAY_ISNOTEMPTY\cr EQUAL\cr DATE_EQUAL\cr NOT_EQUAL\cr @@ -58,7 +65,7 @@ EXP_CHILD_OF\cr EXP_PARENT_OF\cr EXP_LINEAGE_OF\cr -When using the MISSING, NOT_MISSING, MV_INDICATOR, or NO_MV_INDICATOR operators, an empty string should be supplied as the value. +When using the MISSING, NOT_MISSING, MV_INDICATOR, NO_MV_INDICATOR, ARRAY_ISEMPTY, or ARRAY_ISNOTEMPTY operators, an empty string should be supplied as the value. See example below. } diff --git a/Rlabkey/src/listToMatrix.cpp b/Rlabkey/src/listToMatrix.cpp index 52c3d46..3df35e9 100644 --- a/Rlabkey/src/listToMatrix.cpp +++ b/Rlabkey/src/listToMatrix.cpp @@ -1,4 +1,5 @@ #include +#include using namespace Rcpp; // [[Rcpp::export]] @@ -35,11 +36,30 @@ CharacterMatrix listToMatrix(List data, List names) { } else { - // only try to parse the first vector element as a string if it is non-null + // only try to parse the vector elements if the first element is not null GenericVector gv = as((as(data[i]))[as(indexList[j])]); if(gv.size() > 0 && !Rf_isNull(gv[0])) { - cMatrix(i,j) = as(gv[0])[0]; + // Check if first element is a string - if so, concatenate all elements + if(TYPEOF(gv[0]) == STRSXP) + { + std::string result; + for(int k = 0; k < gv.size(); k++) + { + if(!Rf_isNull(gv[k]) && TYPEOF(gv[k]) == STRSXP) + { + String s = as(gv[k]); + if(k > 0) result += ","; + result += s.get_cstring(); + } + } + cMatrix(i,j) = result; + } + else + { + // Fallback to just returning the first element + cMatrix(i,j) = as(gv[0])[0]; + } } } }