From 7cbbd321fe690aed38ff4e5213ad72cb8477738c Mon Sep 17 00:00:00 2001 From: chenjunwen <15046437592@139.com> Date: Fri, 17 Jul 2026 00:19:14 +0800 Subject: [PATCH] fix: handle null operands in LogicOrOperator for consistency with && and ! LogicAndOperator and LogicNotOperator both treat null as false, but LogicOrOperator throws INVALID_BINARY_OPERAND when either operand is null. This makes `null || true` fail at runtime while `null && true` correctly returns false. Add null-to-false conversion to align the behavior across all three logical operators. --- .../operator/logic/LogicOrOperator.java | 7 +++++ .../independent/operator/logic_or_null.ql | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/test/resources/testsuite/independent/operator/logic_or_null.ql diff --git a/src/main/java/com/alibaba/qlexpress4/runtime/operator/logic/LogicOrOperator.java b/src/main/java/com/alibaba/qlexpress4/runtime/operator/logic/LogicOrOperator.java index d64a5200f..9e1109ca0 100644 --- a/src/main/java/com/alibaba/qlexpress4/runtime/operator/logic/LogicOrOperator.java +++ b/src/main/java/com/alibaba/qlexpress4/runtime/operator/logic/LogicOrOperator.java @@ -36,6 +36,13 @@ public Object execute(Value left, Value right, QRuntime qRuntime, QLOptions qlOp ErrorReporter errorReporter) { Object leftValue = left.get(); Object rightValue = right.get(); + if (leftValue == null) { + leftValue = false; + } + if (rightValue == null) { + rightValue = false; + } + if (!(leftValue instanceof Boolean) || !(rightValue instanceof Boolean)) { throw buildInvalidOperandTypeException(left, right, errorReporter); } diff --git a/src/test/resources/testsuite/independent/operator/logic_or_null.ql b/src/test/resources/testsuite/independent/operator/logic_or_null.ql new file mode 100644 index 000000000..fd5aeacf7 --- /dev/null +++ b/src/test/resources/testsuite/independent/operator/logic_or_null.ql @@ -0,0 +1,30 @@ +// || operator: null should be treated as false, consistent with && and ! +assert(true || true) +assert(true || false) +assert(false || true) +assertFalse(false || false) + +// || with null operands: null is treated as false +assert(true || null) +assert(null || true) +assertFalse(false || null) +assertFalse(null || false) +assertFalse(null || null) + +// 'or' keyword: same behavior as || +assert(true or true) +assert(true or false) +assert(false or true) +assertFalse(false or false) + +// 'or' with null operands +assert(true or null) +assert(null or true) +assertFalse(false or null) +assertFalse(null or false) +assertFalse(null or null) + +// consistency with ! (not): !null == true, so null || true should be true +assert(!null) +assert(!null || false) +assert(false || !null)