Index: obuspa-10.0.5.0/src/core/expr_vector.c =================================================================== --- obuspa-10.0.5.0.orig/src/core/expr_vector.c +++ obuspa-10.0.5.0/src/core/expr_vector.c @@ -59,6 +59,7 @@ char *expr_op_2_str[kExprOp_Max] = "<", // kExprOp_LessThan ">", // kExprOp_GreaterThan "=", // kExprOp_Equals + "~=", // kExprOp_Contains }; @@ -487,6 +488,15 @@ char *SplitOnOperator(char *buf, expr_op *op = '\0'; return &op[2]; } + + // Exit if found the "~=" operator + op = strstr(buf, "~="); + if (op != NULL) + { + *p_op = kExprOp_Contains; + *op = '\0'; + return &op[2]; + } // Exit if found the "<" operator op = strchr(buf, '<'); Index: obuspa-10.0.5.0/src/core/path_resolver.c =================================================================== --- obuspa-10.0.5.0.orig/src/core/path_resolver.c +++ obuspa-10.0.5.0/src/core/path_resolver.c @@ -1088,7 +1088,7 @@ int ResolveUniqueKey(char *resolved, cha char temp[MAX_DM_PATH]; bool is_match; bool is_ref_match; - expr_op_t valid_ops[] = {kExprOp_Equal, kExprOp_NotEqual, kExprOp_LessThanOrEqual, kExprOp_GreaterThanOrEqual, kExprOp_LessThan, kExprOp_GreaterThan}; + expr_op_t valid_ops[] = {kExprOp_Equal, kExprOp_NotEqual, kExprOp_LessThanOrEqual, kExprOp_GreaterThanOrEqual, kExprOp_LessThan, kExprOp_GreaterThan, kExprOp_Contains}; // Exit if unable to find the end of the unique key p = TEXT_UTILS_StrStr(unresolved, "]"); @@ -1754,6 +1754,67 @@ int DoUniqueKeysMatch(int index, search_ } USP_ASSERT(gge->value != NULL); // GROUP_GET_VECTOR_GetValues() should have set an error message if the vendor hook didn't set a value for the parameter + if (ec->op == kExprOp_Contains) { + // NOTE: There is no "list" flag defined for the key parameter, which should be a limitation at the moment. + // The code below assumes comma-separated values in the key parameter value for the "contains" operator + char *list_copy = USP_STRDUP(gge->value); + char *saveptr; + char *token; + bool found = false; + + // Split the list and compare each element + token = strtok_r(list_copy, ",", &saveptr); + while (token != NULL) + { + // Trim whitespace from token + TEXT_UTILS_TrimBuffer(token); + + // Compare based on type + if (type_flags & (DM_INT | DM_UINT | DM_ULONG | DM_LONG | DM_DECIMAL)) + { + err = DM_ACCESS_CompareNumber(token, kExprOp_Equal, ec->value, &result); + } + else if (type_flags & DM_BOOL) + { + err = DM_ACCESS_CompareBool(token, kExprOp_Equal, ec->value, &result); + } + else if (type_flags & DM_DATETIME) + { + err = DM_ACCESS_CompareDateTime(token, kExprOp_Equal, ec->value, &result); + } + else + { + // Default string comparison + err = DM_ACCESS_CompareString(token, kExprOp_Equal, ec->value, &result); + } + + if (err != USP_ERR_OK) + { + USP_FREE(list_copy); + return err; + } + + if (result) + { + found = true; + break; + } + + token = strtok_r(NULL, ",", &saveptr); + } + + USP_FREE(list_copy); + + // Exit if element not found in list + if (!found) + { + return USP_ERR_OK; + } + + // Skip the normal comparison since we already handled it + continue; + } + // Determine the function to call to perform the comparison if (type_flags & (DM_INT | DM_UINT | DM_ULONG | DM_LONG | DM_DECIMAL)) { Index: obuspa-10.0.5.0/src/include/usp_api.h =================================================================== --- obuspa-10.0.5.0.orig/src/include/usp_api.h +++ obuspa-10.0.5.0/src/include/usp_api.h @@ -106,6 +106,7 @@ typedef enum kExprOp_LessThan, // '<' kExprOp_GreaterThan, // '>' kExprOp_Equals, // '=' + kExprOp_Contains, // '~=' kExprOp_Max } expr_op_t;