|
1 | 1 | import typing |
2 | 2 | from test.utils import pandas_only |
3 | | -from unittest.mock import Mock, PropertyMock, patch |
| 3 | +from unittest.mock import Mock, PropertyMock, patch ,mock_open |
4 | 4 |
|
5 | 5 | import pytest # type: ignore |
6 | 6 |
|
@@ -249,3 +249,114 @@ def test_get_tables_considers_args(is_single_database_metadata_val, _input, sche |
249 | 249 | for arg in (schema_pattern, table_name_pattern): |
250 | 250 | if arg is not None: |
251 | 251 | assert arg in spy.call_args[0][1] |
| 252 | + |
| 253 | + |
| 254 | +@pytest.mark.parametrize("indexes, names", [([1], []), ([], ["c1"])]) |
| 255 | +def test_insert_data_column_names_indexes_mismatch_raises(indexes, names, mocker): |
| 256 | + # mock fetchone to return "True" to ensure the table_name and column_name |
| 257 | + # validation steps pass |
| 258 | + mocker.patch("redshift_connector.Cursor.fetchone", return_value=[1]) |
| 259 | + |
| 260 | + mock_cursor: Cursor = Cursor.__new__(Cursor) |
| 261 | + # mock out the connection |
| 262 | + mock_cursor._c = Mock() |
| 263 | + mock_cursor.paramstyle = "qmark" |
| 264 | + |
| 265 | + with pytest.raises( |
| 266 | + InterfaceError, match="Column names and indexes must be the same length" |
| 267 | + ): |
| 268 | + mock_cursor.insert_data_bulk( |
| 269 | + filename="test_file", |
| 270 | + table_name="test_table", |
| 271 | + column_indexes=indexes, |
| 272 | + column_names=names, |
| 273 | + delimeter=",", |
| 274 | + ) |
| 275 | + |
| 276 | + |
| 277 | +in_mem_csv = """\ |
| 278 | +col1,col2,col3 |
| 279 | +1,3,foo |
| 280 | +2,5,bar |
| 281 | +-1,7,baz""" |
| 282 | + |
| 283 | +insert_bulk_data = [ |
| 284 | + ( |
| 285 | + [0], |
| 286 | + ["col1"], |
| 287 | + ("INSERT INTO test_table (col1) VALUES (%s), (%s), (%s);", ["1", "2", "-1"]), |
| 288 | + ), |
| 289 | + ( |
| 290 | + [1], |
| 291 | + ["col2"], |
| 292 | + ("INSERT INTO test_table (col2) VALUES (%s), (%s), (%s);", ["3", "5", "7"]), |
| 293 | + ), |
| 294 | + ( |
| 295 | + [2], |
| 296 | + ["col3"], |
| 297 | + ( |
| 298 | + "INSERT INTO test_table (col3) VALUES (%s), (%s), (%s);", |
| 299 | + ["foo", "bar", "baz"], |
| 300 | + ), |
| 301 | + ), |
| 302 | + ( |
| 303 | + [0, 1], |
| 304 | + ["col1", "col2"], |
| 305 | + ( |
| 306 | + "INSERT INTO test_table (col1, col2) VALUES (%s, %s), (%s, %s), (%s, %s);", |
| 307 | + ["1", "3", "2", "5", "-1", "7"], |
| 308 | + ), |
| 309 | + ), |
| 310 | + ( |
| 311 | + [0, 2], |
| 312 | + ["col1", "col3"], |
| 313 | + ( |
| 314 | + "INSERT INTO test_table (col1, col3) VALUES (%s, %s), (%s, %s), (%s, %s);", |
| 315 | + ["1", "foo", "2", "bar", "-1", "baz"], |
| 316 | + ), |
| 317 | + ), |
| 318 | + ( |
| 319 | + [1, 2], |
| 320 | + ["col2", "col3"], |
| 321 | + ( |
| 322 | + "INSERT INTO test_table (col2, col3) VALUES (%s, %s), (%s, %s), (%s, %s);", |
| 323 | + ["3", "foo", "5", "bar", "7", "baz"], |
| 324 | + ), |
| 325 | + ), |
| 326 | + ( |
| 327 | + [0, 1, 2], |
| 328 | + ["col1", "col2", "col3"], |
| 329 | + ( |
| 330 | + "INSERT INTO test_table (col1, col2, col3) VALUES (%s, %s, %s), (%s, %s, %s), (%s, %s, %s);", |
| 331 | + ["1", "3", "foo", "2", "5", "bar", "-1", "7", "baz"], |
| 332 | + ), |
| 333 | + ), |
| 334 | +] |
| 335 | + |
| 336 | + |
| 337 | +@patch("builtins.open", new_callable=mock_open, read_data=in_mem_csv) |
| 338 | +@pytest.mark.parametrize("indexes,names,exp_execute_args", insert_bulk_data) |
| 339 | +def test_insert_data_column_stmt(mocked_csv, indexes, names, exp_execute_args, mocker): |
| 340 | + # mock fetchone to return "True" to ensure the table_name and column_name |
| 341 | + # validation steps pass |
| 342 | + mocker.patch("redshift_connector.Cursor.fetchone", return_value=[1]) |
| 343 | + mock_cursor: Cursor = Cursor.__new__(Cursor) |
| 344 | + |
| 345 | + # spy on the execute method, so we can check value of sql_query |
| 346 | + spy = mocker.spy(mock_cursor, "execute") |
| 347 | + |
| 348 | + # mock out the connection |
| 349 | + mock_cursor._c = Mock() |
| 350 | + mock_cursor.paramstyle = "qmark" |
| 351 | + |
| 352 | + mock_cursor.insert_data_bulk( |
| 353 | + filename="mocked_csv", |
| 354 | + table_name="test_table", |
| 355 | + column_indexes=indexes, |
| 356 | + column_names=names, |
| 357 | + delimeter=",", |
| 358 | + ) |
| 359 | + |
| 360 | + assert spy.called is True |
| 361 | + assert spy.call_args[0][0] == exp_execute_args[0] |
| 362 | + assert spy.call_args[0][1] == exp_execute_args[1] |
0 commit comments