Skip to content

[POC] Bound Expressions SerDe - #270

Open
singhpk234 wants to merge 12 commits into
masterfrom
feature/serialize-bound-expression
Open

singhpk234 wants to merge 12 commits into
masterfrom
feature/serialize-bound-expression

Conversation

@singhpk234

Copy link
Copy Markdown
Owner

About the change

The main problem for the bound reference is the accessor, we can't store it in a language agnostic way but we need bound Expressions portability both for ReadRestrictions as well as new adaptive metadata tree.

This pr introduces couple of new APIs :

  • ResolvedReference : a reference with name and fieldId (may be field id is just enough)
  • ResolvedTransform : a unbound transform which has ResolvedReference rather than name reference
  • ResolvedExpression which operates on the ResolvedReference and ResolvedTransform respectively
    so a bound expression when serialized is converted to UnboundExpression which contains the ResolvedReference and ResolvedExpression

This is still a work in progress change will keep this update as i discover / break things along the way !

@singhpk234 singhpk234 changed the title [POC][Do not review] Bound Expressions SerDe [POC][IN PROGRESS] Bound Expressions SerDe Oct 1, 2025
@singhpk234 singhpk234 changed the title [POC][IN PROGRESS] Bound Expressions SerDe [POC] Bound Expressions SerDe Oct 10, 2025
@singhpk234

singhpk234 commented Oct 13, 2025 •

Copy link
Copy Markdown
Owner Author

cc @rdblue @stevenzwu please have a pass when you get some time

BoundPredicate<?> boundPred = (BoundPredicate<?>) boundExpr;

UnboundTerm<?> unbound = ExpressionUtil.unbind(boundPred.term());
assertThat(unbound).isInstanceOf(NamedReference.class);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, unbind can reconstruct the ResolvedReference. not sure it is feasible or not.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, let me double confirm where the unbind is used, since we have BoundReference and all we care about is an unbound term so both NameReference and ResolvedReference would work

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not change the behavior of unbind right now. We don't know the intent of unbinding a reference. It could easily be that you want to go back to binding by name instead of binding by ID.

@singhpk234
singhpk234 force-pushed the feature/serialize-bound-expression branch from d3745b6 to 870d601 Compare October 14, 2025 19:08
@singhpk234

Copy link
Copy Markdown
Owner Author

chaning the NamedReference to UnboundRefernce breaks the rev-api i will adjust the rev-api given we want to move forward with this approach.

@singhpk234
singhpk234 force-pushed the feature/serialize-bound-expression branch from c4a8f4c to 93252f5 Compare October 19, 2025 04:41
}

@SuppressWarnings("unchecked")
public static <S, T> UnboundTerm<T> bucket(ResolvedReference<S> resolvedRef, int numBuckets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are already transform functions that accept UnboundTerm. Why are these needed?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  public static <T> UnboundTerm<T> bucket(String name, int numBuckets) {
    Transform<?, T> transform = (Transform<?, T>) Transforms.bucket(numBuckets);
    return new UnboundTransform<>(ref(name), transform);
  }

The signatures for those are tied to the String name, i can move this the UnboundTerm as even in this function calls ref(name) which returns NamedReference

this way we have just one api and the caller needs to make sure it passes appropriate unboundTerm

case REFERENCE:
return Expressions.ref(JsonUtil.getString(TERM, node));
// Reference must have a name (via "name" or "term")
// fieldId is optional - if present, creates ResolvedReference, otherwise NamedReference

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? Currently, there are three cases for a term:

  1. A string name: "term": "some_column",
  2. A reference object: "term": { "type": "reference", "term": "some_column" },
  3. A transform object: "term": { "type": "transform", "term": (a term) }

I think this needs to be updated so that an ID can be optionally added to case 2: "term": { "type": "reference", "field-id": 12, "term": "some_column" }. I can see the appeal of using "name" instead of "term", but reusing term makes this more consistent. We still have 3 cases and are adding optional data, rather than having 4 cases, where two of those cases share a "type".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants