@@ -179,12 +179,23 @@ public static TreePattern parsePipePatternFromSourceParameters(
179179
180180 // 5. Check if the resulting inclusion pattern is empty
181181 if (inclusionPatterns .isEmpty ()) {
182- throw new PipeException (
183- "Pipe: The inclusion pattern is empty after pruning by the exclusion pattern. "
184- + "This pipe pattern will match nothing." );
182+ final String msg =
183+ String .format (
184+ "Pipe: The provided exclusion pattern fully covers the inclusion pattern. "
185+ + "This pipe pattern will match nothing. "
186+ + "Inclusion: %s, Exclusion: %s" ,
187+ sourceParameters .getStringByKeys (EXTRACTOR_PATTERN_KEY , SOURCE_PATTERN_KEY ),
188+ sourceParameters .getStringByKeys (
189+ EXTRACTOR_PATTERN_EXCLUSION_KEY , SOURCE_PATTERN_EXCLUSION_KEY ));
190+ LOGGER .warn (msg );
191+ throw new PipeException (msg );
185192 }
186193
187- // 6. Build final patterns
194+ // 6. Prune exclusion patterns: if an exclusion pattern does not overlap with
195+ // ANY of the remaining inclusion patterns, it is useless and should be removed.
196+ exclusionPatterns = pruneIrrelevantExclusions (inclusionPatterns , exclusionPatterns );
197+
198+ // 7. Build final patterns
188199 final TreePattern finalInclusionPattern =
189200 buildUnionPattern (isTreeModelDataAllowedToBeCaptured , inclusionPatterns );
190201
@@ -195,7 +206,7 @@ public static TreePattern parsePipePatternFromSourceParameters(
195206 final TreePattern finalExclusionPattern =
196207 buildUnionPattern (isTreeModelDataAllowedToBeCaptured , exclusionPatterns );
197208
198- // 7 . Combine inclusion and exclusion
209+ // 8 . Combine inclusion and exclusion
199210 if (finalInclusionPattern instanceof IoTDBTreePatternOperations
200211 && finalExclusionPattern instanceof IoTDBTreePatternOperations ) {
201212 return new WithExclusionIoTDBTreePattern (
@@ -395,6 +406,37 @@ private static List<TreePattern> pruneInclusionPatterns(
395406 return prunedInclusion ;
396407 }
397408
409+ /**
410+ * Prunes patterns from the exclusion list that do NOT overlap with any of the remaining inclusion
411+ * patterns.
412+ */
413+ private static List <TreePattern > pruneIrrelevantExclusions (
414+ final List <TreePattern > inclusion , final List <TreePattern > exclusion ) {
415+ if (exclusion == null || exclusion .isEmpty ()) {
416+ return new ArrayList <>();
417+ }
418+ if (inclusion == null || inclusion .isEmpty ()) {
419+ // If inclusion is empty, exclusion is irrelevant anyway, but usually this case
420+ // throws exception earlier.
421+ return new ArrayList <>();
422+ }
423+
424+ final List <TreePattern > relevantExclusion = new ArrayList <>();
425+ for (final TreePattern exc : exclusion ) {
426+ boolean overlapsWithAnyInclusion = false ;
427+ for (final TreePattern inc : inclusion ) {
428+ if (overlaps (exc , inc )) {
429+ overlapsWithAnyInclusion = true ;
430+ break ;
431+ }
432+ }
433+ if (overlapsWithAnyInclusion ) {
434+ relevantExclusion .add (exc );
435+ }
436+ }
437+ return relevantExclusion ;
438+ }
439+
398440 /** Checks if 'coverer' pattern fully covers 'coveree' pattern. */
399441 private static boolean covers (final TreePattern coverer , final TreePattern coveree ) {
400442 try {
@@ -423,6 +465,41 @@ private static boolean covers(final TreePattern coverer, final TreePattern cover
423465 } catch (final Exception e ) {
424466 // In case of path parsing errors or unsupported operations, assume no coverage
425467 // to be safe and avoid aggressive pruning.
468+ LOGGER .warn (
469+ "Pipe: Failed to check if pattern [{}] covers [{}]. Assuming false." ,
470+ coverer .getPattern (),
471+ coveree .getPattern (),
472+ e );
473+ return false ;
474+ }
475+ }
476+
477+ /** Checks if 'patternA' overlaps with 'patternB'. */
478+ private static boolean overlaps (final TreePattern patternA , final TreePattern patternB ) {
479+ try {
480+ final List <PartialPath > pathsA = patternA .getBaseInclusionPaths ();
481+ final List <PartialPath > pathsB = patternB .getBaseInclusionPaths ();
482+
483+ if (pathsA .isEmpty () || pathsB .isEmpty ()) {
484+ return false ;
485+ }
486+
487+ // Logic: Check if ANY path in A overlaps with ANY path in B.
488+ for (final PartialPath pathA : pathsA ) {
489+ for (final PartialPath pathB : pathsB ) {
490+ if (pathA .overlapWith (pathB )) {
491+ return true ;
492+ }
493+ }
494+ }
495+ return false ;
496+ } catch (final Exception e ) {
497+ // Best effort check
498+ LOGGER .warn (
499+ "Pipe: Failed to check if pattern [{}] overlaps with [{}]. Assuming false." ,
500+ patternA .getPattern (),
501+ patternB .getPattern (),
502+ e );
426503 return false ;
427504 }
428505 }
0 commit comments