Executing functions asynchronously in CLI applications

Executing functions asynchronously in CLI applications is part of the larger task of programming with CLI. The task of enabling asynchronous functions and working with those functions involves ensuring that asynchronous execution is supported, initializing the application for asynchronous execution, and working with the functions to take advantage of asynchronous execution.

Before you begin

Before you begin setting up your CLI application for asynchronous execution, you must allocate an environment handle and a connection handle. This is part of the task of initializing your CLI application.

About this task

Note: Starting from Version 9.7, Fix Pack 4, this feature can also be used with the CLI load processing feature.
An application can have at most 1 active function running in asynchronous mode on any one connection. If asynchronous mode is enabled at the connection level, all statements already allocated, as well as future statement handles allocated on the connection will be enabled for asynchronous execution.

Procedure

  1. Call SQLGetInfo() with InfoType SQL_ASYNC_MODE to ensure that functions can be called asynchronously. For example:
        /* See what type of Asynchronous support is available. */
        rc = SQLGetInfo( hdbc, /* Connection handle */
                         SQL_ASYNC_MODE, /* Query the support available */
                         &ubuffer, /* Store the result in this variable */
                         4, 
                         &outlen);
    The call to the SQLGetInfo() function will return one of the following values:
    • SQL_AM_STATEMENT: asynchronous execution can be turned on or off at a statement level.
    • SQL_AM_CONNECTION: asynchronous execution can be turned on or off at a connection level.
    • SQL_AM_NONE: asynchronous execution is not supported. Your application cannot be set up for asynchronous execution. This will be returned for one of two reasons:
      • The datasource itself does not support asynchronous execution.
      • The CLI/ODBC configuration keyword ASYNCENABLE has been specifically set to disable asynchronous execution.
  2. Set the SQL_ATTR_ASYNC_ENABLE attribute using SQLSetStmtAttr() or SQLSetConnectAttr() to enable your application for asynchronous execution if the return value from SQLGetInfo() is either SQL_AM_STATEMENT or SQL_AM_CONNECTION.
    • If the return value is SQL_AM_STATEMENT, set SQL_ATTR_ASYNC_ENABLE to SQL_ASYNC_ENABLE_ON using SQLSetStmtAttr(). For example:
          /* Set statement level asynchronous execution on */
          rc = SQLSetStmtAttr( hstmt, /* Statement handle */
                               SQL_ATTR_ASYNC_ENABLE,
                               (SQLPOINTER) SQL_ASYNC_ENABLE_ON,
                               0);
    • If the return value is SQL_AM_CONNECTION, set the SQL_ATTR_ASYNC_ENABLE to SQL_ASYNC_ENABLE_ON using SQLSetConnectAttr(). For example:
          /* Set connection level asynchronous execution on */
          rc = SQLSetConnectAttr( hstmt, /* Connection handle */
                               SQL_ATTR_ASYNC_ENABLE,
                               (SQLPOINTER) SQL_ASYNC_ENABLE_ON,
                               0);
  3. Call a function that supports asynchronous execution and poll the asynchronous function. Refer to the SQL_ATTR_ASYNC_ENABLE connection or statement attribute for a list of functions that can be executed asynchronously.

    The application determines whether the function has completed by calling it repeatedly with the same arguments it used to call the function the first time. A return code of SQL_STILL_EXECUTING indicates it is not yet finished, any other value indicates it has completed. The value other than SQL_STILL_EXECUTING is the same return code it would have returned if it had executed synchronously.

    The following example demonstrates a common while loop that takes both possible outcomes into account:
    while ( (rc = SQLExecDirect(hstmt, sqlstmt, SQL_NTS) ) == SQL_STILL_EXECUTING)
    {
        /* Other processing can be performed here, between each call to
         * see if SQLExecDirect() has finished running asynchronously.
         * This section will never run if CLI runs the function
         * synchronously.
         */
    }
    /* The application continues at this point when SQLExecDirect() */
    /* has finished running. */