Skip to content

Commit 97206b6

Browse files
committed
Fix SP returning NULL (closes pymssql#441).
1 parent caf2b6f commit 97206b6

3 files changed

Lines changed: 51 additions & 3 deletions

File tree

ChangeLog.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ Version 2.3.1 - 2024- - Mikhail Terekhov
77
General
88
-------
99

10-
- Update FreeTDS to 1.4.22.
10+
- Fix SP returning NULL (closes #441).
11+
- Update FreeTDS to 1.4.22 (closes #895).
1112
- Require Cython>3.0.10.
1213

1314
Version 2.3.0 - 2024-04-06 - Mikhail Terekhov

src/pymssql/_mssql.pyx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,13 +1823,16 @@ cdef class MSSQLStoredProcedure:
18231823
# set the values in the parameters dictionary.
18241824
if output_count:
18251825
for i in xrange(1, output_count + 1):
1826+
value = None
18261827
with nogil:
18271828
type = dbrettype(self.dbproc, i)
18281829
param_name_bytes = dbretname(self.dbproc, i)
18291830
length = dbretlen(self.dbproc, i)
1830-
data = dbretdata(self.dbproc, i)
1831+
if length:
1832+
data = dbretdata(self.dbproc, i)
18311833

1832-
value = self.conn.convert_db_value(data, type, length)
1834+
if length:
1835+
value = self.conn.convert_db_value(data, type, length)
18331836

18341837
if strlen(param_name_bytes):
18351838
param_name = param_name_bytes.decode('utf-8')

tests/test_sprocs.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ def tearDown(self):
113113
self.pymssql.close()
114114
self.mssql.close()
115115

116+
def testBigIntNullIn(self):
117+
input = None
118+
proc = self.mssql.init_procedure('pymssqlTestBigInt')
119+
proc.bind(input, _mssql.SQLINT8, '@ibigint', null=True)
120+
proc.bind(None, _mssql.SQLINT8, '@obigint', output=True)
121+
proc.execute()
122+
self.assertEqual(input, proc.parameters['@obigint'])
116123

117124
def testBigInt(self):
118125
input = 123456789
@@ -776,3 +783,40 @@ def test_callproc(self):
776783
res = self.cursor.fetchall()
777784
self.assertEqual(res, [('Tom',), ('Dick',), ('Harry',)])
778785

786+
787+
@pytest.mark.mssql_server_required
788+
class TestSPWithNULLResult(unittest.TestCase):
789+
"""
790+
GH: #441
791+
"""
792+
793+
SP_NAME = 'SPWithANullResult'
794+
795+
def setUp(self):
796+
self.mssql = mssqlconn()
797+
self.pymssql = pymssqlconn()
798+
799+
self.mssql.execute_non_query("""
800+
CREATE PROCEDURE [dbo].[%(spname)s]
801+
@int_arg int output,
802+
@varchar_arg varchar output
803+
AS
804+
BEGIN
805+
SET @int_arg = null
806+
SET @varchar_arg = null
807+
END
808+
""" % {'spname': self.SP_NAME})
809+
810+
def tearDown(self):
811+
self.mssql.execute_non_query('DROP PROCEDURE [dbo].[%(spname)s]' % {'spname': self.SP_NAME})
812+
self.pymssql.close()
813+
self.mssql.close()
814+
815+
def testNull(self):
816+
proc = self.mssql.init_procedure(self.SP_NAME)
817+
proc.bind(None, _mssql.SQLINT8, '@int_arg', output=True)
818+
proc.bind(None, _mssql.SQLVARCHAR, '@varchar_arg', output=True)
819+
proc.execute()
820+
self.assertIsNone(proc.parameters['@int_arg'])
821+
self.assertIsNone(proc.parameters['@varchar_arg'])
822+

0 commit comments

Comments
 (0)