This is an automated email from the ASF dual-hosted git repository.

viirya pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/spark-connect-gateway.git


The following commit(s) were added to refs/heads/main by this push:
     new f154d51  [SPARK-59908] Sync the vendored Spark Connect protos to v4.2.0
f154d51 is described below

commit f154d512a04224a205808c8aef31087fecb3ff68
Author: Liang-Chi Hsieh <[email protected]>
AuthorDate: Sat Oct 3 22:38:05 2026 -0700

    [SPARK-59908] Sync the vendored Spark Connect protos to v4.2.0
    
    ### What changes were proposed in this pull request?
    
    Sync the vendored Spark Connect protocol definitions to upstream `v4.2.0`:
    
    ```bash
    dev/sync-protos.sh --sync --ref v4.2.0
    ```
    
    `+31` lines in `relations.proto` and `+42` in `pipelines.proto`, **no 
deletions** —
    the drift was one-directional, so closing it is purely additive:
    
    | File | Added |
    |---|---|
    | `relations.proto` | the `NearestByJoin` message, and its entry in the 
`Relation.rel_type` oneof (tag 47) |
    | `pipelines.proto` | the `AutoCdcFlowDetails` message, and the `import 
"spark/connect/expressions.proto"` it needs |
    
    `proto/PROVENANCE.md` and the `UPSTREAM_REF` comment in 
`dev/sync-protos.sh` are
    updated to describe the new state.
    
    ### Why are the changes needed?
    
    #40 (SPARK-59856) recorded that the vendored protos were behind upstream 
and added
    `dev/sync-protos.sh`, but deliberately left the drift in place — re-syncing 
moves
    the protocol the gateway speaks, so it wanted its own review rather than 
riding
    along with a documentation change. This is that review.
    
    **Why `v4.2.0`.** It is the newest *released* Spark tag. `v4.3.0` exists 
only as
    release candidates, and syncing to an rc would pin the gateway to a 
protocol that
    can still change before release. For reference, the tree is 4 files away 
from
    `v4.3.0-rc1`, so there is another sync to make once 4.3.0 ships — this is a 
step,
    not an end state.
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. The added messages extend the protocol the gateway can describe; they 
do not
    change how it routes, authenticates, or forwards anything. No configuration,
    metric, or audit-event change.
    
    ### How was this patch tested?
    
    A compiling binding is weak evidence for a protocol change, so the 
verification
    goes past the build.
    
    **Byte-identical to upstream.** Checked file by file rather than trusting 
the
    script that wrote them — all 11 of 11 match `v4.2.0` exactly, and
    `dev/sync-protos.sh` reports `identical: 11   differing: 0`.
    
    **The new messages really are generated**, not just compiled past.
    `cargo build -p scg-genproto` regenerates the bindings, and both appear in 
the
    generated Rust as real structs:
    
    ```rust
    pub struct NearestByJoin {
        #[prost(message, optional, boxed, tag = "1")]
        pub left: ::core::option::Option<::prost::alloc::boxed::Box<Relation>>,
    ```
    
    **The new `rel_type` variant cannot break an exhaustive match.** A new oneof
    variant is the one way this change could have broken compilation somewhere
    unexpected, so I checked rather than assumed: grepping the workspace outside
    `crates/genproto` for `rel_type` / `RelType` returns nothing. The single 
place that
    does inspect message contents, `crates/proxy/src/config_filter.rs`, matches 
on
    `ConfigRequest.operation.op_type` — untouched here.
    
    **End to end against a real Spark backend**, on kind, deployed through the 
Helm
    chart: `AnalyzePlan` returns the correct schema for a `range` plan, and
    `ExecutePlan` streams 15 response messages back, with the gateway's audit 
log
    confirming both RPCs passed through it:
    
    ```
       1 "rpc":"AnalyzePlan"
       1 "rpc":"ExecutePlan"
    ```
    
    The client encoded its requests **from the newly synced `.proto` files**, 
which is
    what makes this a test of the sync rather than of the gateway alone. It also
    confirms the `v4.2.0` protocol stays compatible with a Spark 4.0 backend, 
which is
    what the e2e jobs run.
    
    **Nothing regressed:** `cargo test --workspace` is 204 passed, 0 failed, 10
    ignored — matching `main` — with `clippy --workspace --all-targets -D 
warnings` and
    `cargo fmt --check` clean.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Yes, co-authored with Claude Code.
    
    Closes #42 from viirya/proto-02-sync-4.2.0.
    
    Authored-by: Liang-Chi Hsieh <[email protected]>
    Signed-off-by: Liang-Chi Hsieh <[email protected]>
---
 dev/sync-protos.sh                  |  5 +--
 proto/PROVENANCE.md                 | 68 ++++++++++++++++++++-----------------
 proto/spark/connect/pipelines.proto | 42 +++++++++++++++++++++++
 proto/spark/connect/relations.proto | 31 +++++++++++++++++
 4 files changed, 112 insertions(+), 34 deletions(-)

diff --git a/dev/sync-protos.sh b/dev/sync-protos.sh
index 0a487a5..2b5e68b 100755
--- a/dev/sync-protos.sh
+++ b/dev/sync-protos.sh
@@ -33,8 +33,9 @@
 
 set -euo pipefail
 
-# The revision proto/PROVENANCE.md records as the comparison baseline. Bump 
this
-# together with that file whenever the vendored protos are re-synced.
+# The upstream revision proto/PROVENANCE.md records the vendored files as being
+# at. Bump this together with that file whenever the protos are re-synced, so 
the
+# two never disagree about what proto/ contains.
 UPSTREAM_REF="v4.2.0"
 
 # Upstream location of the protocol definitions within apache/spark.
diff --git a/proto/PROVENANCE.md b/proto/PROVENANCE.md
index 7b8038d..be1c556 100644
--- a/proto/PROVENANCE.md
+++ b/proto/PROVENANCE.md
@@ -25,7 +25,7 @@ maintained here, and they are not generated: they are 
checked-in schema source.
 |---|---|
 | Upstream project | `apache/spark` |
 | Upstream path | `sql/connect/common/src/main/protobuf/spark/connect/` |
-| Baseline revision | `v4.2.0` (see *Which revision* below) |
+| Revision | `v4.2.0` — the vendored files match it exactly |
 | Files vendored | all 11 `.proto` files in that directory |
 | License | Apache-2.0 — the same license as this project; each file keeps its 
ASF header |
 
@@ -36,37 +36,24 @@ the directory and fails if it is empty.
 
 ## Which revision
 
-The vendored copy predates the `v4.2.0` release. It matches `v4.2.0` exactly 
for
-9 of the 11 files, and the files themselves refer to fields "deprecated since
-Spark 4.2+", so it was taken from the Spark 4.2 development line — but from an
-untagged commit, not from a release. No `v4.2.0-rcN` tag matches either.
+The vendored files are byte-identical to `v4.2.0`, synced by
+`dev/sync-protos.sh --sync --ref v4.2.0` (SPARK-59857). `dev/sync-protos.sh`
+with no arguments confirms this and reports `identical: 11`.
 
-`v4.2.0` is recorded as the baseline revision because it is the earliest
-*released* tag the vendored copy is consistent with, which makes it a 
meaningful
-thing to diff against. It is not a claim that these files were taken from that
-tag.
+`v4.2.0` was chosen because it is the newest *released* Spark tag. `v4.3.0` 
exists
+only as release candidates, and syncing to an rc would pin the gateway to a
+protocol that can still change before release.
 
-Two files differ from `v4.2.0`, in both cases because upstream has content the
-vendored copy does not:
+### History
 
-| File | Missing relative to `v4.2.0` |
-|---|---|
-| `spark/connect/relations.proto` | the `NearestByJoin` message and its 
`Relation.rel_type` entry |
-| `spark/connect/pipelines.proto` | the `AutoCdcFlowDetails` message and its 
`import "spark/connect/expressions.proto"` |
-
-Both are pure additions upstream: nothing in the vendored files was edited
-locally. In other words the vendored protos are slightly **behind** upstream, 
not
-forked from it.
-
-This does not currently affect the gateway. It forwards each
-`SparkConnectService` request onward as a whole and only ever reads the
-session and identity metadata — nothing in `crates/proxy` inspects a plan's
-`rel_type` or walks the relation tree. So a request carrying one of these newer
-messages is still routed and forwarded correctly.
-
-What the gap does mean is that anything which needs to *inspect* one of those
-newer messages — a routing rule keyed on plan shape, say — would have to 
re-sync
-first.
+The original vendored copy — everything before SPARK-59857 — predated the
+`v4.2.0` release. It matched `v4.2.0` for 9 of the 11 files and the files
+referenced fields "deprecated since Spark 4.2+", but no release tag matched it,
+including `v4.2.0-rc1` through `rc5`: it came from an untagged commit on the
+Spark 4.2 development line. It was behind upstream rather than forked from it,
+missing the `NearestByJoin` message in `relations.proto` and
+`AutoCdcFlowDetails` in `pipelines.proto`; the sync added both. Nothing had 
been
+edited locally, then or now.
 
 ## Checking and re-syncing
 
@@ -100,11 +87,28 @@ gateway speaks. After a `--sync`:
 A re-sync is worth reviewing on its own rather than folding into an unrelated
 change, since it moves the wire protocol.
 
+## How protocol drift affects the gateway
+
+Useful context when deciding how urgent a re-sync is: the gateway forwards each
+`SparkConnectService` request onward whole and reads only the session and 
identity
+metadata. Nothing in `crates/proxy` inspects a plan's `rel_type` or walks the
+relation tree, and nothing in the workspace matches on those enums, so a 
request
+carrying a message type the vendored protos do not know about is still routed 
and
+forwarded correctly.
+
+The one place that does look inside a message is 
`crates/proxy/src/config_filter.rs`,
+which matches on `ConfigRequest.operation.op_type` to withhold the backend 
token —
+unrelated to the relation and plan types.
+
+So falling behind upstream degrades gracefully. It becomes a real problem only 
for
+something that needs to *inspect* a newer message, such as a routing rule 
keyed on
+plan shape.
+
 ## For a release
 
 These files are third-party content redistributed in the source release. They
 are Apache-2.0 licensed and retain their upstream ASF headers, so they need no
 separate entry in `LICENSE`, but the source release's `NOTICE`-side paperwork
-should account for them as sourced from `apache/spark`. That belongs with the
-`LICENSE-binary` / `NOTICE-binary` dependency-census work, which is still
-outstanding.
+should account for them as sourced from `apache/spark` at the revision recorded
+above. That belongs with the `LICENSE-binary` / `NOTICE-binary` 
dependency-census
+work, which is still outstanding.
diff --git a/proto/spark/connect/pipelines.proto 
b/proto/spark/connect/pipelines.proto
index 6438583..7632ec9 100644
--- a/proto/spark/connect/pipelines.proto
+++ b/proto/spark/connect/pipelines.proto
@@ -22,6 +22,7 @@ package spark.connect;
 import "google/protobuf/any.proto";
 import "google/protobuf/timestamp.proto";
 import "spark/connect/common.proto";
+import "spark/connect/expressions.proto";
 import "spark/connect/relations.proto";
 import "spark/connect/types.proto";
 
@@ -144,6 +145,7 @@ message PipelineCommand {
 
     oneof details {
       WriteRelationFlowDetails relation_flow_details = 7;
+      AutoCdcFlowDetails auto_cdc_flow_details = 10;
       google.protobuf.Any extension = 999;
     }
 
@@ -154,6 +156,46 @@ message PipelineCommand {
       optional spark.connect.Relation relation = 1;
     }
 
+    // Details for Auto CDC flows.
+    message AutoCdcFlowDetails {
+      // The name of the CDC source to stream from.
+      optional string source = 1;
+
+      // Column(s) that uniquely identify a row in source and target data.
+      repeated Expression keys = 2;
+
+      // Expression to order the source data.
+      optional Expression sequence_by = 3;
+
+      // Delete condition for the merged operation.
+      optional Expression apply_as_deletes = 6;
+
+      // Truncate condition for the merged operation.
+      optional Expression apply_as_truncates = 7;
+
+      // Columns included in the output table.
+      repeated Expression column_list = 8;
+
+      // Columns excluded from the output table.
+      repeated Expression except_column_list = 9;
+
+      // SCD Type for target table.
+      SCDType stored_as_scd_type = 10;
+
+      // Subset of columns to ignore null in updates.
+      repeated Expression ignore_null_updates_column_list = 14;
+
+      // Subset of columns excluded from ignoring null in updates.
+      repeated Expression ignore_null_updates_except_column_list = 15;
+
+    }
+
+    // SCD Type for Auto CDC target tables.
+    enum SCDType {
+      SCD_TYPE_UNSPECIFIED = 0;
+      SCD_TYPE_1 = 1;
+    }
+
     // If true, define the flow as a one-time flow, such as for backfill.
     // Set to true changes the flow in two ways:
     //   - The flow is run one time by default. If the pipeline is ran with a 
full refresh,
diff --git a/proto/spark/connect/relations.proto 
b/proto/spark/connect/relations.proto
index 57c4ed7..95cc928 100644
--- a/proto/spark/connect/relations.proto
+++ b/proto/spark/connect/relations.proto
@@ -82,6 +82,7 @@ message Relation {
     LateralJoin lateral_join = 44;
     ChunkedCachedLocalRelation chunked_cached_local_relation = 45;
     RelationChanges relation_changes = 46;
+    NearestByJoin nearest_by_join = 47;
 
     // NA functions
     NAFill fill_na = 90;
@@ -1276,3 +1277,33 @@ message LateralJoin {
   // (Required) The join type.
   Join.JoinType join_type = 4;
 }
+
+// Relation of type [[NearestByJoin]].
+//
+// For each row on the left side, returns up to `num_results` rows from the 
right side ranked
+// by `ranking_expression`.
+message NearestByJoin {
+  // (Required) Left (query) input relation.
+  Relation left = 1;
+
+  // (Required) Right (base) input relation.
+  Relation right = 2;
+
+  // (Required) Scalar expression used to rank candidate rows on the right 
side.
+  Expression ranking_expression = 3;
+
+  // (Required) Maximum number of matches per left row. Must be between 1 and 
100000.
+  int32 num_results = 4;
+
+  // The following three fields use `string` (not typed enums) for parity with 
`AsOfJoin`,
+  // which models analogous fields the same way. Validation happens 
server-side at planning time.
+
+  // (Required) The join type. Must be one of: "inner", "leftouter".
+  string join_type = 5;
+
+  // (Required) Search algorithm contract. Must be one of: "approx", "exact".
+  string mode = 6;
+
+  // (Required) Ranking direction. Must be one of: "distance", "similarity".
+  string direction = 7;
+}


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

Reply via email to