@@ -2753,3 +2753,64 @@ def test_disable_test_logging_if_no_tests_found(mocker: MockerFixture, tmp_path:
27532753
27542754 output = captured_output .stdout
27552755 assert "test" not in output .lower ()
2756+
2757+
2758+ def test_test_generation_with_timestamp_nat (tmp_path : Path ) -> None :
2759+ init_example_project (tmp_path , engine_type = "duckdb" )
2760+
2761+ config = Config (
2762+ default_connection = DuckDBConnectionConfig (),
2763+ model_defaults = ModelDefaultsConfig (dialect = "duckdb" ),
2764+ )
2765+ foo_sql_file = tmp_path / "models" / "foo.sql"
2766+ foo_sql_file .write_text (
2767+ "MODEL (name sqlmesh_example.foo); SELECT ts_col FROM sqlmesh_example.bar;"
2768+ )
2769+ bar_sql_file = tmp_path / "models" / "bar.sql"
2770+ bar_sql_file .write_text ("MODEL (name sqlmesh_example.bar); SELECT ts_col FROM external_table;" )
2771+
2772+ context = Context (paths = tmp_path , config = config )
2773+
2774+ # This simulates the scenario where upstream models have NULL timestamp values
2775+ input_queries = {
2776+ "sqlmesh_example.bar" : """
2777+ SELECT ts_col FROM (
2778+ VALUES
2779+ (TIMESTAMP '2024-09-20 11:30:00.123456789'),
2780+ (CAST(NULL AS TIMESTAMP)),
2781+ (TIMESTAMP '2024-09-21 15:45:00.987654321')
2782+ ) AS t(ts_col)
2783+ """
2784+ }
2785+
2786+ # This should not raise an exception even with NULL timestamp values
2787+ context .create_test ("sqlmesh_example.foo" , input_queries = input_queries , overwrite = True )
2788+
2789+ test = load_yaml (context .path / c .TESTS / "test_foo.yaml" )
2790+ assert len (test ) == 1
2791+ assert "test_foo" in test
2792+
2793+ # Verify that the test was created with correct input and output data
2794+ inputs = test ["test_foo" ]["inputs" ]
2795+ outputs = test ["test_foo" ]["outputs" ]
2796+
2797+ # Check that we have the expected input table
2798+ assert '"memory"."sqlmesh_example"."bar"' in inputs
2799+ bar_data = inputs ['"memory"."sqlmesh_example"."bar"' ]
2800+
2801+ # Verify we have 3 rows (2 with timestamps, 1 with NULL)
2802+ assert len (bar_data ) == 3
2803+
2804+ # Verify that non-NULL timestamps are preserved
2805+ assert bar_data [0 ]["ts_col" ] == datetime .datetime (2024 , 9 , 20 , 11 , 30 , 0 , 123456 )
2806+ assert bar_data [2 ]["ts_col" ] == datetime .datetime (2024 , 9 , 21 , 15 , 45 , 0 , 987654 )
2807+
2808+ # Verify that NULL timestamp is represented as None (not NaT)
2809+ assert bar_data [1 ]["ts_col" ] is None
2810+
2811+ # Verify that the output matches the input (since the model just selects from bar)
2812+ query_output = outputs ["query" ]
2813+ assert len (query_output ) == 3
2814+ assert query_output [0 ]["ts_col" ] == datetime .datetime (2024 , 9 , 20 , 11 , 30 , 0 , 123456 )
2815+ assert query_output [1 ]["ts_col" ] is None
2816+ assert query_output [2 ]["ts_col" ] == datetime .datetime (2024 , 9 , 21 , 15 , 45 , 0 , 987654 )
0 commit comments