diff --git a/sql_metadata/parser.py b/sql_metadata/parser.py index c92538fc..bb1ccc58 100644 --- a/sql_metadata/parser.py +++ b/sql_metadata/parser.py @@ -488,10 +488,14 @@ def values_dict(self) -> dict[str, Any] | None: if is_multi: self._values_dict = { - col: [row[i] for row in values] for i, col in enumerate(columns) + col: [row[i] if i < len(row) else None for row in values] + for i, col in enumerate(columns) } else: - self._values_dict = dict(zip(columns, values)) + self._values_dict = { + col: (values[i] if i < len(values) else None) + for i, col in enumerate(columns) + } return self._values_dict @property diff --git a/test/test_values.py b/test/test_values.py index 07668a53..5d883a4e 100644 --- a/test/test_values.py +++ b/test/test_values.py @@ -151,6 +151,27 @@ def test_insert_multi_row_values(): assert p.values_dict == {"field1": [1, 3], "field2": [2, 4]} +def test_insert_multi_row_ragged_values_dict(): + """Ragged multi-row VALUES must not IndexError in values_dict.""" + p = Parser("INSERT INTO t (a, b) VALUES (1, 2), (3)") + assert p.values == [[1, 2], [3]] + assert p.values_dict == {"a": [1, 3], "b": [2, None]} + + +def test_insert_multi_row_all_rows_shorter_than_columns(): + """Every VALUES row shorter than the column list still yields all keys.""" + p = Parser("INSERT INTO t (a, b) VALUES (1), (2)") + assert p.values == [[1], [2]] + assert p.values_dict == {"a": [1, 2], "b": [None, None]} + + +def test_insert_single_row_shorter_than_columns(): + """Single-row VALUES shorter than the column list still yields all keys.""" + p = Parser("INSERT INTO t (a, b) VALUES (1)") + assert p.values == [1] + assert p.values_dict == {"a": 1, "b": None} + + def test_insert_with_expression_value(): """INSERT with a function call in VALUES uses str(val) fallback.""" p = Parser("INSERT INTO t (a) VALUES (CURRENT_TIMESTAMP)")