@@ -292,4 +292,120 @@ public void testParseMapMetadata_EmptyMap() {
292292 exception .getMessage ().contains ("Invalid MAP metadata" ),
293293 "Exception message should indicate invalid MAP metadata." );
294294 }
295+
296+ /**
297+ * Test parsing of STRUCT metadata with DECIMAL precision and scale - regression test for
298+ * parentheses handling.
299+ */
300+ @ Test
301+ @ DisplayName ("parseStructMetadata with DECIMAL precision and scale" )
302+ public void testParseStructMetadata_WithDecimalPrecisionScale () {
303+ String metadata = "STRUCT<name:STRING, amount:DECIMAL(18,2)>" ;
304+ Map <String , String > expected = new LinkedHashMap <>();
305+ expected .put ("name" , "STRING" );
306+ expected .put ("amount" , "DECIMAL(18,2)" );
307+
308+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
309+ assertEquals (
310+ expected ,
311+ actual ,
312+ "Parsed struct metadata with DECIMAL precision and scale should handle parentheses correctly." );
313+ }
314+
315+ /**
316+ * Test parsing of STRUCT metadata with multiple DECIMAL fields with different precision/scale.
317+ */
318+ @ Test
319+ @ DisplayName ("parseStructMetadata with multiple DECIMAL fields" )
320+ public void testParseStructMetadata_MultipleDecimalFields () {
321+ String metadata = "STRUCT<id:INT, price:DECIMAL(10,2), amount:DECIMAL(18,4), name:STRING>" ;
322+ Map <String , String > expected = new LinkedHashMap <>();
323+ expected .put ("id" , "INT" );
324+ expected .put ("price" , "DECIMAL(10,2)" );
325+ expected .put ("amount" , "DECIMAL(18,4)" );
326+ expected .put ("name" , "STRING" );
327+
328+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
329+ assertEquals (
330+ expected ,
331+ actual ,
332+ "Parsed struct metadata with multiple DECIMAL fields should handle all parentheses correctly." );
333+ }
334+
335+ /** Test parsing of complex nested STRUCT with DECIMAL fields - comprehensive regression test. */
336+ @ Test
337+ @ DisplayName ("parseStructMetadata with nested STRUCT containing DECIMAL" )
338+ public void testParseStructMetadata_NestedStructWithDecimal () {
339+ String metadata =
340+ "STRUCT<id:INT, financial:STRUCT<balance:DECIMAL(15,2), credit:DECIMAL(10,2)>, active:BOOLEAN>" ;
341+ Map <String , String > expected = new LinkedHashMap <>();
342+ expected .put ("id" , "INT" );
343+ expected .put ("financial" , "STRUCT<balance:DECIMAL(15,2), credit:DECIMAL(10,2)>" );
344+ expected .put ("active" , "BOOLEAN" );
345+
346+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
347+ assertEquals (
348+ expected ,
349+ actual ,
350+ "Parsed struct metadata with nested STRUCT containing DECIMAL should preserve all type information." );
351+ }
352+
353+ /** Test parsing of deeply nested STRUCT with multiple DECIMAL fields at different levels. */
354+ @ Test
355+ @ DisplayName ("parseStructMetadata with deeply nested STRUCT and DECIMAL fields" )
356+ public void testParseStructMetadata_DeeplyNestedStructWithDecimals () {
357+ String metadata =
358+ "STRUCT<id:INT, account:STRUCT<balance:DECIMAL(18,4), details:STRUCT<fee:DECIMAL(5,2), rate:DECIMAL(10,6)>>, status:STRING>" ;
359+ Map <String , String > expected = new LinkedHashMap <>();
360+ expected .put ("id" , "INT" );
361+ expected .put (
362+ "account" ,
363+ "STRUCT<balance:DECIMAL(18,4), details:STRUCT<fee:DECIMAL(5,2), rate:DECIMAL(10,6)>>" );
364+ expected .put ("status" , "STRING" );
365+
366+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
367+ assertEquals (
368+ expected ,
369+ actual ,
370+ "Parsed struct metadata with deeply nested STRUCT and DECIMAL fields should handle all levels correctly." );
371+ }
372+
373+ /** Test parsing of STRUCT with mixed complex types and DECIMAL fields. */
374+ @ Test
375+ @ DisplayName ("parseStructMetadata with mixed complex types and DECIMAL" )
376+ public void testParseStructMetadata_MixedComplexTypesWithDecimal () {
377+ String metadata =
378+ "STRUCT<id:INT, prices:ARRAY<DECIMAL(12,2)>, accounts:MAP<STRING, STRUCT<balance:DECIMAL(15,2)>>, summary:STRUCT<total:DECIMAL(20,4), count:INT>>" ;
379+ Map <String , String > expected = new LinkedHashMap <>();
380+ expected .put ("id" , "INT" );
381+ expected .put ("prices" , "ARRAY<DECIMAL(12,2)>" );
382+ expected .put ("accounts" , "MAP<STRING, STRUCT<balance:DECIMAL(15,2)>>" );
383+ expected .put ("summary" , "STRUCT<total:DECIMAL(20,4), count:INT>" );
384+
385+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
386+ assertEquals (
387+ expected ,
388+ actual ,
389+ "Parsed struct metadata with mixed complex types and DECIMAL fields should handle all combinations correctly." );
390+ }
391+
392+ /** Test parsing of STRUCT with other parenthesized types to ensure fix applies broadly. */
393+ @ Test
394+ @ DisplayName ("parseStructMetadata with various parenthesized types" )
395+ public void testParseStructMetadata_VariousParenthesizedTypes () {
396+ String metadata =
397+ "STRUCT<id:INT, name:STRING, amount:DECIMAL(38,18), price:DECIMAL(10,2), active:BOOLEAN>" ;
398+ Map <String , String > expected = new LinkedHashMap <>();
399+ expected .put ("id" , "INT" );
400+ expected .put ("name" , "STRING" );
401+ expected .put ("amount" , "DECIMAL(38,18)" );
402+ expected .put ("price" , "DECIMAL(10,2)" );
403+ expected .put ("active" , "BOOLEAN" );
404+
405+ Map <String , String > actual = MetadataParser .parseStructMetadata (metadata );
406+ assertEquals (
407+ expected ,
408+ actual ,
409+ "Parsed struct metadata with various parenthesized types should handle all type parameters correctly." );
410+ }
295411}
0 commit comments