This sample C++ code does a simple search. Its been tested on Linux and Windows.
If I was going to write code like this in C++, I'd find and/or write some Object Oriented wrapper around the ODBC stuff. Also, if I was just going to access RETS data, aka make a RETS client, I'd use libRETS rather that go via ODBC.
Anyway, on with the example code.
To compile it under windows with Visual C++:
cl.exe /MDd /Od /Gm /Zi /D_DEBUG /GZ /nologo /D__WIN__ /W3 /GX /YX /FD /c /GR /EHsc testCode.cpp link /nologo /out:testCode.exe testCode.obj odbc32.lib
To compile it under Linux using gcc:
g++ -o testCode testCode.cpp -lodbc
#ifdef __WIN__ #include <windows.h> #endif /* __WIN__ */ #define ODBCVER 0x0351 #include <sqltypes.h> #include <sql.h> #include <sqlext.h> #include <iostream> #include <string> using std::cout; using std::cerr; using std::endl; using std::string; // We are completely ignoring the return codes from these SQL calls. // If something goes wrong, its not good. Never do this in real code. int main() { // Declare the ODBC handles we'll be using SQLHENV environment; SQLHDBC connection; SQLHSTMT statement; // Set up the DSN, user, and password we'll use to connect. // It is assumed that the DSN is already setup in the odbc.ini or // your platforms control panel. char* dsn = "retstest"; char* user = "Joe"; char* passwd = "Schmoe"; // Allocate the environment. SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &environment); // Tell the driver manager we'll be speaking ODBCv3. SQLSetEnvAttr(environment, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER); // Allocate the database connection handle SQLAllocHandle(SQL_HANDLE_DBC, environment, &connection); // Connect to the database. SQLConnect(connection, (SQLCHAR*) dsn, SQL_NTS, (SQLCHAR*) user, SQL_NTS, (SQLCHAR*) passwd, SQL_NTS); // Allocate a statement. SQLAllocHandle(SQL_HANDLE_STMT, connection, &statement); // Prepare and execute a query char* query = "SELECT ListingID,ListDate" " FROM data:Property:ResidentialProperty" " WHERE ListPrice > 0"; cout << "Executing query: " << query << endl; SQLExecDirect(statement, (SQLCHAR*) query, SQL_NTS); // See how many columns there are in the result SQLSMALLINT noColumns; SQLNumResultCols(statement, &noColumns); cout << "The query has returned " << noColumns << " columns" << endl; // See how many rows there are in the result SQLLEN rowCount; SQLRowCount(statement, &rowCount); cout << "The query has returned " << rowCount << " rows" << endl; // We have already look at the rets metadata outside of code, so // we know what those columns are supposed to look like. There // for, we'll skip the calls to SQLDescribeCol. We'll just bind // the column without checking. // Create a struct for column one and bind it to a result column struct { char data[1024]; SQLLEN size; } col1; SQLBindCol(statement, 1, SQL_CHAR, &col1.data, 1024, &col1.size); // Create a struct for column two and bind it to a result column struct { TIMESTAMP_STRUCT data; SQLLEN size; } col2; SQLBindCol(statement, 2, SQL_TYPE_TIMESTAMP, &col2.data, SQL_TIMESTAMP_LEN, &col2.size); // Fetch and display the data until there is no more data. SQLRETURN result = SQLFetch(statement); while (result != SQL_NO_DATA && result != SQL_ERROR) { if (col1.size != SQL_NULL_DATA) { cout << string(col1.data, col1.size); }; cout << " "; if (col2.size != SQL_NULL_DATA) { cout << col2.data.year << "-" << col2.data.month << "-" << col2.data.day; } cout << endl; result = SQLFetch(statement); } // Free the statement handle SQLFreeHandle(SQL_HANDLE_STMT, statement); // Disconnect from the database. SQLDisconnect(connection); // Free the connection and environment handles SQLFreeHandle(SQL_HANDLE_DBC, connection); SQLFreeHandle(SQL_HANDLE_ENV, environment); }
