Skip to content

Commit 8f44b1a

Browse files
committed
resolving conflicy
2 parents 79706c7 + b47a5cf commit 8f44b1a

File tree

3 files changed

+104
-2
lines changed

3 files changed

+104
-2
lines changed

mssql_python/cursor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,9 @@ def fetchall(self) -> List[Row]:
22812281
wchar_decoding.get("encoding", "utf-16le"),
22822282
)
22832283

2284+
# Check for errors
2285+
check_error(ddbc_sql_const.SQL_HANDLE_STMT.value, self.hstmt, ret)
2286+
22842287
if self.hstmt:
22852288
self.messages.extend(ddbc_bindings.DDBCSQLGetAllDiagRecords(self.hstmt))
22862289

tests/test_003_connection.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2049,7 +2049,8 @@ def test_timeout_long_query(db_connection):
20492049
# Method 2: Try with WAITFOR
20502050
start_time = time.perf_counter()
20512051
cursor.execute("WAITFOR DELAY '00:00:05'")
2052-
cursor.fetchall()
2052+
# Don't call fetchall() on WAITFOR - it doesn't return results
2053+
# The execute itself should timeout
20532054
elapsed_time = time.perf_counter() - start_time
20542055

20552056
# If we still get here, try one more approach

tests/test_004_cursor.py

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10114,7 +10114,11 @@ def test_procedures_result_set_info(cursor, db_connection):
1011410114

1011510115
# Test execution of the procedures to verify they work
1011610116
cursor.execute("EXEC pytest_proc_schema.test_no_results")
10117-
assert cursor.fetchall() == [], "test_no_results should return no results"
10117+
# Procedures with no results should have no description and calling fetchall() should raise an error
10118+
assert (
10119+
cursor.description is None,
10120+
), "test_no_results should have no description (no result set)"
10121+
# Don't call fetchall() on procedures with no results - this is invalid in ODBC
1011810122

1011910123
cursor.execute("EXEC pytest_proc_schema.test_one_result")
1012010124
rows = cursor.fetchall()
@@ -14656,6 +14660,100 @@ def test_fixed_length_binary_type(cursor, db_connection):
1465614660
pytest.fail(f"Fixed-length BINARY test failed: {e}")
1465714661

1465814662

14663+
def test_fetchall_with_integrity_constraint(cursor, db_connection):
14664+
"""
14665+
Test that UNIQUE constraint errors are appropriately triggered for multi-row INSERT
14666+
statements that use OUTPUT inserted.
14667+
14668+
This test covers a specific case where SQL Server's protocol has error conditions
14669+
that do not become apparent until rows are fetched, requiring special handling
14670+
in fetchall().
14671+
"""
14672+
try:
14673+
# Setup table with unique constraint
14674+
cursor.execute("DROP TABLE IF EXISTS #uniq_cons_test")
14675+
cursor.execute(
14676+
"""
14677+
CREATE TABLE #uniq_cons_test (
14678+
id INTEGER NOT NULL IDENTITY,
14679+
data VARCHAR(50) NULL,
14680+
PRIMARY KEY (id),
14681+
UNIQUE (data)
14682+
)
14683+
"""
14684+
)
14685+
14686+
# Insert initial row - should work
14687+
cursor.execute(
14688+
"INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?)", ("the data 1",)
14689+
)
14690+
cursor.fetchall() # Complete the operation
14691+
14692+
# Test single row duplicate - should raise IntegrityError
14693+
with pytest.raises(mssql_python.IntegrityError):
14694+
cursor.execute(
14695+
"INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?)", ("the data 1",)
14696+
)
14697+
cursor.fetchall() # Error should be detected here
14698+
14699+
# Insert two valid rows in one statement - should work
14700+
cursor.execute(
14701+
"INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
14702+
("the data 2", "the data 3"),
14703+
)
14704+
cursor.fetchall()
14705+
14706+
# Verify current state
14707+
cursor.execute("SELECT * FROM #uniq_cons_test ORDER BY id")
14708+
rows = cursor.fetchall()
14709+
expected_before = [(1, "the data 1"), (3, "the data 2"), (4, "the data 3")]
14710+
actual_before = [tuple(row) for row in rows]
14711+
assert actual_before == expected_before
14712+
14713+
# THE CRITICAL TEST: Multi-row INSERT with duplicate values
14714+
# This should raise IntegrityError during fetchall()
14715+
with pytest.raises(mssql_python.IntegrityError):
14716+
cursor.execute(
14717+
"INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
14718+
("the data 4", "the data 4"),
14719+
) # Duplicate in same statement
14720+
14721+
# The error should be detected HERE during fetchall()
14722+
cursor.fetchall()
14723+
14724+
# Verify table state after failed multi-row insert
14725+
cursor.execute("SELECT * FROM #uniq_cons_test ORDER BY id")
14726+
rows = cursor.fetchall()
14727+
expected_after = [(1, "the data 1"), (3, "the data 2"), (4, "the data 3")]
14728+
actual_after = [tuple(row) for row in rows]
14729+
assert actual_after == expected_after, "Table should be unchanged after failed insert"
14730+
14731+
# Test timing: execute() should succeed, error detection happens in fetchall()
14732+
try:
14733+
cursor.execute(
14734+
"INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
14735+
("the data 5", "the data 5"),
14736+
)
14737+
execute_succeeded = True
14738+
except Exception:
14739+
execute_succeeded = False
14740+
14741+
assert execute_succeeded, "execute() should succeed, error detection happens in fetchall()"
14742+
14743+
# fetchall() should raise the IntegrityError
14744+
with pytest.raises(mssql_python.IntegrityError):
14745+
cursor.fetchall()
14746+
14747+
except Exception as e:
14748+
pytest.fail(f"Integrity constraint multi-row test failed: {e}")
14749+
finally:
14750+
# Cleanup
14751+
try:
14752+
cursor.execute("DROP TABLE IF EXISTS #uniq_cons_test")
14753+
except:
14754+
pass
14755+
14756+
1465914757
def test_close(db_connection):
1466014758
"""Test closing the cursor"""
1466114759
try:

0 commit comments

Comments
 (0)