Skip to content

Commit 793fb4c

Browse files
committed
FIX: ODBC Catalog method fetchone() issue
1 parent a4ab587 commit 793fb4c

2 files changed

Lines changed: 148 additions & 0 deletions

File tree

mssql_python/cursor.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,9 @@ def fetchall_with_mapping():
16381638
self.fetchmany = fetchmany_with_mapping
16391639
self.fetchall = fetchall_with_mapping
16401640

1641+
# Initialize rownumber tracking so fetchone() and iteration work
1642+
self._reset_rownumber()
1643+
16411644
# Return the cursor itself for method chaining
16421645
return self
16431646

tests/test_004_cursor.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15961,3 +15961,148 @@ def reader(reader_id):
1596115961
finally:
1596215962
stop_event.set()
1596315963
mssql_python.native_uuid = original
15964+
15965+
15966+
def test_catalog_fetchone_iteration_setup(cursor, db_connection):
15967+
"""Create test objects for catalog fetchone/iteration testing"""
15968+
try:
15969+
cursor.execute(
15970+
"IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'pytest_cat_fetch') "
15971+
"EXEC('CREATE SCHEMA pytest_cat_fetch')"
15972+
)
15973+
cursor.execute("DROP TABLE IF EXISTS pytest_cat_fetch.fetch_test_child")
15974+
cursor.execute("DROP TABLE IF EXISTS pytest_cat_fetch.fetch_test")
15975+
15976+
cursor.execute("""
15977+
CREATE TABLE pytest_cat_fetch.fetch_test (
15978+
id INT PRIMARY KEY,
15979+
name VARCHAR(100) NOT NULL,
15980+
value DECIMAL(10,2),
15981+
ts DATETIME DEFAULT GETDATE()
15982+
)
15983+
""")
15984+
cursor.execute("""
15985+
CREATE TABLE pytest_cat_fetch.fetch_test_child (
15986+
child_id INT PRIMARY KEY,
15987+
parent_id INT NOT NULL,
15988+
CONSTRAINT fk_parent FOREIGN KEY (parent_id)
15989+
REFERENCES pytest_cat_fetch.fetch_test(id)
15990+
)
15991+
""")
15992+
db_connection.commit()
15993+
except Exception as e:
15994+
pytest.fail(f"Catalog fetchone/iteration setup failed: {e}")
15995+
15996+
15997+
def test_tables_fetchone(cursor, db_connection):
15998+
"""Test that fetchone() works on tables() result set (GH-505)"""
15999+
cursor.tables(table="fetch_test", schema="pytest_cat_fetch")
16000+
row = cursor.fetchone()
16001+
assert row is not None, "fetchone() should return a row"
16002+
assert row.table_name.lower() == "fetch_test"
16003+
assert row.table_schem.lower() == "pytest_cat_fetch"
16004+
assert cursor.fetchone() is None
16005+
16006+
16007+
def test_tables_iteration(cursor, db_connection):
16008+
"""Test that 'for row in cursor.tables()' works (GH-505)"""
16009+
rows = list(cursor.tables(table="fetch_test", schema="pytest_cat_fetch"))
16010+
assert len(rows) == 1, "Iteration should yield 1 row"
16011+
assert rows[0].table_name.lower() == "fetch_test"
16012+
16013+
16014+
def test_columns_fetchone(cursor, db_connection):
16015+
"""Test that fetchone() works on columns() result set (GH-505)"""
16016+
cursor.columns(table="fetch_test", schema="pytest_cat_fetch")
16017+
row = cursor.fetchone()
16018+
assert row is not None, "fetchone() should return a row from columns()"
16019+
assert hasattr(row, "column_name")
16020+
assert row.table_name.lower() == "fetch_test"
16021+
16022+
16023+
def test_primarykeys_fetchone(cursor, db_connection):
16024+
"""Test that fetchone() works on primaryKeys() result set (GH-505)"""
16025+
cursor.primaryKeys(table="fetch_test", schema="pytest_cat_fetch")
16026+
row = cursor.fetchone()
16027+
assert row is not None, "fetchone() should return a row from primaryKeys()"
16028+
assert row.column_name.lower() == "id"
16029+
assert cursor.fetchone() is None
16030+
16031+
16032+
def test_foreignkeys_fetchone(cursor, db_connection):
16033+
"""Test that fetchone() works on foreignKeys() result set (GH-505)"""
16034+
cursor.foreignKeys(
16035+
table="fetch_test_child",
16036+
schema="pytest_cat_fetch",
16037+
)
16038+
row = cursor.fetchone()
16039+
assert row is not None, "fetchone() should return a row from foreignKeys()"
16040+
assert row.pkcolumn_name.lower() == "id"
16041+
assert row.fkcolumn_name.lower() == "parent_id"
16042+
assert cursor.fetchone() is None
16043+
16044+
16045+
def test_statistics_fetchone(cursor, db_connection):
16046+
"""Test that fetchone() works on statistics() result set (GH-505)"""
16047+
cursor.statistics(table="fetch_test", schema="pytest_cat_fetch")
16048+
row = cursor.fetchone()
16049+
assert row is not None, "fetchone() should return a row from statistics()"
16050+
assert row.table_name.lower() == "fetch_test"
16051+
16052+
16053+
def test_procedures_fetchone(cursor, db_connection):
16054+
"""Test that fetchone() works on procedures() result set (GH-505)"""
16055+
cursor.procedures()
16056+
row = cursor.fetchone()
16057+
assert row is not None, "fetchone() should return a row from procedures()"
16058+
assert hasattr(row, "procedure_name")
16059+
16060+
16061+
def test_rowid_columns_fetchone(cursor, db_connection):
16062+
"""Test that fetchone() works on rowIdColumns() result set (GH-505)"""
16063+
cursor.rowIdColumns(table="fetch_test", schema="pytest_cat_fetch")
16064+
# May or may not have rowid columns; just verify no InterfaceError
16065+
row = cursor.fetchone()
16066+
if row is not None:
16067+
assert hasattr(row, "column_name")
16068+
16069+
16070+
def test_rowver_columns_fetchone(cursor, db_connection):
16071+
"""Test that fetchone() works on rowVerColumns() result set (GH-505)"""
16072+
cursor.rowVerColumns(table="fetch_test", schema="pytest_cat_fetch")
16073+
# May or may not have rowver columns; just verify no InterfaceError
16074+
row = cursor.fetchone()
16075+
if row is not None:
16076+
assert hasattr(row, "column_name")
16077+
16078+
16079+
def test_gettypeinfo_fetchone(cursor, db_connection):
16080+
"""Test that fetchone() works on getTypeInfo() result set (GH-505)"""
16081+
cursor.getTypeInfo()
16082+
row = cursor.fetchone()
16083+
assert row is not None, "fetchone() should return a row from getTypeInfo()"
16084+
assert hasattr(row, "type_name")
16085+
16086+
16087+
def test_catalog_rownumber_increments_correctly(cursor, db_connection):
16088+
"""Test that rownumber increments correctly during fetchone() on catalog results (GH-505)"""
16089+
cursor.columns(table="fetch_test", schema="pytest_cat_fetch")
16090+
assert cursor.rownumber == -1
16091+
16092+
for expected_idx in range(4):
16093+
row = cursor.fetchone()
16094+
assert row is not None, f"Expected row at index {expected_idx}"
16095+
assert cursor.rownumber == expected_idx
16096+
16097+
assert cursor.fetchone() is None
16098+
16099+
16100+
def test_catalog_fetchone_iteration_cleanup(cursor, db_connection):
16101+
"""Clean up test objects for catalog fetchone/iteration testing"""
16102+
try:
16103+
cursor.execute("DROP TABLE IF EXISTS pytest_cat_fetch.fetch_test_child")
16104+
cursor.execute("DROP TABLE IF EXISTS pytest_cat_fetch.fetch_test")
16105+
cursor.execute("DROP SCHEMA IF EXISTS pytest_cat_fetch")
16106+
db_connection.commit()
16107+
except Exception as e:
16108+
pytest.fail(f"Catalog fetchone/iteration cleanup failed: {e}")

0 commit comments

Comments
 (0)