@@ -368,5 +368,110 @@ def test_numeric_and_character_varying_positional_arguments_are_unchanged(self):
368368 self .assertEqual (varchar_kwargs , {})
369369
370370
371+ class TestRedshiftIntervalParsing (unittest .TestCase ):
372+ """Test Redshift interval column type argument parsing."""
373+
374+ def test_interval_with_precision_uses_keyword_argument (self ):
375+ """interval(N) must route precision through kwargs, not positional args."""
376+ args , kwargs = _get_args_and_kwargs ("6" , "interval" , "interval(6)" )
377+
378+ self .assertEqual (args , ())
379+ self .assertEqual (kwargs , {"precision" : 6 })
380+
381+ coltype = _update_coltype (
382+ ischema_names ["interval" ],
383+ args ,
384+ kwargs ,
385+ "interval" ,
386+ "duration" ,
387+ False ,
388+ )
389+
390+ self .assertEqual (coltype .precision , 6 )
391+ self .assertIsNone (coltype .fields )
392+
393+ def test_interval_with_fields_and_precision_uses_keyword_arguments (self ):
394+ """interval <fields>(N) must route both precision and fields through kwargs."""
395+ args , kwargs = _get_args_and_kwargs ("6" , "interval day to second" , "interval day to second(6)" )
396+
397+ self .assertEqual (args , ())
398+ self .assertEqual (kwargs , {"precision" : 6 , "fields" : "day to second" })
399+
400+ coltype = _update_coltype (
401+ ischema_names ["interval" ],
402+ args ,
403+ kwargs ,
404+ "interval" ,
405+ "duration" ,
406+ False ,
407+ )
408+
409+ self .assertEqual (coltype .precision , 6 )
410+ self .assertEqual (coltype .fields , "day to second" )
411+
412+ def test_interval_without_precision_keeps_args_empty (self ):
413+ """Bare interval must produce empty args and empty kwargs."""
414+ args , kwargs = _get_args_and_kwargs (None , "interval" , "interval" )
415+
416+ self .assertEqual (args , ())
417+ self .assertEqual (kwargs , {})
418+
419+
420+ class TestRedshiftNumericParsing (unittest .TestCase ):
421+ """Test Redshift numeric column type argument parsing."""
422+
423+ def test_numeric_with_precision_only_does_not_crash (self ):
424+ """numeric(N) without scale must parse precision-only without ValueError."""
425+ args , kwargs = _get_args_and_kwargs ("10" , "numeric" , "numeric(10)" )
426+
427+ self .assertEqual (args , (10 ,))
428+ self .assertEqual (kwargs , {})
429+
430+ coltype = _update_coltype (
431+ ischema_names ["numeric" ],
432+ args ,
433+ kwargs ,
434+ "numeric" ,
435+ "amount" ,
436+ False ,
437+ )
438+
439+ self .assertEqual (coltype .precision , 10 )
440+ self .assertIsNone (coltype .scale )
441+
442+ def test_numeric_with_precision_and_scale_unchanged (self ):
443+ """Regression: numeric(P,S) must continue to parse both as positional args."""
444+ args , kwargs = _get_args_and_kwargs ("10,2" , "numeric" , "numeric(10,2)" )
445+
446+ self .assertEqual (args , (10 , 2 ))
447+ self .assertEqual (kwargs , {})
448+
449+ coltype = _update_coltype (
450+ ischema_names ["numeric" ],
451+ args ,
452+ kwargs ,
453+ "numeric" ,
454+ "amount" ,
455+ False ,
456+ )
457+
458+ self .assertEqual (coltype .precision , 10 )
459+ self .assertEqual (coltype .scale , 2 )
460+
461+ def test_numeric_without_charlen_keeps_args_empty (self ):
462+ """Bare numeric must produce empty args and empty kwargs."""
463+ args , kwargs = _get_args_and_kwargs (None , "numeric" , "numeric" )
464+
465+ self .assertEqual (args , ())
466+ self .assertEqual (kwargs , {})
467+
468+ def test_numeric_with_space_after_comma_falls_back_to_init_args (self ):
469+ """numeric(P, S) with a space must still parse precision and scale."""
470+ args , kwargs = _get_args_and_kwargs (None , "numeric" , "numeric(10, 2)" )
471+
472+ self .assertEqual (args , (10 , 2 ))
473+ self .assertEqual (kwargs , {})
474+
475+
371476if __name__ == "__main__" :
372477 unittest .main ()
0 commit comments