[#2176] RSQL filtering with exist/not-exist support (#2396)

* [#2176] RSQL filtering with exist/not-exist support

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>

* [#2176] Big Refactoring

* RSQL: all maps with joins with on

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-05-16 16:13:04 +03:00
committed by GitHub
parent c0e89fbbee
commit 12140e468d
24 changed files with 518 additions and 616 deletions

View File

@@ -16,29 +16,21 @@ import org.apache.commons.text.lookup.StringLookupFactory;
import org.eclipse.hawkbit.repository.TimestampCalculator;
/**
* Adds macro capabilities to RSQL expressions that are used to filter for
* targets.
* Adds macro capabilities to RSQL expressions that are used to filter for targets.
* <p>
* Some (virtual) properties do not have a representation in the database (in
* general these properties are time-related, or more explicitly, they deal with
* time intervals).<br>
* Such a virtual property needs to be calculated on Java-side before it may be
* used in a target filter query that is passed to the database. Therefore a
* placeholder is used in the RSQL expression that is expanded when the RSQL is
* parsed
* Some (virtual) properties do not have a representation in the database (in general these properties are time-related, or more explicitly,
* they deal with time intervals).<br>
* Such a virtual property needs to be calculated on Java-side before it may be used in a target filter query that is passed to the database.
* Therefore, a placeholder is used in the RSQL expression that is expanded when the RSQL is parsed
* <p>
* A virtual property may either be a system value like the current date (aka
* <em>now_ts</em>) or a value derived from (tenant-specific) system
* A virtual property may either be a system value like the current date (aka <em>now_ts</em>) or a value derived from (tenant-specific) system
* configuration (e.g. <em>overdue_ts</em>).
* <p>
* Known values are:<br>
* <ul>
* <li><em>now_ts</em>: maps to system UTC time in milliseconds since Unix epoch
* as long value</li>
* <li><em>overdue_ts</em>: is a calculated value: <em>overdue_ts = now_ts -
* pollingInterval - pollingOverdueInterval</em>; pollingInterval and
* pollingOverdueInterval are retrieved from tenant-specific system
* configuration.</li>
* <li><em>now_ts</em>: maps to system UTC time in milliseconds since Unix epoch as long value</li>
* <li><em>overdue_ts</em>: is a calculated value: <em>overdue_ts = now_ts - pollingInterval - pollingOverdueInterval</em>; pollingInterval
* and pollingOverdueInterval are retrieved from tenant-specific system configuration.</li>
* </ul>
*/
public class VirtualPropertyResolver implements VirtualPropertyReplacer {
@@ -46,19 +38,16 @@ public class VirtualPropertyResolver implements VirtualPropertyReplacer {
@Serial
private static final long serialVersionUID = 1L;
private transient StringSubstitutor substitutor;
private static final StringSubstitutor STRING_SUBSTITUTOR = new StringSubstitutor(
StringLookupFactory.builder().get().functionStringLookup(VirtualPropertyResolver::lookup),
StringSubstitutor.DEFAULT_PREFIX, StringSubstitutor.DEFAULT_SUFFIX, StringSubstitutor.DEFAULT_ESCAPE);
@Override
public String replace(final String input) {
if (substitutor == null) {
substitutor = new StringSubstitutor(
StringLookupFactory.builder().get().functionStringLookup(this::lookup),
StringSubstitutor.DEFAULT_PREFIX, StringSubstitutor.DEFAULT_SUFFIX, StringSubstitutor.DEFAULT_ESCAPE);
}
return substitutor.replace(input);
return STRING_SUBSTITUTOR.replace(input);
}
private String lookup(final String rhs) {
private static String lookup(final String rhs) {
if ("now_ts".equalsIgnoreCase(rhs)) {
return String.valueOf(System.currentTimeMillis());
} else if ("overdue_ts".equalsIgnoreCase(rhs)) {