@@ -15497,6 +15497,88 @@ def test_fixed_length_binary_type(cursor, db_connection):
1549715497 pytest.fail(f"Fixed-length BINARY test failed: {e}")
1549815498
1549915499
15500+ def test_fetchall_with_integrity_constraint(cursor, db_connection):
15501+ """
15502+ Test that UNIQUE constraint errors are appropriately triggered for multi-row INSERT
15503+ statements that use OUTPUT inserted.
15504+
15505+ This test covers a specific case where SQL Server's protocol has error conditions
15506+ that do not become apparent until rows are fetched, requiring special handling
15507+ in fetchall().
15508+ """
15509+ try:
15510+ # Setup table with unique constraint
15511+ cursor.execute("DROP TABLE IF EXISTS #uniq_cons_test")
15512+ cursor.execute("""
15513+ CREATE TABLE #uniq_cons_test (
15514+ id INTEGER NOT NULL IDENTITY,
15515+ data VARCHAR(50) NULL,
15516+ PRIMARY KEY (id),
15517+ UNIQUE (data)
15518+ )
15519+ """)
15520+
15521+ # Insert initial row - should work
15522+ cursor.execute("INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?)", ('the data 1',))
15523+ cursor.fetchall() # Complete the operation
15524+
15525+ # Test single row duplicate - should raise IntegrityError
15526+ with pytest.raises(mssql_python.IntegrityError):
15527+ cursor.execute("INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?)", ('the data 1',))
15528+ cursor.fetchall() # Error should be detected here
15529+
15530+ # Insert two valid rows in one statement - should work
15531+ cursor.execute("INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
15532+ ('the data 2', 'the data 3'))
15533+ cursor.fetchall()
15534+
15535+ # Verify current state
15536+ cursor.execute("SELECT * FROM #uniq_cons_test ORDER BY id")
15537+ rows = cursor.fetchall()
15538+ expected_before = [(1, "the data 1"), (3, "the data 2"), (4, "the data 3")]
15539+ actual_before = [tuple(row) for row in rows]
15540+ assert actual_before == expected_before
15541+
15542+ # THE CRITICAL TEST: Multi-row INSERT with duplicate values
15543+ # This should raise IntegrityError during fetchall()
15544+ with pytest.raises(mssql_python.IntegrityError):
15545+ cursor.execute("INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
15546+ ('the data 4', 'the data 4')) # Duplicate in same statement
15547+
15548+ # The error should be detected HERE during fetchall()
15549+ cursor.fetchall()
15550+
15551+ # Verify table state after failed multi-row insert
15552+ cursor.execute("SELECT * FROM #uniq_cons_test ORDER BY id")
15553+ rows = cursor.fetchall()
15554+ expected_after = [(1, "the data 1"), (3, "the data 2"), (4, "the data 3")]
15555+ actual_after = [tuple(row) for row in rows]
15556+ assert actual_after == expected_after, "Table should be unchanged after failed insert"
15557+
15558+ # Test timing: execute() should succeed, error detection happens in fetchall()
15559+ try:
15560+ cursor.execute("INSERT INTO #uniq_cons_test (data) OUTPUT inserted.id VALUES (?), (?)",
15561+ ('the data 5', 'the data 5'))
15562+ execute_succeeded = True
15563+ except Exception:
15564+ execute_succeeded = False
15565+
15566+ assert execute_succeeded, "execute() should succeed, error detection happens in fetchall()"
15567+
15568+ # fetchall() should raise the IntegrityError
15569+ with pytest.raises(mssql_python.IntegrityError):
15570+ cursor.fetchall()
15571+
15572+ except Exception as e:
15573+ pytest.fail(f"Integrity constraint multi-row test failed: {e}")
15574+ finally:
15575+ # Cleanup
15576+ try:
15577+ cursor.execute("DROP TABLE IF EXISTS #uniq_cons_test")
15578+ except:
15579+ pass
15580+
15581+
1550015582def test_close(db_connection):
1550115583 """Test closing the cursor"""
1550215584 try:
0 commit comments