Skip to content

Commit

Permalink
get diag recs when fast_executemany=True
Browse files Browse the repository at this point in the history
When fast_executemany is True, function ExecuteMulti() is called instead of execute().  ExecuteMulti() was not calling GetDiagRecs() to populate the cursor "messages" attribute.  Made GetDiagRecs() public for that purpose.
  • Loading branch information
keitherskine authored and mkleehammer committed Feb 5, 2024
1 parent 091b45d commit 9298c00
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/cursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ static bool PrepareResults(Cursor* cur, int cCols)
}


static int GetDiagRecs(Cursor* cur)
int GetDiagRecs(Cursor* cur)
{
// Retrieves all diagnostic records from the cursor and assigns them to the "messages" attribute.

Expand Down
2 changes: 2 additions & 0 deletions src/cursor.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ struct Cursor
PyObject* messages;
};

int GetDiagRecs(Cursor* cur);

void Cursor_init();

Cursor* Cursor_New(Connection* cnxn);
Expand Down
5 changes: 5 additions & 0 deletions src/params.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,11 @@ bool ExecuteMulti(Cursor* cur, PyObject* pSql, PyObject* paramArrayObj)
goto ErrorRet8;
}

if (rc == SQL_SUCCESS_WITH_INFO)
{
GetDiagRecs(cur);
}

// TODO: Refactor into ProcessDAEParams() ?
while (rc == SQL_NEED_DATA)
{
Expand Down
32 changes: 28 additions & 4 deletions tests/sqlserver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1072,10 +1072,9 @@ def test_cursor_messages_with_print(cursor: pyodbc.Cursor):
"""
assert not cursor.messages

# SQL Server PRINT statements are never more than 8000 characters
# https://docs.microsoft.com/en-us/sql/t-sql/language-elements/print-transact-sql#remarks
for msg in ('hello world', 'ABCDEFGHIJ' * 800):
cursor.execute(f"PRINT '{msg}'")
# ascii / extended ascii / unicode / beyond BMP unicode
for msg in ('hello world', 'a \xeb a', 'b \u0394 b', 'c \U0001F31C c'):
cursor.execute(f"PRINT N'{msg}'") # note, unicode literal
messages = cursor.messages
assert isinstance(messages, list)
assert len(messages) == 1
Expand All @@ -1086,6 +1085,31 @@ def test_cursor_messages_with_print(cursor: pyodbc.Cursor):
assert '[01000] (0)' == messages[0][0]
assert messages[0][1].endswith(msg)

# maximum size message
# SQL Server PRINT statements are never more than 8000 characters
# https://docs.microsoft.com/en-us/sql/t-sql/language-elements/print-transact-sql#remarks
msg = 'ABCDEFGH' * 1000
cursor.execute(f"PRINT '{msg}'") # note, plain ascii literal
messages = cursor.messages
assert len(messages) == 1
assert messages[0][1].endswith(msg)


def test_cursor_messages_with_fast_executemany(cursor: pyodbc.Cursor):
"""
Ensure the Cursor.messages attribute is set with fast_executemany=True.
"""
cursor.execute("create table t2(id1 int, id2 int)")
cursor.commit()

cursor.fast_executemany = True
cursor.executemany(
"print 'hello';insert into t2(id1, id2) values (?, ?)",
[(10, 11), (20, 21)],
)
assert len(cursor.messages) == 2
assert all(m[1].endswith('hello') for m in cursor.messages)


def test_cursor_messages_with_stored_proc(cursor: pyodbc.Cursor):
"""
Expand Down

0 comments on commit 9298c00

Please sign in to comment.