The com.spotify:dockerfile-maven-plugin:1.4.13 is deprecated and broken
on modern macOS (Apple Silicon) due to its Java HTTP client being
incompatible with current Docker Desktop socket/API.
Replace the Java-based plugin with exec-maven-plugin calling the docker
CLI directly — the same approach already used by the multiarch push
profiles (push-docker-amd-arm-images).
All existing Maven property contracts preserved:
- dockerfile.skip (default true) controls docker build
- push-docker-image profile for single-arch push
- push-docker-amd-arm-images profiles unchanged (already use exec)
Introduces four independent flags to skip individual packaging artifacts:
-Dpkg.skip.bootjar=true skip spring-boot repackage (*-boot.jar)
-Dpkg.skip.deb=true skip Gradle buildDeb + Maven attach-artifact
-Dpkg.skip.rpm=true skip Gradle buildRpm
-Dpkg.skip.zip=true skip maven-assembly-plugin Windows ZIP
Adds -Dpkg.skip=true as a single convenience flag that sets all four
at once. msa/pom.xml mirrors the skip-pkg profile to override its own
<pkg.deb.phase>package</pkg.deb.phase> property (child POM properties
have higher priority than parent profile properties in Maven).
msa/* docker modules used ${basedir}/../.. (non-canonical) for main.dir.
maven-enforcer-plugin 3.5.0's osIndependentNameMatch() compares
file.toURI() vs file.getCanonicalFile().toURI() — these differ when the
path contains '..', causing RequireFilesExist to report false-negative.
Fix: replace ${basedir}/../.. with ${maven.multiModuleProjectDirectory}.
Move 504 handling from interceptor to parseHttpErrorMessage, add
user-friendly messages for 502/503/504 via httpStatusMessageMap,
and scope isProxyError to only match proxy status codes to avoid
breaking error handling for other HTTP errors.
- Wrap entityKeyColumn null-swap in try/finally in EntityKeyMapping
- Remove @Setter from BaseEntityService, use ReflectionTestUtils in test
- Replace Thread.sleep with awaitility in all OR test methods
- Fix confusing temperature comment in pagination test
- Add test for OR with textSearch (middle-layer WHERE logic)
- Add test for OR with TIME_SERIES key filters
- Add test for OR with ComplexFilterPredicate within key filter
- Add EDQS tests for STRING/entity-field with OR (including null special case)
Disable the keyFiltersOperation form control when OR is not allowed.
This uses Angular's reactive form disabled state which properly
propagates through setDisabledState to tb-toggle-select, greying out
the entire toggle. If the filter had OR saved, it resets to AND and
marks the form dirty so Update is enabled. The tooltip on hover
explains why the toggle is disabled.
When OR is disabled but a filter had OR saved, the reset to AND now
marks the form dirty so the Update button is enabled and the user
can save the corrected value.
- Move validateKeyFiltersOperation from DefaultEntityQueryService to
BaseEntityService.validateEntityCountQuery so both REST and WebSocket
paths are covered
- Fix AND/OR toggle: use valueChanges listener to prevent OR selection
when disabled (instead of [disabled] which broke the control entirely)
- Force AND when OR is disabled and filter had OR saved
- Update test to set flag on BaseEntityService
filters-dialog.component.ts was the bridge between filter-dialog
(which sets keyFiltersOperation on the Filter object) and the
dashboard configuration JSON. It was dropping the field in three
places:
- createFilterFormControl: form group had no keyFiltersOperation field
- edit path: patched filter/editable/keyFilters but not operation
- save(): rebuilt Filter objects without keyFiltersOperation
- FilterTextComponent: implement OnChanges to re-render preview text
when the operation input changes (AND→OR or OR→AND)
- isFilterEqual: include keyFiltersOperation in comparison so changing
only the operation triggers widget subscription refresh
- alias-controller: propagate keyFiltersOperation from FilterInfo to Datasource
- entity-data.service: propagate keyFiltersOperation from Datasource to EntityDataSubscriptionOptions
- entity-data-subscription: include keyFiltersOperation in entity data, entity count, and alarm count query construction
- alarm-data-subscription: include keyFiltersOperation in alarm data query construction
- alarm-data.service: propagate keyFiltersOperation from alarmSource to AlarmDataSubscriptionOptions
- Add keyFiltersOperation?: ComplexOperation to Datasource interface in widget.models.ts
- Add keyFiltersOperation?: ComplexOperation to EntityDataSubscriptionOptions interface
- Add keyFiltersOperation?: ComplexOperation to AlarmDataSubscriptionOptions interface
- Import ComplexOperation from query.models in all three files
- Add tb-toggle-select with AND/OR options to filter-dialog
- Toggle disabled with tooltip when feature flag is false
- Pass operation to key-filter-list via @Input binding
- Replace hardcoded AND label with dynamic operation label
- Pass operation through to filter-text preview component
- Add or-conditions-disabled translation key
- Add allowKeyFiltersOrConditions to SysParamsState interface
- Add keyFiltersOperation to FilterInfo and EntityCountQuery interfaces
- Update keyFiltersToText to accept dynamic operation parameter with AND default
- Propagate keyFiltersOperation in getFilterId helper
- Move OR filter predicates to middle-layer WHERE clause where JOIN alias
table references are visible, fixing BadSqlGrammarException
- Use alias name (e.g. alias2) instead of bare column name for entity
field predicates in middle-layer WHERE
- Propagate keyFiltersOperation through BaseEntityService optimization
path and alarm subscription contexts (TbAlarmDataSubCtx, TbAlarmCountSubCtx)
- Replace ThingsboardException with IllegalArgumentException for OR
disabled validation
- Add AlarmCountQuery 3-arg constructor for test convenience
- Add 8 new integration tests: alarm data/count OR, mixed entity field +
attribute OR, string attributes, single filter, 3-way OR, pagination,
and zero-match edge case
- Add testCheckKeyFiltersWithOrOperation: OR short-circuits on first match
- Add testCheckKeyFiltersWithOrOperationNoMatch: OR returns false when nothing matches
- Add testCheckKeyFiltersWithOrOperationSameKey: same-key OR works correctly
- Add testCheckKeyFiltersWithAndOperationUnchanged: AND behavior unchanged
- Add testCheckKeyFiltersWithNullOperationDefaultsToAnd: null defaults to AND
- Add testCheckKeyFiltersWithOrEmptyFilters: OR with empty filters returns true
- Add testCountEntitiesWithOrKeyFiltersOperation: verifies OR count returns entities matching any filter
- Add testFindEntityDataWithOrKeyFiltersOperation: verifies OR data query with different keys
- Add testFindEntityDataWithOrSameKeyFilters: verifies same-key OR ungrouping
- Add testCountEntitiesWithoutKeyFiltersOperation: verifies null defaults to AND
- Add testAlarmDataQueryWithOrKeyFiltersOperation: verifies alarm queries with OR
- Add OrConditionsDisabledEntityQueryControllerTest: verifies OR rejected when toggle disabled
- Read keyFiltersOperationOrDefault in countEntitiesByQuery and findEntityDataByQuery
- Under OR: relocate entity field filter predicates from inner WHERE to outer WHERE
- Under OR: pass forceLeftJoin=true to buildLatestJoins for all aliases
- Under OR: combine all filter mappings with OR joiner via buildQuery(ComplexOperation.OR)
- Under OR: ensure entity field filter columns are in inner SELECT for outer WHERE reference
- AND path remains completely unchanged (same execution path as before)
- Add 4-arg buildQuery overload with ComplexOperation parameter that joins predicates with OR
- Add 3-arg toQueries overload with outerContext flag for bare column names in outer WHERE
- Add forceLeftJoin parameter to toLatestJoin and buildLatestJoins for LEFT JOIN under OR
- Modify prepareKeyMapping to create individual mappings per KeyFilter under OR (no same-key grouping)
- Modify prepareEntityCountKeyMapping with same OR ungrouping logic
- All existing 2-arg/3-arg overloads preserved as backward-compatible delegates
- Extract evaluateSingleFilter helper to avoid duplicating filter evaluation logic
- Add 3-arg checkKeyFilters overload accepting ComplexOperation parameter
- OR mode: any matching filter includes entity (short-circuit on first true)
- AND mode: all filters must match (short-circuit on first false, unchanged behavior)
- Null operation defaults to AND for backward compatibility
- Update checkFilters to pass query.getKeyFiltersOperation() through to checkKeyFilters
- Add keyFiltersOperation field to EdqsQuery base class
- Update EdqsCountQuery and EdqsDataQuery constructors to accept and propagate ComplexOperation
- Propagate keyFiltersOperationOrDefault in both toNewQuery overloads in RepositoryUtils
- Add sql.query.key-filters-or-conditions.enabled property to thingsboard.yml
- Add allowKeyFiltersOrConditions field to SystemParams
- Wire config value into SystemInfoController for /api/system/params
- Add validateKeyFiltersOperation to DefaultEntityQueryService
- Add throws ThingsboardException to EntityQueryService interface methods
- Reject OR queries with 400 when feature is disabled
- Add keyFiltersOperation field with null-safe getKeyFiltersOperationOrDefault()
- Add 3-arg constructor to EntityCountQuery for explicit operation
- Add 6-arg constructors to AbstractDataQuery and EntityDataQuery
- Add 7-arg constructor to AlarmDataQuery
- Update next() methods to propagate keyFiltersOperation
- Update buildEntityDataQuery methods to pass operation from alarm queries