SQLExtendedFetch()
- Fetch an array of rows
SQLExtendedFetch()
extends the function
of SQLFetch()
by returning a row set array
for each bound column. The value the SQL_ATTR_ROWSET_SIZE statement
attribute determines the size of the row set that SQLExtendedFetch()
returns.
ODBC specifications for SQLExtendedFetch()
ODBC specification level | In X/Open CLI CAE specification? | In ISO CLI specification? |
---|---|---|
1.0 (Deprecated) | No | No |
Syntax
For 31-bit applications, use the following syntax:
SQLRETURN SQLExtendedFetch (SQLHSTMT hstmt,
SQLUSMALLINT fFetchType,
SQLINTEGER irow,
SQLUINTEGER FAR *pcrow,
SQLUSMALLINT FAR *rgfRowStatus);
For 64-bit applications, use the following syntax:
SQLRETURN SQLExtendedFetch (SQLHSTMT hstmt,
SQLUSMALLINT fFetchType,
SQLLEN irow,
SQLULEN FAR *pcrow,
SQLUSMALLINT FAR *rgfRowStatus);
Function arguments
The following table lists the data type, use, and description for each argument in this function.
Data type | Argument | Use | Description |
---|---|---|---|
SQLHSTMT | hstmt | input | Specifies the statement handle from which you retrieve an array data. |
SQLUSMALLINT | fFetchType | input | Specifies the direction and type of fetch. Db2 ODBC supports only the fetch direction SQL_FETCH_NEXT (that is, forward-only cursor direction). The next array (row set) of data is always retrieved. |
SQLINTEGER (31-bit) or SQLLEN (64-bit) 1 | irow | input | Reserved for future use. Use any integer for this argument. |
SQLUINTEGER *(31-bit) or SQLULEN * (64-bit)2 | pcrow | output | Returns the number of the rows that are actually fetched. If an error occurs during processing, the pcrow argument points to the ordinal position of the row (in the row set) that precedes the row where the error occurred. If an error occurs retrieving the first row, the pcrow argument points to the value 0. |
SQLUSMALLINT * | rgfRowStatus | output | Returns an array of status values. The number of
elements must equal the number of rows in the row set (as defined
by the SQL_ATTR_ROWSET_SIZE attribute). A status value for each row
that is fetched is returned:
If the number of rows fetched is less than the number of elements in the status array (that is, less than the row set size), the remaining status elements are set to SQL_ROW_NOROW. Db2 ODBC cannot detect whether a row has been
updated or deleted since the start of the fetch. Therefore, the following
ODBC-defined status values are not reported:
|
Notes:
|
Usage
SQLExtendedFetch()
performs an array fetch of a set of rows. An application specifies the size of the array by calling SQLSetStmtAttr()
with the SQL_ROWSET_SIZE attribute.
You cannot mix SQLExtendedFetch()
with SQLFetch()
when you retrieve results.
Before SQLExtendedFetch()
is called the first time, the cursor is positioned before the first row. After SQLExtendedFetch()
is called, the cursor is positioned on the row in the result set corresponding to the last row element in the row set that was just retrieved.
To fetch one row of data at a time, call SQLFetch()
instead of SQLExtendedFetch()
.
The number of elements in the rgfRowStatus array output buffer must equal the number of rows in the row set (as defined by the SQL_ROWSET_SIZE statement attribute). If the number of rows fetched is less than the number of elements in the status array, the remaining status elements are set to SQL_ROW_NOROW.
For any columns in the result set that are bound using the SQLBindCol()
function, Db2 ODBC converts the data for the bound columns as necessary and stores it in the locations that are bound to these columns. The result set can be bound in a column-wise or row-wise fashion.
Column-wise binding: To bind a result set in column-wise fashion, an application specifies SQL_BIND_BY_COLUMN for the SQL_BIND_TYPE statement attribute. (This is the default value.) Then the application calls the SQLBindCol()
function. To bind LOB column values to files, the application can call the SQLBindFileToCol()
function.
When you call SQLExtendedFetch()
, data for the first row is stored at the start of the buffer. Each subsequent row of data is stored at an offset of the number of bytes that you specify with the cbValueMax argument in the SQLBindCol()
call. If, however, the associated C buffer type is fixed-width (such as SQL_C_LONG), the data is stored at an offset corresponding to that fixed-length from the data for the previous row.
SQLBindCol()
specifies. The number of bytes that are available to return for the first row of that column is stored at the start of the buffer. The number of bytes available to return for each subsequent row is stored at an offset equal to the value that the following C function returns: sizeof(SQLINTEGER)
If the data in the column is null for a particular row, the associated element in the array that the pcbValue argument in SQLBindCol()
points to is set to SQL_NULL_DATA.Row-wise binding: The application needs to first call SQLSetStmtAttr()
with the SQL_BIND_TYPE attribute, with the vParam argument set to the size of the structure capable of holding a single row of retrieved data and the associated data lengths for each column data value.
For each bound column, the first row of data is stored at the address given by the rgbValue argument in SQLBindCol()
. Each subsequent row of data is separated by an offset equal to the number of bytes that you specify in the vParam argument in SQLSetStmtAttr()
from the data for the previous row.
For each bound column, the number of bytes that are available to return for the first row is stored at the address given by the pcbValue argument in SQLBindCol()
. Each subsequent value is separated by an offset equal to the number of bytes you specify in the vParam argument in SQLBindCol()
.
SQLExtendedFetch()
returns errors in the same manner as SQLFetch() with the following exceptions:- When a warning occurs that applies to a particular row in the rowset,
SQLExtendedFetch()
sets the corresponding entry in the row status array to SQL_ROW_SUCCESS, not SQL_ROW_SUCCESS_WITH_INFO. - If errors occur in every row in the rowset,
SQLExtendedFetch()
returns SQL_SUCCESS_WITH_INFO, and not SQL_ERROR. - In each group of status records that applies to an individual row, the first status record that is returned by
SQLExtendedFetch()
contains SQLSTATE 01S01 (error in row). IfSQLExtendedFetch()
cannot return additional SQLSTATEs, it returns only SQLSTATE 01S01.
Handling encoding schemes: The CURRENTAPPENSCH keyword in the initialization file and the fCType argument in SQLBindCol()
or SQLGetData()
determine the encoding scheme of any character or graphic data in the result set.
Return codes
SQLExtendedFetch()
,
it returns one of the following values: - SQL_SUCCESS
- SQL_SUCCESS_WITH_INFO
- SQL_ERROR
- SQL_INVALID_HANDLE
- SQL_NO_DATA_FOUND
Diagnostics
The following table lists each SQLSTATE that this function generates, with a description and explanation for each value.
SQLSTATE | Description | Explanation |
---|---|---|
01004 | Data truncated. | The data that is returned for one or more columns
is truncated. (SQLExtendedFetch() returns SQL_SUCCESS_WITH_INFO
for this SQLSTATE.) |
01S01 | Error in row. | An error occurs while fetching one or more rows.
(SQLExtendedFetch() returns SQL_SUCCESS_WITH_INFO
for this SQLSTATE.) |
07002 | Too many columns. | This SQLSTATE is returned for one or more of the
following reasons:
|
07006 | Invalid conversion. | The data value can not be converted in a meaningful
manner to the data type that the fCType argument
in SQLBindCol() specifies. |
08S01 | Communication link failure. | The communication link between the application and data source fails before the function completes. |
22002 | Invalid output or indicator buffer specified. | The pcbValue argument
in SQLBindCol() specifies a null pointer and the
value of the corresponding column is null. The function can not report
SQL_NULL_DATA. |
22008 | Invalid datetime format or datetime field overflow. | This SQLSTATE is returned for one or more of the
following reasons:
|
22012 | Division by zero is invalid. | A value from an arithmetic expression is returned that results in division by zero. |
22018 | Error in assignment. | This SQLSTATE is returned for one or more of the
following reasons:
|
24000 | Invalid cursor state. | The SQL statement that is executed on the statement handle is not a query. |
58004 | Unexpected system failure. | Unrecoverable system error. |
HY001 | Memory allocation failure. | Db2 ODBC is not able to allocate the required memory to support the execution or the completion of the function. |
HY010 | Function sequence error. | This SQLSTATE is returned for one or more of the
following reasons:
|
HY013 | Unexpected memory handling error. | Db2 ODBC is not able to access the memory that is required to support execution or completion of the function. |
HY019 | Numeric value out of range. | This SQLSTATE is returned for one or more of the
following reasons:
|
HY106 | Fetch type out of range. | The value that thefFetchType argument specifies is not recognized. |
HYC00 | Driver not capable. | This SQLSTATE is returned for one or more of the
following reasons:
|
Example
Although this function is deprecated in ODBC 3.0, this function is not deprecated in Db2 ODBC. However, ODBC applications should use SQLFetchScroll()
, rather than SQLExtendedFetch()
.
Example
SQLExtendedFetch()
to perform
an array fetch. /* ... */
"SELECT deptnumb, deptname, id, name FROM staff, org \
WHERE dept=deptnumb AND job = 'Mgr'";
/* Column-wise */
SQLINTEGER deptnumb[ROWSET_SIZE];
SQLCHAR deptname[ROWSET_SIZE][15];
SQLINTEGER deptname_l[ROWSET_SIZE];
SQLSMALLINT id[ROWSET_SIZE];
SQLCHAR name[ROWSET_SIZE][10];
SQLINTEGER name_l[ROWSET_SIZE];
/* Row-wise (Includes buffer for both column data and length) */
struct {
SQLINTEGER deptnumb_l; /* length */
SQLINTEGER deptnumb; /* value */
SQLINTEGER deptname_l;
SQLCHAR deptname[15];
SQLINTEGER id_l;
SQLSMALLINT id;
SQLINTEGER name_l;
SQLCHAR name[10];
} R[ROWSET_SIZE];
SQLUSMALLINT Row_Stat[ROWSET_SIZE];
SQLUINTEGER pcrow;
int i;
/* ... */
/*********************************************/
/* Column-wise binding */
/*********************************************/
rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt);
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWSET_SIZE, (void*) ROWSET_SIZE, 0);
rc = SQLExecDirect(hstmt, stmt, SQL_NTS);
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, (SQLPOINTER) deptnumb, 0, NULL);
rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) deptname,
15, deptname_l);
rc = SQLBindCol(hstmt, 3, SQL_C_SSHORT, (SQLPOINTER) id, 0, NULL);
rc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) name, 10, name_l);
/* Fetch ROWSET_SIZE rows ast a time, and display */
printf("\nDEPTNUMB DEPTNAME ID NAME\n");
printf("-------- -------------- -------- ---------\n");
while ((rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 0,
&pcrow, Row_Stat)) == SQL_SUCCESS) {
for (i = 0; i < pcrow; i++) {
printf("%8ld %-14s %8ld %-9s\n", deptnumb[i], deptname[i],
id[i], name[i]);
}
if (pcrow < ROWSET_SIZE)
break;
} /* endwhile */
if (rc != SQL_NO_DATA_FOUND && rc != SQL_SUCCESS)
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
/*********************************************/
/* Row-wise binding */
/*********************************************/
rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/* Set maximum number of rows to receive with each extended fetch */
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWSET_SIZE, (void*) ROWSET_SIZE, 0);
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/*
* Set vparam to size of one row, used as offset for each bindcol
* rgbValue
*/
/* ie. &(R[0].deptnumb) + vparam = &(R[1].deptnum) */
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_BIND_TYPE,
(void*) (sizeof(R) / ROWSET_SIZE), 0);
rc = SQLExecDirect(hstmt, stmt, SQL_NTS);
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, (SQLPOINTER) &R[0].deptnumb, 0,
&R[0].deptnumb_l);
rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) R[0].deptname, 15,
&R[0].deptname_l);
rc = SQLBindCol(hstmt, 3, SQL_C_SSHORT, (SQLPOINTER) &R[0].id, 0,
&R[0].id_l);
rc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) R[0].name, 10, &R[0].name_l);
/* Fetch ROWSET_SIZE rows at a time, and display */
printf("\nDEPTNUMB DEPTNAME ID NAME\n");
printf("-------- -------------- -------- ---------\n");
while ((rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 0, &pcrow, Row_Stat))
== SQL_SUCCESS) {
for (i = 0; i < pcrow; i++) {
printf("%8ld %-14s %8ld %-9s\n", R[i].deptnumb, R[i].deptname,
R[i].id, R[i].name);
}
if (pcrow < ROWSET_SIZE)
break;
} /* endwhile */
if (rc != SQL_NO_DATA_FOUND && rc != SQL_SUCCESS)
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/* Free handles, commit, exit */
/* ... */