Canceling ODBC queries
You can cancel ODBC queries with the SQLCancel() function.
You can cancel ODBC queries with the SQLCancel()
function.
The following example:
- Creates a table
odbccanceltest
- Queries
odbccanceltest
three times, canceling the third query - Runs another query on
dual
to show that the cancelation succeeded
// Example of calling SQLCancel() during SQLFetch()
#include <stdio.h>
#include <stdlib.h>
// Only needed for Windows clients
// #include <windows.h>
// SQL data types and ODBC API functions
#include <sql.h>
#include <sqlext.h>
#include <sqltypes.h>
int main()
{
SQLRETURN ret; // Stores return value from ODBC API calls
SQLHENV hdlEnv; // Handle for the SQL environment object
// Allocate an a SQL environment object
ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hdlEnv);
if(!SQL_SUCCEEDED(ret)) {
printf("Could not allocate a handle.\n");
exit(EXIT_FAILURE);
} else {
printf("Allocated an environment handle.\n");
}
// Set the ODBC version we are going to use to 3.
ret = SQLSetEnvAttr(hdlEnv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER) SQL_OV_ODBC3, SQL_IS_UINTEGER);
if(!SQL_SUCCEEDED(ret)) {
printf("Could not set application version to ODBC 3.\n");
exit(EXIT_FAILURE);
} else {
printf("Application version set to ODBC 3.\n");
}
// Allocate a database handle.
SQLHDBC hdlDbc;
ret = SQLAllocHandle(SQL_HANDLE_DBC, hdlEnv, &hdlDbc);
assert(SQL_SUCCEEDED(ret));
if(!SQL_SUCCEEDED(ret)) {
printf("Could not allocate database handle.\n");
exit(EXIT_FAILURE);
} else {
printf("Database handle allocated.\n");
}
// Connect to the database using
// SQL Connect
printf("Connecting to database.\n");
const char *dsnName = "ExampleDB";
const char* userID = "ExampleUser";
const char* passwd = "password123";
ret = SQLConnect(hdlDbc, (SQLCHAR*)dsnName,
SQL_NTS,(SQLCHAR*)userID,SQL_NTS,
(SQLCHAR*)passwd, SQL_NTS);
if(!SQL_SUCCEEDED(ret)) {
printf("Could not connect to database.\n");
exit(EXIT_FAILURE);
} else {
printf("Connected to database.\n");
}
// Query the v_monitor.current_session table to find the name of the node we've connected to.
// Set up a statement handle
SQLHSTMT hdlStmt;
SQLAllocHandle(SQL_HANDLE_STMT, hdlDbc, &hdlStmt);
assert(SQL_SUCCEEDED(ret));
// Create and populate the sampel table odbccanceltest to test SQLCancel()
SQLExecDirect(hdlStmt, (SQLCHAR *)"CREATE TABLE odbccanceltest(id INTEGER, time TIMESTAMP)",
SQL_NTS);
SQLExecDirect(hdlStmt,
(SQLCHAR *)"INSERT INTO odbccanceltest SELECT row_number() "
"OVER(), slice_time FROM(SELECT slice_time FROM( "
"SELECT '2021-01-01'::timestamp s UNION ALL SELECT "
"'2022-01-01'::timestamp s) sq TIMESERIES "
"slice_time AS '1 second' OVER(ORDER BY s)) sq2;",
SQL_NTS);
ret = SQLPrepare(hdlStmt, (SQLCHAR *)"SELECT id, time FROM "
"odbccanceltest LIMIT 5000000", SQL_NTS) ;
if(!SQL_SUCCEEDED(ret)) {
printf("Could not create prepared statement\n");
SQLFreeHandle(SQL_HANDLE_STMT, hdlStmt);
SQLFreeHandle(SQL_HANDLE_DBC, hdlDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hdlEnv);
exit(EXIT_FAILURE);
} else {
printf("Ceated prepared statement.\n");
}
SQLINTEGER d;
size_t count = 0;
while (SQLFetch(hdlStmt) == SQL_SUCCESS) {
++count;
SQLGetData(hdlStmt, 1, SQL_C_SLONG, (SQLPOINTER)&d, sizeof(d), NULL);
// Cancel the third query
if (count > 3) {
SQLCancel(hdlStmt);
break;
}
}
// Run a follow-up query
ret = SQLPrepare(hdlStmt, (SQLCHAR *)"SELECT 1 FROM dual", SQL_NTS);
ret = SQLExecute(hdlStmt)
if (!SQL_SUCCEEDED(ret)) {
printf("Error in SQLExecute.\n");
exit(EXIT_FAILURE);
}
while (SQLFetch(hdlStmt) == SQL_SUCCESS) {
;
}
// Free handles
printf("Disconnecting and freeing handles.\n");
ret = SQLDisconnect( hdlDbc );
if(!SQL_SUCCEEDED(ret)) {
printf("Error disconnecting from database. Transaction might still be open.\n");
exit(EXIT_FAILURE);
}
SQLFreeHandle(SQL_HANDLE_DBC, hdlDbc);
SQLFreeHandle(SQL_HANDLE_ENV, hdlEnv);
exit(EXIT_SUCCESS);
}