Canceling ODBC queries

You can cancel ODBC queries with the SQLCancel() function.

You can cancel ODBC queries with the SQLCancel() function.

The following example:

  1. Creates a table odbccanceltest
  2. Queries odbccanceltest three times, canceling the third query
  3. 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);
}