@@ -36,7 +36,15 @@ public class LiteralRoundtripTest extends TestBase {
3636 + " structure:\n "
3737 + " p1: point\n "
3838 + " p2: point\n "
39- + " p3: point\n " ;
39+ + " p3: point\n "
40+ + " - name: vector\n "
41+ + " parameters:\n "
42+ + " - name: T\n "
43+ + " type: dataType\n "
44+ + " structure:\n "
45+ + " x: T\n "
46+ + " y: T\n "
47+ + " z: T\n " ;
4048
4149 private static final SimpleExtension .ExtensionCollection NESTED_TYPES_EXTENSIONS =
4250 SimpleExtension .load ("nested_types.yaml" , NESTED_TYPES_YAML );
@@ -267,4 +275,43 @@ void mixedRepresentationNestedUserDefinedLiteral() {
267275 Expression result = NESTED_TYPES_PROTO_TO_EXPRESSION .from (protoExpression );
268276 assertEquals (triangle , result );
269277 }
278+
279+ /**
280+ * Verifies round-trip conversion of a parameterized user-defined type. Tests that type parameters
281+ * are correctly preserved during serialization and deserialization.
282+ */
283+ @ Test
284+ void userDefinedLiteralWithTypeParameters () {
285+ // Create a type parameter for i32
286+ io .substrait .proto .Type i32Type =
287+ io .substrait .proto .Type .newBuilder ()
288+ .setI32 (
289+ io .substrait .proto .Type .I32
290+ .newBuilder ()
291+ .setNullability (io .substrait .proto .Type .Nullability .NULLABILITY_REQUIRED ))
292+ .build ();
293+ io .substrait .proto .Type .Parameter typeParam =
294+ io .substrait .proto .Type .Parameter .newBuilder ().setDataType (i32Type ).build ();
295+
296+ // Create a vector<i32> instance with fields (x: 1, y: 2, z: 3)
297+ Expression .UserDefinedStruct vectorI32 =
298+ ExpressionCreator .userDefinedLiteralStruct (
299+ false ,
300+ NESTED_TYPES_URN ,
301+ "vector" ,
302+ java .util .Arrays .asList (typeParam ),
303+ java .util .Arrays .asList (
304+ ExpressionCreator .i32 (false , 1 ),
305+ ExpressionCreator .i32 (false , 2 ),
306+ ExpressionCreator .i32 (false , 3 )));
307+
308+ io .substrait .proto .Expression protoExpression =
309+ NESTED_TYPES_EXPRESSION_TO_PROTO .toProto (vectorI32 );
310+ Expression result = NESTED_TYPES_PROTO_TO_EXPRESSION .from (protoExpression );
311+ assertEquals (vectorI32 , result );
312+
313+ Expression .UserDefinedStruct resultStruct = (Expression .UserDefinedStruct ) result ;
314+ assertEquals (1 , resultStruct .typeParameters ().size ());
315+ assertEquals (typeParam , resultStruct .typeParameters ().get (0 ));
316+ }
270317}
0 commit comments