Retrieving Implicit Conversion of Prefetched LOB Data

Use SQLGetData and SQLBindCol to retrieve the underlying prefetched LOB data by binding the column to SQL_C_CHAR or SQL_C_WCHAR for text locators, or to SQL_C_BINARY for image locators, when Adaptive Server returns a LOB locator.

  1. Set the SQL_ATTR_LOBLOCATOR attribute to enable or disable locators in a connection.

    If EnableLOBLocator has been specified in the connection string, SQL_ATTR_LOBLOCATOR is initialized with the value of EnableLOBLocator, otherwise, it is set to SQL_LOBLOCATOR_OFF, the default value.

  2. To enable locators, set the attribute to SQL_LOBLOCATOR_ON.
  3. Use SQLSetConnectAttr to set the attribute’s value and SQLGetConnectAttr to retrieve its value.
  4. Use SQLSetStatementAttr to set SQL_ATTR_LOBLOCATOR_FETCHSIZE to specify the size in bytes for binary data and in characters for character data of the LOB data to retrieve.

    The default value, 0, indicates that prefetched data is not requested, while a value of -1 retrieves the entire LOB data.

    Note: If the underlying LOB data size of the column being retrieved exceeds the prefetched data size that you have set, native error 3202 is raised when an ODBC client attempts to directly retrieve the data. When this happens, the client can retrieve the complete data by calling SQLGetData to obtain the underlying locator and perform all of the operations available on locators.

    Example 1 – retrieves an image locator using SQLGetData when the prefetched data represents the complete LOB value:

    //Set Autocommit off
    SQLRETURN sr;
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_AUTOCOMMIT, 
       (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
    
    //Enable LOB Locator for this exchange
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_LOBLOCATOR, (SQLPOINTER)SQL_LOCATOR_ON,
       0);
    
    // Set size of prefetched LOB data
    sr = SQLSetStatementAttr(stmt, SQL_ATTR_LOBLOCATOR_FETCHSIZE, (SQLPOINTER)32768, 0);
    
    //Get a locator from the server
    SQLLEN lLOBLen = 0;
    Byte cBin[COL_SIZE];
    SQLLEN lBin = sizeof(CBin);
    unsigned char cLOC[SQL_LOCATOR_SIZE];
    SQLLEN lLOC = sizeof(cLOC);
    
    int id = 4;
    SQLLEN l1 = sizeof(int);
    SQLLEN idLen = sizeof(int);
    sr = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, idLen, 
       0, &id, idLen, &idLen);
    
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    //Execute the select statement to return a locator
    sr = SQLExecDirect(stmt, selectCOL_SQL, SQL_NTS);
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    sr = SQLFetch(stmt);
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    //Retrieve the binary data  (Complete Data is returned)	
    sr = SQLGetData(stmt, 1, SQL_C_BINARY, cBin, lBin, &lBin);
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    
    //Cleanup
    sr = SQLFreeStmt(stmt, SQL_UNBIND);
    sr = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
    sr = SQLFreeStmt(stmt, SQL_CLOSE);
    
    SQLEndTran(SQL_HANDLE_DBC, dbc,SQL_COMMIT);
    
    //Disable LOB Locator for the future
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_LOBLOCATOR, (SQLPOINTER)SQL_LOCATOR_OFF,
       0);

    Example 2 – retrieves an image locator using SQLGetData when prefetched data represents a truncated LOB value:

    //Set Autocommit off
    SQLRETURN sr;
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_AUTOCOMMIT, 
       (SQLPOINTER)SQL_AUTOCOMMIT_OFF, 0);
    
    //Enable LOB Locator for this exchange
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_LOBLOCATOR, 
       (SQLPOINTER)SQL_LOCATOR_ON, 0);
    
    //Set size of prefetched LOB data
    sr = SQLSetStatementAttr(stmt, 
       SQL_ATTR_LOBLOCATOR_FETCHSIZE, (SQLPOINTER)32768, 0);
    
    //Get a locator from the server
    SQLLEN lLOBLen = 0;
    Byte cBin[COL_SIZE];
    SQLLEN lBin = sizeof(CBin);
    unsigned char cLOC[SQL_LOCATOR_SIZE];
    SQLLEN lLOC = sizeof(cLOC);
    
    int id = 4;
    SQLLEN l1 = sizeof(int);
    SQLLEN idLen = sizeof(int);
    sr = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, idLen,
       0, &id, idLen, &idLen);
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    //Execute the select statement to return a locator
    sr = SQLExecDirect(stmt, selectCOL_SQL, SQL_NTS);
    printError(sr, SQL_HANDLE_STMT, stmt);
    sr = SQLFetch(stmt);
    printError(sr, SQL_HANDLE_STMT, stmt);
    
    // Retrieve the binary data(Truncated data is returned)
    sr = SQLGetData(stmt, 1, SQL_C_BINARY, cBin, lBin, &lBin);
    
    if(sr == SQL_SUCCESS_WITH_INFO)
    {
       SQLTCHAR errormsg[ERR_MSG_LEN];
       SQLTCHAR sqlstate[SQL_SQLSTATE_SIZE+1];
       SQLINTEGER nativeerror = 0;
       SQLSMALLINT errormsglen = 0;
    
       retcode = SQLGetDiagRec(handleType, handle, 1, sqlstate, &nativeerror,
          errormsg, ERR_MSG_LEN, &errormsglen);
    
       printf("SqlState: %s Error Message: %s\n", sqlstate, errormsg);
    
       //Handle truncation of LOB data; if data was truncated call SQLGetData to
       // retrieve the locator.
    
       /* Warning returns truncated LOB data */
       if (NativeError == 32028) //Error code may change
       {
          BYTE ImageLocator[SQL_LOCATOR_SIZE];
          sr = SQLGetData(stmt, 1, SQL_C_IMAGE_LOCATOR, &ImageLocator,
             sizeof(ImageLocator), &Len);
          printError(sr, SQL_HANDLE_STMT, stmt);
    
          /* 
             Perform locator specific calls using image Locator on a separate
             statement handle if needed 
          */
       }
    }
    
    //Cleanup
    sr = SQLFreeStmt(stmt, SQL_UNBIND);
    sr = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
    sr = SQLFreeStmt(stmt, SQL_CLOSE);
    
    SQLEndTran(SQL_HANDLE_DBC, dbc,SQL_COMMIT);
    
    //Disable LOB Locator for the future
    sr = SQLSetConnectAttr(dbc, SQL_ATTR_LOBLOCATOR, (SQLPOINTER)SQL_LOCATOR_OFF,
       0);