@@ -140,82 +140,104 @@ impl PartialEq for UnKnownColumn {
140140 }
141141}
142142
143- #[ cfg( test) ]
144- mod tests {
143+ /// Tests for the `try_to_proto` / `try_from_proto` hooks.
144+ #[ cfg( all( test, feature = "proto" ) ) ]
145+ mod proto_tests {
145146 use super :: * ;
146-
147- #[ cfg( feature = "proto" ) ]
148- use std:: sync:: Arc ;
149-
150- #[ cfg( feature = "proto" ) ]
147+ use crate :: proto_test_util:: { StubEncoder , UnreachableDecoder , column_node} ;
151148 use arrow:: datatypes:: Schema ;
152-
153- #[ cfg( feature = "proto" ) ]
154- use datafusion_common:: { Result , internal_err} ;
155-
156- #[ cfg( feature = "proto" ) ]
149+ use datafusion_common:: DataFusionError ;
157150 use datafusion_physical_expr_common:: physical_expr:: proto_decode:: PhysicalExprDecodeCtx ;
151+ use datafusion_physical_expr_common:: physical_expr:: proto_encode:: PhysicalExprEncodeCtx ;
152+ use datafusion_proto_models:: protobuf:: { self , physical_expr_node} ;
158153
159- #[ cfg( feature = "proto" ) ]
160- struct DummyDecode ;
154+ // ── try_to_proto ─────────────────────────────────────────────────────────
161155
162- #[ cfg( feature = "proto" ) ]
163- impl datafusion_physical_expr_common:: physical_expr:: proto_decode:: PhysicalExprDecode
164- for DummyDecode
165- {
166- fn decode (
167- & self ,
168- _node : & datafusion_proto_models:: protobuf:: PhysicalExprNode ,
169- _schema : & Schema ,
170- ) -> Result < Arc < dyn PhysicalExpr > > {
171- internal_err ! ( "decode should not be called" )
172- }
156+ #[ test]
157+ fn try_to_proto_encodes_unknown_column ( ) {
158+ let expr = UnKnownColumn :: new ( "my_col" ) ;
159+ let encoder = StubEncoder :: ok ( ) ;
160+ let ctx = PhysicalExprEncodeCtx :: new ( & encoder) ;
161+
162+ let node = expr
163+ . try_to_proto ( & ctx)
164+ . unwrap ( )
165+ . expect ( "UnKnownColumn should encode to Some(node)" ) ;
166+
167+ // Built-in exprs never set expr_id; only dynamic filters do.
168+ assert ! ( node. expr_id. is_none( ) ) ;
169+
170+ // Verify the encoded name matches the original.
171+ let protobuf:: UnknownColumn { name } = match node. expr_type {
172+ Some ( physical_expr_node:: ExprType :: UnknownColumn ( c) ) => c,
173+ other => panic ! ( "expected UnknownColumn proto node, got {other:?}" ) ,
174+ } ;
175+ assert_eq ! ( name, "my_col" ) ;
173176 }
174177
175- #[ cfg( feature = "proto" ) ]
176- #[ test]
177- fn try_from_proto_reports_found_variant ( ) {
178- use datafusion_proto_models:: protobuf;
178+ // ── try_from_proto ───────────────────────────────────────────────────────
179179
180+ #[ test]
181+ fn try_from_proto_decodes_name ( ) {
180182 let node = protobuf:: PhysicalExprNode {
181- expr_id : Some ( 7 ) ,
182- expr_type : Some ( protobuf:: physical_expr_node:: ExprType :: Column (
183- protobuf:: PhysicalColumn {
184- name : "col_a" . to_string ( ) ,
185- index : 0 ,
183+ expr_id : None ,
184+ expr_type : Some ( physical_expr_node:: ExprType :: UnknownColumn (
185+ protobuf:: UnknownColumn {
186+ name : "my_col" . to_string ( ) ,
186187 } ,
187188 ) ) ,
188189 } ;
189190 let schema = Schema :: empty ( ) ;
190- let decoder = DummyDecode ;
191+ // UnKnownColumn has no child exprs so the decoder is never called.
192+ let decoder = UnreachableDecoder ;
191193 let ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
192194
193- let err = UnKnownColumn :: try_from_proto ( & node, & ctx) . unwrap_err ( ) ;
194- let err = err. to_string ( ) ;
195+ let decoded = UnKnownColumn :: try_from_proto ( & node, & ctx) . unwrap ( ) ;
196+ let col = decoded
197+ . downcast_ref :: < UnKnownColumn > ( )
198+ . expect ( "decoded expr should be an UnKnownColumn" ) ;
199+ assert_eq ! ( col. name( ) , "my_col" ) ;
200+ }
195201
196- assert ! ( err. contains( "expr_id=Some(7)" ) ) ;
197- assert ! ( err. contains( "PhysicalColumn" ) ) ;
202+ #[ test]
203+ fn try_from_proto_rejects_non_unknown_column_node ( ) {
204+ // column_node produces an ExprType::Column node, not UnknownColumn.
205+ let node = column_node ( "a" ) ;
206+ let schema = Schema :: empty ( ) ;
207+ let decoder = UnreachableDecoder ;
208+ let ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
209+ let err = UnKnownColumn :: try_from_proto ( & node, & ctx) . unwrap_err ( ) ;
210+ assert ! ( matches!(
211+ err,
212+ DataFusionError :: Internal ( ref msg)
213+ if msg. contains( "PhysicalExprNode is not an UnKnownColumn" )
214+ // The error includes the actual expr_type for easier diagnosis.
215+ && msg. contains( "PhysicalColumn" )
216+ ) ) ;
198217 }
199218
200- #[ cfg( feature = "proto" ) ]
219+ // ── roundtrip ────────────────────────────────────────────────────────────
220+
201221 #[ test]
202222 fn unknown_column_proto_roundtrip ( ) {
203- use datafusion_proto_models:: protobuf;
223+ let expr = UnKnownColumn :: new ( "col_b" ) ;
224+ let encoder = StubEncoder :: ok ( ) ;
225+ let enc_ctx = PhysicalExprEncodeCtx :: new ( & encoder) ;
204226
205- let name = "col_b" . to_string ( ) ;
206- let node = protobuf:: PhysicalExprNode {
207- expr_id : Some ( 42 ) ,
208- expr_type : Some ( protobuf:: physical_expr_node:: ExprType :: UnknownColumn (
209- protobuf:: UnknownColumn { name : name. clone ( ) } ,
210- ) ) ,
211- } ;
227+ let node = expr
228+ . try_to_proto ( & enc_ctx)
229+ . unwrap ( )
230+ . expect ( "UnKnownColumn should encode to Some(node)" ) ;
212231
213232 let schema = Schema :: empty ( ) ;
214- let decoder = DummyDecode ;
215- let ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
216-
217- let decoded = UnKnownColumn :: try_from_proto ( & node, & ctx) . unwrap ( ) ;
218- let col = decoded. as_ref ( ) . downcast_ref :: < UnKnownColumn > ( ) . unwrap ( ) ;
219- assert_eq ! ( col. name( ) , name. as_str( ) ) ;
233+ // UnKnownColumn has no child exprs so the decoder is never called.
234+ let decoder = UnreachableDecoder ;
235+ let dec_ctx = PhysicalExprDecodeCtx :: new ( & schema, & decoder) ;
236+
237+ let decoded = UnKnownColumn :: try_from_proto ( & node, & dec_ctx) . unwrap ( ) ;
238+ let col = decoded
239+ . downcast_ref :: < UnKnownColumn > ( )
240+ . expect ( "decoded expr should be an UnKnownColumn" ) ;
241+ assert_eq ! ( col. name( ) , "col_b" ) ;
220242 }
221243}
0 commit comments