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
4 changes: 2 additions & 2 deletions Rlabkey/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
4 changes: 4 additions & 0 deletions Rlabkey/NEWS
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
10 changes: 10 additions & 0 deletions Rlabkey/R/makeFilter.R
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 2 additions & 2 deletions Rlabkey/man/Rlabkey-package.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
9 changes: 8 additions & 1 deletion Rlabkey/man/makeFilter.Rd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
}

Expand Down
24 changes: 22 additions & 2 deletions Rlabkey/src/listToMatrix.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <Rcpp.h>
#include <string>
using namespace Rcpp;

// [[Rcpp::export]]
Expand Down Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how querying multi-value foreign key columns are done in R currently? That one should also return array result.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the current behavior is to just use the first array value if the response is an array. that seems a bit odd, but I didn't want to go too far with this change so I just scoped it to arrays of string values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is fine. It doesn't handle special case such as the value itself contains comma, but better than current.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct. that was my thought as well (better than current). I don't know how far we want to go for the special cases (as mentioned "string values that contain comma")

GenericVector gv = as<GenericVector>((as<List>(data[i]))[as<int>(indexList[j])]);
if(gv.size() > 0 && !Rf_isNull(gv[0]))
{
cMatrix(i,j) = as<CharacterVector>(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<String>(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<CharacterVector>(gv[0])[0];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, it's been a long time since I've had to look at C++ code (or think about pointers) 👎 but this looks fine.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, this was AI generated code that I just reviewed and tested!

}
}
}
Expand Down