Skip to content

[C++][Gandiva] Compiled expression cache returns wrong results for different expressions with the same ToString() #55614

Open

Description

@dmitry-chirkov-dremio

Describe the bug, including details regarding any error messages, version, and platform.

Gandiva builds the cache key from Expression::ToString(). Different expressions can print the same text. The second Projector::Make then reuses the compiled code of the first one. The result is wrong and there is no error.

To reproduce:

  1. Create boolean fields a, b, c.
  2. Build a projector for a AND (b OR c). Evaluate a=false, b=false, c=true. The result is false, correct.
  3. In the same process, build a projector for (a AND b) OR c. BooleanNode::ToString() prints no parentheses, so both expressions print (bool) a && (bool) b || (bool) c.
  4. Evaluate the same row.

The result is false. Expected true.

Two more cases with the same cause:

  • String literals are not escaped. With d = "' } else { (const string) '", the expressions if (c) 'x<d>y' else 'z' and if (c) 'x' else 'y<d>z' print the same text. The second one returns the string of the first.
  • The key does not include the type of the output field. Compile the int32 literal 1 with an int32 output field, then the same tree with an int64 output field. In a fresh process the int64 version is rejected (Return type of root node int32 does not match that of expression int64). After the int32 version was compiled, Make returns OK and Evaluate returns garbage: [4294967297, 4294967297, 1, 0, 0].

Float and double literals are not affected. They print raw bits.

The key also ignores the nullability of fields inside the expression. FieldNode::ToString() prints no nullability. A FieldNode that differs from the schema field only in nullability is rejected by the validator on a cache miss, so on a hit it should be rejected too. Schemas that differ in nullability get different keys, so those are not affected.

Seen on macOS ARM64, main at ab5b42237d. The collisions reproduce in CI on Linux ARM64, Linux ASAN, macOS Intel and macOS ARM64.

The key should be built from the expression tree and the output type, not from ToString().

AI tools paired with common sense helped with the investigation, fix, and tests.

Component(s)

C++, Gandiva

Activity

  1. changed the title [-]Compiled expression cache returns wrong results for different expressions with the same ToString()[/-] [+][C++][Gandiva] Compiled expression cache returns wrong results for different expressions with the same ToString()[/+] on Nov 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions