I'm using Visual Studio 2010 C++ Express and connecting via ODBC to MS SQL Server 2008 R2 Express.

My question is: Is there any way I can pass some type of pointer into SqlGetData instead of an actual data type, then stuff that reference into a void pointer for the calling function to typecast/dereference?

I'd like to have a single function to handle all of my select queries, but I'm currently stumped when calling SqlGetData and supplying an appropriate SQLPOINTER in the 4th parameter.

I surrounded my trouble code (the last few parameters to pass into SqlGetData) with *****. I was able to retrieve results using a simple SELECT query that returned 11 rows of 1 column of type VARCHAR.

When looking at the DatabaseODBC::Query(...) method, the first chunk of code simply retrieves the actual query from an alias list I stored so I wouldn't have to recompile every time I modified a query. So, assume for the rest of the function that the query is SELECT Name FROM Race and that there are 11 rows in the database.

static struct _DBRow_Race
{
    SQLCHAR			Name[51];
	SQLINTEGER		NameLength;
    SQLCHAR			Visible;
	SQLINTEGER		VisibleLength;
} DBRow_Race;
static struct ColumnInfo
{
public:
	SQLCHAR			ColumnName[32];
	SQLSMALLINT		ColumnNameLength;
	SQLSMALLINT		ColumnType;
	SQLUINTEGER		ColumnSize;
	SQLSMALLINT		DecimalDigits;
	SQLSMALLINT		Nullable;
	SQLPOINTER		TargetValue;
} _ColumnInfo;
int DatabaseODBC::Query(std::string QueryName)
{
	// Check that the database connection is established
	if (SQLHandleDatabaseConnection == SQL_NULL_HDBC)
		return -1;

	SqlReturnCode = SQLAllocHandle(SQL_HANDLE_STMT, SQLHandleDatabaseConnection, &SQLHandleStatement);
	if(SqlReturnCode != SQL_SUCCESS && SqlReturnCode != SQL_SUCCESS_WITH_INFO)
		return -2;

	// Retrieve the actual query from the table of queries
	std::string GetQuery = "SELECT QueryText FROM QueryList WHERE QueryName LIKE '" + QueryName + "'";
	SqlReturnCode = SQLExecDirect(SQLHandleStatement, (SQLCHAR*)GetQuery.c_str(), SQL_NTS);
	if(SqlReturnCode != SQL_SUCCESS && SqlReturnCode != SQL_SUCCESS_WITH_INFO)
		return -3;

	std::string QueryToExecute = "";
	while (SQLFetch(SQLHandleStatement) == SQL_SUCCESS)
	{
		SqlReturnCode=SQLGetData(
						SQLHandleStatement,		//SQLHSTMT StatementHandle,
						1,				//SQLUSMALLINT ColumnNumber,
						SQL_C_CHAR,			//SQLSMALLINT TargetType,
						DBRow_QueryList.Text,		//SQLPOINTER TargetValuePtr,
						sizeof(DBRow_QueryList.Text),	//SQLINTEGER BufferLength,
						&DBRow_QueryList.TextLength);	//SQLINTEGER * StrLen_or_IndPtr
		QueryToExecute += (std::string)((char*)DBRow_QueryList.Text);
	}

	//free the statement handle so that it can be reused
	SQLFreeHandle(SQL_HANDLE_STMT, SQLHandleStatement);

	//allocate the statement handle again
	SqlReturnCode = SQLAllocHandle(SQL_HANDLE_STMT, SQLHandleDatabaseConnection, &SQLHandleStatement);
	if(SqlReturnCode != SQL_SUCCESS && SqlReturnCode != SQL_SUCCESS_WITH_INFO)
		return -2;

	//execute the query string retrieved from the QueryList table
	SqlReturnCode = SQLExecDirect(SQLHandleStatement, (SQLCHAR*)QueryToExecute.c_str(), SQL_NTS);
	if(SqlReturnCode != SQL_SUCCESS && SqlReturnCode != SQL_SUCCESS_WITH_INFO)
		return -3;

	SQLSMALLINT NumColumns;
	SqlReturnCode = SQLNumResultCols(SQLHandleStatement, &NumColumns);
	if(SqlReturnCode != SQL_SUCCESS && SqlReturnCode != SQL_SUCCESS_WITH_INFO)
		return -4;

	//Get specifications for each column in order to fetch the data
	std::vector<ColumnInfo> ColInfo;
	ColInfo.resize(NumColumns);
	for (SQLSMALLINT i=0; i<NumColumns; i++)
	{
			SQLDescribeCol (
					SQLHandleStatement,
					i+1,
					ColInfo[i].ColumnName,
					sizeof (ColInfo[i].ColumnName),
					&ColInfo[i].ColumnNameLength,
					&ColInfo[i].ColumnType,
					&ColInfo[i].ColumnSize,
					&ColInfo[i].DecimalDigits,
					&ColInfo[i].Nullable);
			//convert to SQL_CHAR if necessary so SqlGetData knows how to process
			switch (ColInfo[i].ColumnType)
			{
			case SQL_VARCHAR : ColInfo[i].ColumnType = SQL_CHAR; break;
			default : break;
			}

			std::cout<<"Hello"<<std::endl;

	}
	std::string Result = "";

	int IndexRow	= 0;
	while (SQLFetch(SQLHandleStatement) == SQL_SUCCESS)
	{
		for (SQLSMALLINT IndexColumn=0; IndexColumn < NumColumns; IndexColumn++)
		{
			SqlReturnCode=SQLGetData(
						SQLHandleStatement,			//SQLHSTMT StatementHandle,
					IndexColumn+1,				//SQLUSMALLINT ColumnNumber, starting at 1
						ColInfo[IndexColumn].ColumnType,	//SQLSMALLINT TargetType,
//****************************************************
//						DBRow_Race.Name,			//SQLPOINTER TargetValuePtr,
						_ColumnInfo.TargetValue,		//SQLPOINTER TargetValuePtr,
						sizeof(DBRow_Race.Name),	//SQLINTEGER BufferLength,
						&DBRow_Race.NameLength);//SQLINTEGER * StrLen_or_IndPtr
//****************************************************

//			Result is being used for now just to test my first case. In the end, data will be stored in a two dimensional array of void pointers for the other parts of the application to typecast and dereference
//			Result += (std::string)((char*)DBRow_Race.Name);
			Result += (std::string)((char*)_ColumnInfo.TargetValue);
		}
		IndexRow++;
	}

	//Release the query's handle from memory
	if (SQLHandleStatement != SQL_NULL_HSTMT)
		SQLFreeHandle(SQL_HANDLE_STMT, SQLHandleStatement);
	
	return 0;
}

I guess spending 10 minutes fixing the tabbing didn't work. If anyone needs me to post the code again without words wrapping, let me know.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.