FreeTDS / freetds

Official FreeTDS repository
http://www.freetds.org/
GNU General Public License v2.0
455 stars 154 forks source link

SqlNumResultCols returns count as 0 for CURSOR queries while using FreeTDS driver, works in Microsoft's ODBC driver #590

Open kowsikbabu opened 1 month ago

kowsikbabu commented 1 month ago

We have used the native SqlNumResultCols() method to run a query that uses CURSOR but the result is returned wrongly as 0 for FreeTDS driver, but works correctly in Microsoft's ODBC Driver.

This is the query used:

DECLARE db_cursor CURSOR FOR SELECT name FROM sys.databases WHERE state_desc = 'ONLINE' AND name NOT IN ('master','tempdb','model','msdb'); DECLARE @DatabaseName NVARCHAR(128); DECLARE @outset TABLE([DATABASENAME] varchar(100),[TABLENAME] varchar(100));OPEN db_cursor;FETCH NEXT FROM db_cursor INTO @DatabaseName;WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @command nvarchar(1000) = ' USE ' + QUOTENAME(@DatabaseName) + ';SELECT DB_NAME() AS databasename,ISNULL(''['' + SCHEMA_NAME(schema_id) + ''].['' + name + '']'', ''No Tables'') AS tablename FROM sys.tables UNION ALL SELECT DB_NAME() AS databasename, ''No Tables'' AS tablename WHERE NOT EXISTS (SELECT 1 FROM sys.tables)';INSERT INTO @outset EXEC (@command);FETCH NEXT FROM db_cursor INTO @DatabaseName; END CLOSE db_cursor; DEALLOCATE db_cursor; SELECT DISTINCT databasename, tablename FROM @outset ORDER BY databasename,tablename;

Here's a screenshot that highlights the issue:

When ODBC driver is used: ODBC

When FreeTDS driver is used: FreeTDS

Kindly help us with this issue.

FreeTDS Version: Current Master branch (I think 1.04.12 in registry) SQL server Version: 2019 OS: Windows 10

kowsikbabu commented 1 month ago

@freddy77 we also saved the query as a stored procedure and tried executing it, we faced the same issue again, works in Microsoft ODBC driver and doesn't work in FreeTDS.

kowsikbabu commented 1 month ago

@freddy77 to add more information:

We also rewrote the query to avoid using cursor and ran this query:

SET NOCOUNT ON; CREATE TABLE #AllTables (DatabaseName NVARCHAR(255),TableName NVARCHAR(255));DECLARE @SQL NVARCHAR(MAX) = ''; SELECT @SQL = @SQL + 'INSERT INTO #AllTables (DatabaseName, TableName) SELECT ''' + name + ''', t.name FROM [' + name + '].sys.tables t UNION ALL SELECT ''' + name + ''', ''No Tables'' WHERE NOT EXISTS (SELECT 1 FROM [' + name + '].sys.tables);' FROM sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb'); EXEC sp_executesql @SQL; SELECT * FROM #AllTables ORDER BY DatabaseName, TableName; DROP TABLE #AllTables;

This one doesn't use the CURSOR, but still this doesn't return value in SqlNumResultCols. SET NOCOUNT ON in the query is optionally used to make it work when Microsoft's ODBC Driver is used.