bool DoDirect(HSTMT lpStmt, SQLCHAR* input) { RETCODE RetCode; SQLSMALLINT sNumResults; RetCode = SQLExecDirect(lpStmt, (SQLCHAR*) input, SQL_NTS); switch (RetCode) { case SQL_SUCCESS_WITH_INFO: { HandleError(lpStmt, SQL_HANDLE_STMT, RetCode); // fall through } case SQL_SUCCESS: { // If this is a row-returning query, display // results TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLNumResultCols(lpStmt, &sNumResults)); if (sNumResults > 0) { DisplayResults(lpStmt, sNumResults); } else { SQLLEN siRowCount; TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLRowCount(lpStmt, &siRowCount)); if (siRowCount >= 0) { _tprintf(TEXT("%ld %s affected\n"), static_cast<long>(siRowCount), siRowCount == 1 ? TEXT("row") : TEXT("rows")); } } break; } case SQL_ERROR: { _tprintf(TEXT("going to call handle error\n")); HandleError(lpStmt, SQL_HANDLE_STMT, RetCode); break; } default: fprintf(stderr, "Unexpected return code %d!\n", RetCode); } return true; Exit: return false; }
void DisplayResults(HSTMT hStmt, SQLSMALLINT cCols, bool silent) { SQLSMALLINT cDisplaySize; RETCODE RetCode = SQL_SUCCESS; int iCount = 0; long long numReceived = 0; // Allocate memory for each column SQLCHAR buffer[MAXCOLS][BUFFERLEN]; SQLLEN indPtr[MAXCOLS]; int iCol; for (iCol = 0; iCol < cCols; iCol++) { TRYODBC(hStmt, SQL_HANDLE_STMT, SQLBindCol(hStmt, iCol+1, SQL_C_CHAR, (SQLPOINTER) buffer[iCol], (BUFFERLEN) * sizeof(char), &indPtr[iCol])); } // Fetch and display the data bool fNoData = false; do { // Fetch a row TRYODBC(hStmt, SQL_HANDLE_STMT, RetCode = SQLFetch(hStmt)); if (RetCode == SQL_NO_DATA_FOUND) { fNoData = true; } else { if (!silent) { // Display the data. Ignore truncations printf("%s", buffer[0]); for (iCol = 1; iCol < cCols; iCol++) { printf(",%s", buffer[iCol]); } printf("\n"); } numReceived++; } } while (!fNoData); Exit: printf("numRecieved = %lld\n", numReceived); }
void DisplayTitles(HSTMT lpStmt, DWORD siDisplaySize, BINDING *pBinding) { TCHAR szTitle[DISPLAY_MAX]; SQLSMALLINT iCol = 1; SetConsole(siDisplaySize + 2, TRUE); for (; pBinding; pBinding = pBinding->sNext) { TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLColAttribute(lpStmt, iCol++, SQL_DESC_NAME, szTitle, sizeof(szTitle), // Note count of bytes! NULL, NULL)); _tprintf(TEXT(DISPLAY_FORMAT_C), PIPE, pBinding->siDisplaySize, pBinding->siDisplaySize, szTitle); } Exit: _tprintf(TEXT(" %c"), PIPE); SetConsole(siDisplaySize + 2, FALSE); _tprintf(TEXT("\n")); }
void DisplayTitles(HSTMT hStmt, DWORD cDisplaySize, BINDING *pBinding) { WCHAR wszTitle[DISPLAY_MAX]; SQLSMALLINT iCol = 1; SetConsole(cDisplaySize+2, TRUE); for (; pBinding; pBinding = pBinding->sNext) { TRYODBC(hStmt, SQL_HANDLE_STMT, SQLColAttribute(hStmt, iCol++, SQL_DESC_NAME, wszTitle, sizeof(wszTitle), // Note count of bytes! NULL, NULL)); wprintf(DISPLAY_FORMAT_C, PIPE, pBinding->cDisplaySize, pBinding->cDisplaySize, wszTitle); } Exit: wprintf(L" %c", PIPE); SetConsole(cDisplaySize+2, FALSE); wprintf(L"\n"); }
void AllocateBindings(HSTMT lpStmt, SQLSMALLINT cCols, BINDING **lppBinding, SQLSMALLINT *lpDisplay) { SQLSMALLINT iCol; BINDING *lpThisBinding, *lpLastBinding; SQLSMALLINT cchColumnNameLength; SQLLEN cchDisplay, ssType; *lpDisplay = 0; for (iCol = 1; iCol <= cCols; iCol++) { lpThisBinding = (BINDING *)(malloc(sizeof(BINDING))); if (!(lpThisBinding)) { fprintf(stderr, "Out of memory!\n"); exit(-100); } if (iCol == 1) { *lppBinding = lpThisBinding; } else { lpLastBinding->sNext = lpThisBinding; } lpLastBinding = lpThisBinding; // Figure out the display length of the column (we will // bind to char since we are only displaying data, in general // you should bind to the appropriate C type if you are going // to manipulate data since it is much faster...) TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLColAttribute(lpStmt, iCol, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &cchDisplay)); // Figure out if this is a character or numeric column; this is // used to determine if we want to display the data left- or right- // aligned. // !! Note a bug in the 3.x documentation. We claim that // SQL_DESC_TYPE is a 1.x feature. That is not true, SQL_DESC_TYPE // is a 3.x feature. SQL_DESC_CONCISE_TYPE maps to the 1.x // SQL_COLUMN_TYPE. This is what you must use if you want to work // against a 2.x driver. Sorry for the inconvenience... TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLColAttribute(lpStmt, iCol, SQL_DESC_CONCISE_TYPE, NULL, 0, NULL, &ssType)); lpThisBinding->fChar = (ssType == SQL_CHAR || ssType == SQL_VARCHAR || ssType == SQL_LONGVARCHAR); lpThisBinding->sNext = NULL; // Arbitrary limit on display size if (cchDisplay > DISPLAY_MAX) cchDisplay = DISPLAY_MAX; // Allocate a buffer big enough to hold the text representation // of the data. Add one character for the null terminator lpThisBinding->szBuffer = (TCHAR *)malloc((cchDisplay + 1) * sizeof(TCHAR)); if (!(lpThisBinding->szBuffer)) { fprintf(stderr, "Out of memory!\n"); exit(-100); } // Map this buffer to the driver's buffer. At Fetch time, // the driver will fill in this data. Note that the size is // count of bytes (for Unicode). All ODBC functions that take // SQLPOINTER use count of bytes; all functions that take only // strings use count of characters. SQLLEN lenInd; TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLBindCol(lpStmt, iCol, SQL_C_TCHAR, (SQLPOINTER) lpThisBinding->szBuffer, (cchDisplay + 1) * sizeof(TCHAR), &lenInd)); lpThisBinding->indPtr = lenInd; // Now set the display size that we will use to display // the data. Figure out the length of the column name TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLColAttribute(lpStmt, iCol, SQL_DESC_NAME, NULL, 0, &cchColumnNameLength, NULL)); lpThisBinding->siDisplaySize = cchDisplay > cchColumnNameLength ? cchDisplay : cchColumnNameLength; if (lpThisBinding->siDisplaySize < NULL_SIZE) lpThisBinding->siDisplaySize = NULL_SIZE; *lpDisplay += lpThisBinding->siDisplaySize + DISPLAY_FORMAT_EXTRA; } Exit: // Not really a good error exit handler, we should free // up any memory that we allocated. But this is a sample... return; }
void DisplayResults(HSTMT lpStmt, SQLSMALLINT cCols) { BINDING *pFirstBinding, *pThisBinding; SQLSMALLINT siDisplaySize; RETCODE RetCode; int iCount = 0; // Allocate memory for each column AllocateBindings(lpStmt, cCols, &pFirstBinding, &siDisplaySize); // Set the display mode and write the titles DisplayTitles(lpStmt, siDisplaySize, pFirstBinding); // Fetch and display the data do { // Fetch a row if (iCount++ >= gHeight - 2) { char szInput[100]; printf(" "); SetConsole(siDisplaySize + 2, TRUE); printf(" Press ENTER to continue, Q to quit"); printf("%d", gHeight); SetConsole(siDisplaySize + 2, FALSE); gets(szInput); if ((*szInput == 'Q') || (*szInput == 'q')) goto Exit; iCount = 1; DisplayTitles(lpStmt, siDisplaySize, pFirstBinding); } TRYODBC(lpStmt, SQL_HANDLE_STMT, RetCode = SQLFetch(lpStmt)); if (RetCode == SQL_NO_DATA_FOUND) break; if (RetCode == SQL_NO_DATA) break; // Display the data. Ignore truncations for (pThisBinding = pFirstBinding; pThisBinding; pThisBinding = pThisBinding->sNext) { if (pThisBinding->indPtr != SQL_NULL_DATA) { _tprintf(pThisBinding->fChar ? TEXT(DISPLAY_FORMAT_C) : TEXT(DISPLAY_FORMAT), PIPE, pThisBinding->siDisplaySize, pThisBinding->siDisplaySize, pThisBinding->szBuffer); } else { _tprintf(TEXT(DISPLAY_FORMAT_C), PIPE, pThisBinding->siDisplaySize, pThisBinding->siDisplaySize, "<NULL>"); } } _tprintf(TEXT(" %c\n"), PIPE); } while ( 1); SetConsole(siDisplaySize + 2, TRUE); printf("%*.*s", siDisplaySize + 2, siDisplaySize + 2, " "); SetConsole(siDisplaySize + 2, FALSE); printf("\n"); Exit: // Clean up the allocated buffers while (pFirstBinding) { pThisBinding = pFirstBinding->sNext; free(pFirstBinding->szBuffer); free(pFirstBinding); pFirstBinding = pThisBinding; } }
int _tmain(int argc, TCHAR **argv) { HENV lpEnv = NULL; HDBC lpDbc = NULL; HSTMT lpStmt = NULL; TCHAR *pszConnStr; TCHAR szInput[SQL_QUERY_SIZE]; TCHAR *szLoc = NULL; // Allocate an environment if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &lpEnv) == SQL_ERROR) { fprintf(stderr, "Unable to allocate an environment handle\n"); exit(-1); } // Register this as an application that expects 2.x behavior, // you must register something if you use AllocHandle TRYODBC(lpEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(lpEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, 0)); // Allocate a connection TRYODBC(lpEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, lpEnv, &lpDbc)); if (argc > 1) { pszConnStr = *++argv; } else { pszConnStr = NULL; } // Connect to the driver. Use the connection string if supplied // on the input, otherwise let the driver manager prompt for input. _tprintf("calling connect\n"); TRYODBC(lpDbc, SQL_HANDLE_DBC, SQLDriverConnect(lpDbc, GetDesktopWindow(), (SQLCHAR*) pszConnStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE)); fprintf(stderr, "Connected!\n"); TRYODBC(lpDbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT, lpDbc, &lpStmt)); printf("Enter SQL commands, type (control)Z to exit\nSQL COMMAND>"); // Loop to get input and execute queries while (_fgetts(szInput, SQL_QUERY_SIZE - 1, stdin)) { // Execute the query if (!(*szInput)) { printf("SQL COMMAND>"); continue; } if ('!' == szInput[0]) { int len = strlen(szInput); szInput[len] = '\0'; if (0 == strcmp("tables", szInput)) { DoTables(lpStmt); } else { _tprintf("unknown command\n"); } } else { szLoc = strstr(szInput, "?"); if (NULL == szLoc) { if (!DoDirect(lpStmt, (SQLCHAR*) szInput)) { goto Exit; } } else { if (!DoPrepared(lpDbc, szInput)) { goto Exit; } } } TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLFreeStmt(lpStmt, SQL_CLOSE)); printf("SQL COMMAND>"); } Exit: // Free ODBC handles and exit if (lpDbc) { SQLDisconnect(lpDbc); SQLFreeConnect(lpDbc); } if (lpEnv) SQLFreeEnv(lpEnv); printf("\nDisconnected."); return 0; }
int main(int argc, char **argv) { SQLHENV hEnv = NULL; SQLHDBC hDbc = NULL; SQLHSTMT hStmt = NULL; char* pConnStr; char pQuery[1000]; bool silent = true; if (argc != 5) { fprintf(stderr, "Usage: %s <ConnString> <pkey range> <ccol range> <rand seed>\n", argv[0]); return 1; } pConnStr = argv[1]; char *endptr; long long numkeys = strtoll(argv[2], &endptr, 10); long long rowsperkey = strtoll(argv[3], &endptr, 10); int seed = atoi(argv[4]); struct drand48_data lcg; srand48_r(seed, &lcg); // Allocate an environment if (!silent) fprintf(stderr, "Allocating Handle Enviroment\n"); if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv) == SQL_ERROR) { fprintf(stderr, "Unable to allocate an environment handle\n"); exit(-1); } // Register this as an application that expects 3.x behavior, // you must register something if you use AllocHandle if (!silent) fprintf(stderr, "Setting to ODBC3\n"); TRYODBC(hEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0)); // Allocate a connection if (!silent) fprintf(stderr, "Allocating Handle\n"); TRYODBC(hEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc)); // Connect to the driver. Use the connection string if supplied // on the input, otherwise let the driver manager prompt for input. if (!silent) fprintf(stderr, "Connecting to driver\n"); TRYODBC(hDbc, SQL_HANDLE_DBC, SQLDriverConnect(hDbc, NULL, pConnStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE)); fprintf(stderr, "Connected!\n"); if (!silent) fprintf(stderr, "Allocating statement\n"); TRYODBC(hDbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt)); RETCODE RetCode; SQLSMALLINT sNumResults; // Execute the query if (!silent) fprintf(stderr, "Executing query\n"); long long i; double rval; for (i = 0; i < 100000; i++) { drand48_r(&lcg, &rval); sprintf(pQuery, "SELECT MAX(col1) FROM otest.test10 WHERE ccol = %lld", (long long)(rval * numkeys)); RetCode = SQLExecDirect(hStmt, pQuery, SQL_NTS); switch(RetCode) { case SQL_SUCCESS_WITH_INFO: { HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); // fall through } case SQL_SUCCESS: { // If this is a row-returning query, display // results TRYODBC(hStmt, SQL_HANDLE_STMT, SQLNumResultCols(hStmt,&sNumResults)); if (sNumResults > 0) { DisplayResults(hStmt,sNumResults, silent); } else { SQLLEN cRowCount; TRYODBC(hStmt, SQL_HANDLE_STMT, SQLRowCount(hStmt,&cRowCount)); if (cRowCount >= 0) { printf("%d %s returned\n", (int)cRowCount, (cRowCount == 1) ? "row" : "rows"); } } break; } case SQL_ERROR: { HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); break; } default: fprintf(stderr, "Unexpected return code %hd!\n", RetCode); } } TRYODBC(hStmt, SQL_HANDLE_STMT, SQLFreeStmt(hStmt, SQL_CLOSE)); Exit: // Free ODBC handles and exit if (hStmt) { SQLFreeHandle(SQL_HANDLE_STMT, hStmt); } if (hDbc) { SQLDisconnect(hDbc); SQLFreeHandle(SQL_HANDLE_DBC, hDbc); } if (hEnv) { SQLFreeHandle(SQL_HANDLE_ENV, hEnv); } return 0; }
int _tmain(int argc, TCHAR **argv) { SQLHENV lpEnv = NULL; SQLHDBC lpDbc = NULL; SQLHSTMT lpStmt = NULL; TCHAR *pszConnStr; TCHAR szInput[SQL_QUERY_SIZE]; // Allocate an environment if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&lpEnv) == SQL_ERROR) { fprintf(stderr,"Unable to allocate an environment handle\n"); exit(-1); } // Register this as an application that expects 2.x behavior, // you must register something if you use AllocHandle TRYODBC(lpEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(lpEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC2, 0)); // Allocate a connection TRYODBC(lpEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC,lpEnv,&lpDbc)); if (argc > 1) { pszConnStr = *++argv; } else { pszConnStr = NULL; } // Connect to the driver. Use the connection string if supplied // on the input, otherwise let the driver manager prompt for input. TRYODBC(lpDbc, SQL_HANDLE_DBC, SQLDriverConnect(lpDbc, GetDesktopWindow(), pszConnStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE)); fprintf(stderr,"Connected!\n"); TRYODBC(lpDbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT,lpDbc,&lpStmt)); printf("Enter SQL commands, type (control)Z to exit\nSQL COMMAND>"); // Loop to get input and execute queries while(_fgetts(szInput, SQL_QUERY_SIZE-1, stdin)) { RETCODE RetCode; SQLSMALLINT sNumResults; // Execute the query if (!(*szInput)) { printf("SQL COMMAND>"); continue; } RetCode = SQLExecDirect(lpStmt,szInput,SQL_NTS); switch(RetCode) { case SQL_SUCCESS_WITH_INFO: { HandleError(lpStmt,SQL_HANDLE_STMT,RetCode); // fall through } case SQL_SUCCESS: { // If this is a row-returning query, display // results TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLNumResultCols(lpStmt,&sNumResults)); if (sNumResults > 0) { DisplayResults(lpStmt,sNumResults); } else { SQLLEN siRowCount; TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLRowCount(lpStmt,&siRowCount)); if (siRowCount >= 0) { _tprintf(TEXT("%d %s affected\n"), siRowCount, siRowCount == 1 ? TEXT("row") : TEXT("rows")); } } break; } case SQL_ERROR: { HandleError(lpStmt,SQL_HANDLE_STMT,RetCode); break; } default: fprintf(stderr,"Unexpected return code %d!\n",RetCode); } TRYODBC(lpStmt, SQL_HANDLE_STMT, SQLFreeStmt(lpStmt,SQL_CLOSE)); printf("SQL COMMAND>"); } Exit: // Free ODBC handles and exit if (lpDbc) { SQLDisconnect(lpDbc); SQLFreeConnect(lpDbc); } if (lpEnv) SQLFreeEnv(lpEnv); printf("\nDisconnected."); return 0; }
void AllocateBindings(HSTMT hStmt, SQLSMALLINT cCols, BINDING **ppBinding, SQLSMALLINT *pDisplay) { SQLSMALLINT iCol; BINDING *pThisBinding, *pLastBinding = NULL; SQLLEN cchDisplay, ssType; SQLSMALLINT cchColumnNameLength; *pDisplay = 0; for (iCol = 1; iCol <= cCols; iCol++) { pThisBinding = (BINDING *)(malloc(sizeof(BINDING))); if (!(pThisBinding)) { fwprintf(stderr, L"Out of memory!\n"); exit(-100); } if (iCol == 1) { *ppBinding = pThisBinding; } else { pLastBinding->sNext = pThisBinding; } pLastBinding = pThisBinding; // Figure out the display length of the column (we will // bind to char since we are only displaying data, in general // you should bind to the appropriate C type if you are going // to manipulate data since it is much faster...) TRYODBC(hStmt, SQL_HANDLE_STMT, SQLColAttribute(hStmt, iCol, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL, &cchDisplay)); // Figure out if this is a character or numeric column; this is // used to determine if we want to display the data left- or right- // aligned. // SQL_DESC_CONCISE_TYPE maps to the 1.x SQL_COLUMN_TYPE. // This is what you must use if you want to work // against a 2.x driver. TRYODBC(hStmt, SQL_HANDLE_STMT, SQLColAttribute(hStmt, iCol, SQL_DESC_CONCISE_TYPE, NULL, 0, NULL, &ssType)); pThisBinding->fChar = (ssType == SQL_CHAR || ssType == SQL_VARCHAR || ssType == SQL_LONGVARCHAR); pThisBinding->sNext = NULL; // Arbitrary limit on display size if (cchDisplay > DISPLAY_MAX) cchDisplay = DISPLAY_MAX; // Allocate a buffer big enough to hold the text representation // of the data. Add one character for the null terminator pThisBinding->wszBuffer = (WCHAR *)malloc((cchDisplay+1) * sizeof(WCHAR)); if (!(pThisBinding->wszBuffer)) { fwprintf(stderr, L"Out of memory!\n"); exit(-100); } // Map this buffer to the driver's buffer. At Fetch time, // the driver will fill in this data. Note that the size is // count of bytes (for Unicode). All ODBC functions that take // SQLPOINTER use count of bytes; all functions that take only // strings use count of characters. TRYODBC(hStmt, SQL_HANDLE_STMT, SQLBindCol(hStmt, iCol, SQL_C_TCHAR, (SQLPOINTER) pThisBinding->wszBuffer, (cchDisplay + 1) * sizeof(WCHAR), &pThisBinding->indPtr)); // Now set the display size that we will use to display // the data. Figure out the length of the column name TRYODBC(hStmt, SQL_HANDLE_STMT, SQLColAttribute(hStmt, iCol, SQL_DESC_NAME, NULL, 0, &cchColumnNameLength, NULL)); pThisBinding->cDisplaySize = max((SQLSMALLINT)cchDisplay, cchColumnNameLength); if (pThisBinding->cDisplaySize < NULL_SIZE) pThisBinding->cDisplaySize = NULL_SIZE; *pDisplay += pThisBinding->cDisplaySize + DISPLAY_FORMAT_EXTRA; } return; Exit: exit(-1); return; }
void DisplayResults(HSTMT hStmt, SQLSMALLINT cCols) { BINDING *pFirstBinding, *pThisBinding; SQLSMALLINT cDisplaySize; RETCODE RetCode = SQL_SUCCESS; int iCount = 0; // Allocate memory for each column AllocateBindings(hStmt, cCols, &pFirstBinding, &cDisplaySize); // Set the display mode and write the titles DisplayTitles(hStmt, cDisplaySize+1, pFirstBinding); // Fetch and display the data bool fNoData = false; do { // Fetch a row if (iCount++ >= gHeight - 2) { int nInputChar; bool fEnterReceived = false; while(!fEnterReceived) { wprintf(L" "); SetConsole(cDisplaySize+2, TRUE); wprintf(L" Press ENTER to continue, Q to quit (height:%hd)", gHeight); SetConsole(cDisplaySize+2, FALSE); nInputChar = _getch(); wprintf(L"\n"); if ((nInputChar == 'Q') || (nInputChar == 'q')) { goto Exit; } else if ('\r' == nInputChar) { fEnterReceived = true; } // else loop back to display prompt again } iCount = 1; DisplayTitles(hStmt, cDisplaySize+1, pFirstBinding); } TRYODBC(hStmt, SQL_HANDLE_STMT, RetCode = SQLFetch(hStmt)); if (RetCode == SQL_NO_DATA_FOUND) { fNoData = true; } else { // Display the data. Ignore truncations for (pThisBinding = pFirstBinding; pThisBinding; pThisBinding = pThisBinding->sNext) { if (pThisBinding->indPtr != SQL_NULL_DATA) { wprintf(pThisBinding->fChar ? DISPLAY_FORMAT_C:DISPLAY_FORMAT, PIPE, pThisBinding->cDisplaySize, pThisBinding->cDisplaySize, pThisBinding->wszBuffer); } else { wprintf(DISPLAY_FORMAT_C, PIPE, pThisBinding->cDisplaySize, pThisBinding->cDisplaySize, L"<NULL>"); } } wprintf(L" %c\n",PIPE); } } while (!fNoData); SetConsole(cDisplaySize+2, TRUE); wprintf(L"%*.*s", cDisplaySize+2, cDisplaySize+2, L" "); SetConsole(cDisplaySize+2, FALSE); wprintf(L"\n"); Exit: // Clean up the allocated buffers while (pFirstBinding) { pThisBinding = pFirstBinding->sNext; free(pFirstBinding->wszBuffer); free(pFirstBinding); pFirstBinding = pThisBinding; } }
//int __cdecl wmain(int argc, _In_reads_(argc) WCHAR **argv) //int __cdecl wmain(int argc, WCHAR **argv) int __cdecl wmain2(int argc, WCHAR **argv) { SQLHENV hEnv = NULL; SQLHDBC hDbc = NULL; SQLHSTMT hStmt = NULL; WCHAR* pwszConnStr; WCHAR wszInput[SQL_QUERY_SIZE]; // Allocate an environment if (SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hEnv) == SQL_ERROR) { fwprintf(stderr, L"Unable to allocate an environment handle\n"); exit(-1); } // Register this as an application that expects 3.x behavior, // you must register something if you use AllocHandle TRYODBC(hEnv, SQL_HANDLE_ENV, SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0)); // Allocate a connection TRYODBC(hEnv, SQL_HANDLE_ENV, SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc)); if (argc > 1) { pwszConnStr = *++argv; } else { pwszConnStr = L""; } // Connect to the driver. Use the connection string if supplied // on the input, otherwise let the driver manager prompt for input. TRYODBC(hDbc, SQL_HANDLE_DBC, SQLDriverConnect(hDbc, GetDesktopWindow(), pwszConnStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE)); fwprintf(stderr, L"Connected!\n"); TRYODBC(hDbc, SQL_HANDLE_DBC, SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt)); wprintf(L"Enter SQL commands, type (control)Z to exit\nSQL COMMAND>"); // Loop to get input and execute queries while(_fgetts(wszInput, SQL_QUERY_SIZE-1, stdin)) { RETCODE RetCode; SQLSMALLINT sNumResults; // Execute the query if (!(*wszInput)) { wprintf(L"SQL COMMAND>"); continue; } RetCode = SQLExecDirect(hStmt,wszInput, SQL_NTS); switch(RetCode) { case SQL_SUCCESS_WITH_INFO: { HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); // fall through } case SQL_SUCCESS: { // If this is a row-returning query, display // results TRYODBC(hStmt, SQL_HANDLE_STMT, SQLNumResultCols(hStmt,&sNumResults)); if (sNumResults > 0) { DisplayResults(hStmt,sNumResults); } else { SQLLEN cRowCount; TRYODBC(hStmt, SQL_HANDLE_STMT, SQLRowCount(hStmt,&cRowCount)); if (cRowCount >= 0) { wprintf(L"%Id %s affected\n", cRowCount, cRowCount == 1 ? L"row" : L"rows"); } } break; } case SQL_ERROR: { HandleDiagnosticRecord(hStmt, SQL_HANDLE_STMT, RetCode); break; } default: fwprintf(stderr, L"Unexpected return code %hd!\n", RetCode); } TRYODBC(hStmt, SQL_HANDLE_STMT, SQLFreeStmt(hStmt, SQL_CLOSE)); wprintf(L"SQL COMMAND>"); } Exit: // Free ODBC handles and exit if (hStmt) { SQLFreeHandle(SQL_HANDLE_STMT, hStmt); } if (hDbc) { SQLDisconnect(hDbc); SQLFreeHandle(SQL_HANDLE_DBC, hDbc); } if (hEnv) { SQLFreeHandle(SQL_HANDLE_ENV, hEnv); } wprintf(L"\nDisconnected."); return 0; }