imbajin commented on code in PR #2991:
URL: https://github.com/apache/hugegraph/pull/2991#discussion_r3105758352


##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/ConditionQueryFlatten.java:
##########
@@ -265,7 +265,7 @@ private static List<ConditionQuery> 
flattenRelations(ConditionQuery query) {
             cq.query(nonRelations);
             return ImmutableList.of(cq);
         }
-        return ImmutableList.of(query);
+        return ImmutableList.of();

Review Comment:
   ‼️ **Critical: `flattenRelations` returns empty list for ALL conflicting 
conditions, not just boolean**
   
   This change from `ImmutableList.of(query)` to `ImmutableList.of()` affects 
**all** data types, not just booleans. Previously, when `optimizeRelations` 
returned `null` (meaning conditions were mutually exclusive, e.g., `age > 10 
AND age == 9`), the original query was still returned — the contradiction was 
preserved and evaluated downstream. Now it returns an empty list, silently 
dropping the query.
   
   While returning an empty list for contradictory conditions is arguably more 
correct (no results possible), this is a **behavioral change for 
numeric/date/string range contradictions** too, not just booleans. This should 
be:
   1. Called out explicitly in the PR description since it changes existing 
behavior for all types
   2. Covered with a test for numeric contradictory ranges to ensure no 
regression
   
   Was this intentional or is the fix only meant for the boolean case?
   



##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java:
##########
@@ -488,6 +494,36 @@ private static Condition.Relation 
convCompare2UserpropRelation(HugeGraph graph,
         }
     }
 
+    private static Condition convCompare2BooleanUserpropRelation(Compare 
compare,
+                                                                 Id key,
+                                                                 Boolean 
value) {
+        switch (compare) {
+            case eq:
+                return Condition.eq(key, value);
+            case neq:
+                return Condition.neq(key, value);
+            case gt:
+                return value ? impossibleBooleanCondition(key) :
+                       Condition.eq(key, true);
+            case gte:
+                return value ? Condition.eq(key, true) :
+                       Condition.in(key, ImmutableList.of(false, true));
+            case lt:
+                return value ? Condition.eq(key, false) :
+                       impossibleBooleanCondition(key);
+            case lte:
+                return value ? Condition.in(key, ImmutableList.of(false, 
true)) :
+                       Condition.eq(key, false);
+            default:
+                throw new AssertionError(compare);
+        }
+    }
+
+    private static Condition impossibleBooleanCondition(Id key) {
+        return Condition.and(Condition.eq(key, false),
+                             Condition.eq(key, true));
+    }

Review Comment:
   ⚠️ **`impossibleBooleanCondition` creates an AND node that may not be 
optimized away cleanly**
   
   This creates `AND(eq(key, false), eq(key, true))` to represent an impossible 
condition. This is clever but has a potential issue: this compound 
`Condition.And` flows into the query pipeline where 
`ConditionQueryFlatten.flattenRelations` extracts only `Relation` conditions. 
An `And` node is NOT a `Relation`, so it goes into `nonRelations` and may 
bypass the merge/optimize logic entirely, potentially reaching the backend as a 
real filter condition.
   
   Consider whether returning an empty `ConditionQuery` or a sentinel 
"always-false" condition would be cleaner. Alternatively, verify that the 
`And(eq(false), eq(true))` is properly handled in the flatten/optimize pipeline 
without passing contradictory conditions to the backend.
   
   (If `Condition.in(key, ImmutableList.of())` — i.e., IN with empty list — is 
supported by the backend, that might be a cleaner way to express "matches 
nothing".)
   



##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/query/Condition.java:
##########
@@ -230,6 +232,20 @@ private static int compareDate(Object first, Date second) {
                     second, second.getClass().getSimpleName()));
         }
 
+        private static int compareBoolean(Object first, Boolean second) {
+            if (first == null) {
+                first = false;

Review Comment:
   ⚠️ **`compareBoolean`: null → false coercion is surprising**
   
   When `first` is null, it's silently treated as `false`. This is asymmetric 
with `compareNumber` and `compareDate` which don't do null coercion. If a 
property is absent (null), treating it as `false` could cause incorrect query 
results — e.g., a vertex with no boolean property set would match `lte(false)`.
   
   Consider whether null should throw or return a defined comparison result 
(e.g., null sorts before any non-null value), consistent with how other types 
handle it.
   



##########
hugegraph-struct/src/main/java/org/apache/hugegraph/query/Condition.java:
##########
@@ -472,6 +474,20 @@ private static int compareDate(Object first, Date second) {
                     second, second.getClass().getSimpleName()));
         }
 
+        private static int compareBoolean(Object first, Boolean second) {
+            if (first == null) {
+                first = false;
+            }
+            if (first instanceof Boolean) {
+                return Boolean.compare((Boolean) first, second);
+            }
+
+            throw new IllegalArgumentException(String.format(
+                    "Can't compare between %s(%s) and %s(%s)",
+                    first, first.getClass().getSimpleName(),

Review Comment:
   ⚠️ **Duplicate `compareBoolean` in two Condition classes**
   
   The exact same `compareBoolean` method is added in both:
   - `hugegraph-server/.../backend/query/Condition.java`
   - `hugegraph-struct/.../query/Condition.java`
   
   This is copy-paste duplication. If the null-handling semantics or error 
messages need to change later, both copies must be kept in sync. Is there a 
shared utility class or base class where this could live instead? If 
duplication is intentional (module isolation), consider at least adding a test 
for the `hugegraph-struct` version as well.
   



##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/TraversalUtil.java:
##########
@@ -488,6 +494,36 @@ private static Condition.Relation 
convCompare2UserpropRelation(HugeGraph graph,
         }
     }
 
+    private static Condition convCompare2BooleanUserpropRelation(Compare 
compare,
+                                                                 Id key,
+                                                                 Boolean 
value) {
+        switch (compare) {
+            case eq:
+                return Condition.eq(key, value);
+            case neq:
+                return Condition.neq(key, value);
+            case gt:
+                return value ? impossibleBooleanCondition(key) :
+                       Condition.eq(key, true);
+            case gte:
+                return value ? Condition.eq(key, true) :
+                       Condition.in(key, ImmutableList.of(false, true));

Review Comment:
   🧹 **Minor: `gte(false)` and `lte(true)` normalize to `IN(false, true)` — 
could simplify to "no filter"**
   
   When `gte(false)` or `lte(true)` is applied to a boolean property, the code 
normalizes to `Condition.in(key, [false, true])`. Since these two values are 
the entire boolean domain, this is semantically equivalent to "match 
everything" (no filter). The `IN(false, true)` condition still gets evaluated 
at runtime for every candidate element.
   
   This isn't a bug, but for a performance-conscious path, you could detect 
this case and skip adding the condition entirely. Low priority since boolean 
properties are typically small cardinality.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to