Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLGetConnectAttr() misbehaves. [ODBC202] #188

Open
firebird-automations opened this issue Nov 17, 2016 · 2 comments
Open

SQLGetConnectAttr() misbehaves. [ODBC202] #188

firebird-automations opened this issue Nov 17, 2016 · 2 comments

Comments

@firebird-automations
Copy link

Submitted by: zxMarce (zxmarce)

I'm enhancing an existing ODBC component for use in Gambas 3, a Visual Basic 6 lookalike for Linux platforms. It works against unixODBC and whatever ODBC driver is set up in the system.

When used with FreeTDS v0.91 against a MSSQL database, SQLGetConnectAttr() with the SQL_ATTR_CURRENT_CATALOG attribute correctly fetches the current catalog name (database name).
Please note that I never call SQLSetConnectAttr() in order to later obtain this value, and I'm using SQLDriverConnect() with a connection string to connect to MSSQL, not a DSN.

When I do the same against a Firebird 2.5 server running on Localhost with a test database, the call returns a two-character string, usually -but not always- a lowercase "L" followed by a non-printable char. The routine is calling SQLGetConnectAttr() twice: First to get the necessary buffer length, second to retrieve the string itself.

After I posted these details to the Firebird-odbc-devel mailing list, I was asked to register an issue here.
In the list I was told that I should first call SQLSetConnectAttr() with SQL_ATTR_CURRENT_CATALOG to get data back, to which I replied that FreeTDS does not need it.
Then I was told that SQLGetConnectAttr() with SQL_ATTR_CURRENT_CATALOG should return SQL_NO_DATA, but it does not; my code checks for ODBC errors after each API call.

My code, called no matter which driver is used, is this (pardon my messy C, I'm not that fluent):

void GetConnectedDBName(DB_DESC *desc, SQLHANDLE *connHandle)
{

SQLRETURN	retcode;
SQLINTEGER	charsNeeded = 0;
char		\*dbName;

if \(DB\.IsDebug\(\)\)
\{
	if \(desc\-\>name\)
	\{
		fprintf\(stderr, "gb\.db\.odbc\.GetConnectedDBName: pre desc\-\>name:'%s'\.\\n", desc\-\>name\);
	\} else \{
		fprintf\(stderr, "gb\.db\.odbc\.GetConnectedDBName: pre desc\-\>name: NULL\.\\n"\);
	\}
\}

if \(desc\-\>name\)
\{	
	GB\.FreeString\(POINTER\(&desc\-\>name\)\);
\}

//zxMarce: Attribute to fetch is SQL\_ATTR\_CURRENT\_CATALOG
retcode = SQLGetConnectAttr\(connHandle, SQL\_ATTR\_CURRENT\_CATALOG, NULL, \(SQLINTEGER\) 0, \(SQLINTEGER \*\) &charsNeeded\);
if \(SQL\_SUCCEEDED\(retcode\)\)
\{
	dbName = malloc\(charsNeeded\+\+\);
	dbName\[charsNeeded\+\+\] = 0;
	retcode = SQLGetConnectAttr\(connHandle, SQL\_ATTR\_CURRENT\_CATALOG, dbName, charsNeeded, &charsNeeded\);
	if \(SQL\_SUCCEEDED\(retcode\)\)
	\{
		desc\-\>name = GB\.NewZeroString\(dbName\);
	\} else \{
		reportODBCError\("SQLGetConnectAttr SQL\_ATTR\_CURRENT\_CATALOG \(string\)", connHandle, SQL\_HANDLE\_DBC\);
	\}
\} else \{
	reportODBCError\("SQLGetConnectAttr SQL\_ATTR\_CURRENT\_CATALOG \(len\)", connHandle, SQL\_HANDLE\_DBC\);
\}


if \(DB\.IsDebug\(\)\)
\{
	if \(desc\-\>name\)
	\{
		fprintf\(stderr, "gb\.db\.odbc\.GetConnectedDBName: post dbName: '%s' desc\-\>name \(%d chars\):'%s'\.\\n", dbName, \(int\)charsNeeded, desc\-\>name\);
	\} else \{
		fprintf\(stderr, "gb\.db\.odbc\.GetConnectedDBName: post desc\-\>name: NULL\.\\n"\);
	\}
\}

if \(dbName\)
\{
	free\(dbName\);
\}

}

The routine reportODBCError() is never called. DB.IsDebug() is a flag to post or not low-level debugging info. GB.FreeString and GB.NewZeroString are Gambas 3 API calls to destroy and create Gambas strings.

zxMarce.

@firebird-automations
Copy link
Author

Commented by: Julien Nabet (julien2412)

So perhaps this patch may help:
diff --git a/OdbcConnection.cpp b/OdbcConnection.cpp
index cd27689..0afb9d7 100644
--- a/OdbcConnection.cpp
+++ b/OdbcConnection.cpp
@@ -2060,6 +2060,7 @@ SQLRETURN OdbcConnection::sqlGetConnectAttr(int attribute, SQLPOINTER ptr, int b

    case SQL\_ATTR\_CURRENT\_CATALOG:
            string = databaseName;

+ value = SQL_NO_DATA;
break;

    case SQL\_LOGIN\_TIMEOUT:                 //   103

@irodushka
Copy link
Contributor

irodushka commented Sep 4, 2024

That's what I see with ODBC v3.0

	Full Connect(Default)

	Env. Attr. SQL_ATTR_ODBC_VERSION set to SQL_OV_ODBC3

	Successfully connected to DSN 'EMPL'.
SQLGetConnectAttr:
				In:				ConnectionHandle = 0x0000000005063030, Attribute = Conn: SQL_ATTR_CURRENT_CATALOG=109, ValuePtr = 0x00000000005172A0, 
										BufferLength = 600, StringLengthPtr = 0x000000000050A3C0, fAttribute Type = SQL_C_WCHAR=-8
				Return:	SQL_SUCCESS=0
				Out:			*ValuePtr = "C:\Program Files\Firebird\Firebird_4_0\examples\empbui...", *StringLengthPtr = 138

Seems to be ok.
Please try to reproduce it again, and if the problem persists, describe your case in details pls.
Regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants