Bind server results to program variables.
CS_RETCODE ct_bind(cmd, item, datafmt, buffer, copied, indicator) CS_COMMAND cmd; CS_INT item; CS_DATAFMT *datafmt; CS_VOID *buffer; CS_INT *copied; CS_SMALLINT *indicator;
A pointer to the CS_COMMAND structure managing a client/server operation.
An integer representing the number of the column, parameter, or status to bind.
When binding a column, item is the column’s column number. The first column in a select statement’s select list is column number 1, the second number 2, and so forth.
When binding a compute column, item is the column number of the compute column. Compute columns are returned in the order in which they are listed in the compute clause. The first column returned is number 1.
When binding a return parameter, item is the parameter number. The first parameter returned by a stored procedure is number 1. Stored procedure return parameters are returned in the same order as the parameters were originally specified in the stored procedure’s create procedure statement. This is not necessarily the same order as specified in the RPC command that invoked the stored procedure. In determining what number to pass as item, do not count non-return parameters. For example, if the second parameter in a stored procedure is the only return parameter, pass item as 1.
When binding a stored procedure return status, item must be 1, as there can be only a single status in a return status result set.
To clear all bindings, pass item as CS_UNUSED, with datafmt, buffer, copied, and indicator as NULL.
The address of a CS_DATAFMT structure that describes the destination variable or array. ct_bind copies the contents of *datafmt before returning. Client-Library does not reference the address in datafmt after ct_bind returns.
The chart below lists the fields in *datafmt that are used by ct_bind and contains general information about the fields. ct_bind ignores fields that it does not use.
Field name |
When used |
Set to |
---|---|---|
name |
Not used. |
Not applicable. |
namelen |
Not used. |
Not applicable. |
datatype |
When binding all types of results. |
A type constant (CS_xxx_TYPE) representing the datatype of the destination variable. For valid type constants, see “Datatypes support”. Open Client user-defined types are valid, provided that user-supplied conversion routines have been installed using cs_set_convert. If datatype is an Open Client user-defined type, ct_bind does not validate any CS_DATAFMT fields except count. ct_bind supports a wide range of type conversions, so datatype can be different from the type returned by the server. For instance, by specifying a destination type of CS_FLOAT_TYPE, a CS_MONEY result can be bound to a CS_FLOAT program variable. The appropriate data conversion happens automatically. ct_bind can perform any conversion supported by cs_convert. For a list of the supported conversions, see the cs_convert reference page in the Open Client and Open Server. If datatype is CS_BOUNDARY_TYPE or CS_SENSITIVITY_TYPE, the *buffer program variable must be of type CS_CHAR. |
format |
When binding result items to character, binary, text, or image destination variables; otherwise CS_FMT_UNUSED. |
A bitmask of the following symbols: For character and text destinations only: CS_FMT_NULLTERM to null-terminate the data, or CS_FMT_PADBLANK to pad to the full length of the variable with spaces. For character, binary, text, and image destinations: CS_FMT_PADNULL to pad to the full length of the variable with nulls. For any type of destination: CS_FMT_UNUSED if no format information is being provided. |
maxlength |
When binding all types of results to non-fixed-length types. When binding to fixed-length types, maxlength is ignored. |
The length of the *buffer destination variable. If buffer points to an array, set maxlength to the length of a single element of the array. When binding to character or binary destinations, maxlength must describe the total length of the destination variable, including any space required for special terminating bytes, such as a null terminator. If maxlength indicates that *buffer is not large enough to hold a result data item, then at fetch time ct_fetch discards the result item that is too large, fetches any remaining items in the row, and returns CS_ROW_FAIL. If this occurs, the contents of *buffer are undefined. |
scale |
When binding to numeric or decimal destinations. |
The maximum number of digits to the right of the decimal point in the destination variable. If the source data is the same type as the destination, then scale can be set to CS_SRC_VALUE to indicate that the destination should pick up its value for scale from the source data. scale must be less than or equal to precision. |
precision |
When binding to numeric or decimal destinations. |
The maximum number of decimal digits that can be represented in the destination variable. If the source data is the same type as the destination, then precision can be set to CS_SRC_VALUE to indicate that the destination should pick up its value for precision from the source data. precision must be greater than or equal to scale. |
status |
Not used. |
Not applicable. |
count |
When binding all types of results. |
The number of result rows to be copied to program variables per ct_fetch or ct_scroll_fetch call. If count is larger than the number of available rows, only the available rows are copied. (Note that only regular row and cursor row result sets contain multiple rows. count must have the same value for all columns in a result set, with one exception: an application can intermix counts of 0 and 1. If count is 0, 1 row is fetched. For ct_scroll_fetch calls, the count value must be equal or greater than CS_CURSOR_ROWS. The count value cannot be less than CS_CURSOR_ROWS, as unpredictable results may occur. |
usertype |
Not used. |
Not applicable. |
locale |
When binding all types of results. |
A pointer to a CS_LOCALE structure containing locale information for the *buffer destination variable. If custom locale information is not required for the variable, pass locale as NULL. |
The address of an array of datafmt−>count variables, each of which is of size datafmt−>maxlength.
*buffer is the program variable or variables to which ct_bind binds the server results. When the application calls ct_fetch to fetch the result data, it is copied into this space.
If buffer is NULL, ct_bind clears the binding for this result item. Note that if buffer is NULL, datafmt, copied, and indicator must also be NULL.
The buffer address must remain
valid as long as binds are active on the command structure.
The address of an array of datafmt−>count integer variables. At fetch time, ct_fetch fills this array with the lengths of the copied data. copied is an optional parameter and can be passed as NULL.
The address of an array of datafmt−>count CS_SMALLINT variables. At fetch time, each variable is used to indicate certain conditions about the fetched data. indicator is an optional parameter and can be passed as NULL.
The following table lists the values that an indicator variable can have:
Indicator value |
Meaning |
---|---|
-1 |
The fetched data was NULL. In this case, no data is copied to *buffer. |
0 |
The fetch was successful. |
integer value > 0 |
The actual length of the server data, if the fetch resulted in truncation. |
ct_bind returns the following values:
Return value |
Meaning |
---|---|
CS_SUCCEED |
The routine completed successfully. |
CS_FAIL |
The routine failed. |
CS_BUSY |
An asynchronous operation is already pending for this connection. For more information, see “Asynchronous programming”. |
Common reasons for a ct_bind failure include:
An illegal datatype specified using datafmt−>datatype.
A bad datafmt−>locale pointer. Initialize datafmt−>locale to NULL if it is not used.
Requested conversion is not available.
CS_RETCODE retcode;
CS_INT num_cols;
CS_INT i;
CS_INT j;
CS_INT row_count = 0;
CS_INT rows_read;
CS_INT disp_len;
CS_DATAFMT *datafmt;
EX_COLUMN_DATA *coldata;
/* Determine the number of columns in this result set */
.... ct_res_info code deleted ....
/*
** Our program variable, called 'coldata', is an array of
** EX_COLUMN_DATA structures. Each array element represents
** one column. Each array element will be re-used for each
** row.
**
** First, allocate memory for the data element to process.
*/
coldata = (EX_COLUMN_DATA *)malloc(num_cols *
sizeof (EX_COLUMN_DATA));
if (coldata == NULL)
{
ex_error("ex_fetch_data: malloc() failed");
return CS_MEM_ERROR;
}
datafmt = (CS_DATAFMT *)malloc(num_cols *
sizeof (CS_DATAFMT));
if (datafmt == NULL)
{
ex_error("ex_fetch_data: malloc() failed");
free(coldata);
return CS_MEM_ERROR;
}
/*
** Loop through the columns, getting a description of each
** one and binding each one to a program variable.
**
** We're going to bind each column to a character string;
** this will show how conversions from server native
** datatypes to strings can occur using bind.
**
** We're going to use the same datafmt structure for both
** the describe and the subsequent bind.
**
** If an error occurs within the for loop, a break is used
** to get out of the loop and the data that was allocated
** is freed before returning.
*/
for (i = 0; i < num_cols; i++)
{
/*
** Get the column description. ct_describe() fills
** the datafmt parameter with a description of the
** column.
*/
retcode = ct_describe(cmd, (i + 1), &datafmt[i]);
if (retcode != CS_SUCCEED)
{
ex_error("ex_fetch_data: ct_describe() failed");
break;
}
/*
** Update the datafmt structure to indicate that we
** want the results in a null terminated character
** string.
**
** First, update datafmt.maxlength to contain the
** maximum possible length of the column. To do this,
** call ex_display_len() to determine the number of
** bytes needed for the character string
** representation, given the datatype described
** above. Add one for the null termination character.
*/
datafmt[i].maxlength
= ex_display_dlen(&datafmt[i]) + 1;
/*
** Set datatype and format to tell bind we want things
** converted to null terminated strings.
*/
datafmt[i].datatype = CS_CHAR_TYPE;
datafmt[i].format = CS_FMT_NULLTERM;
/*
** Allocate memory for the column string
*/
coldata[i].value = (CS_CHAR *)malloc
(datafmt[i].maxlength);
if (coldata[i].value == NULL)
{
ex_error("ex_fetch_data: malloc() failed");
retcode = CS_MEM_ERROR;
break;
}
/* Now bind. */
retcode = ct_bind(cmd, (i + 1), &datafmt[i],
coldata[i].value, &coldata[i].valuelen,
&coldata[i].indicator);
if (retcode != CS_SUCCEED)
{
ex_error("ex_fetch_data: ct_bind() failed");
break;
}
}
This code excerpt is from the function ex_fetch_data() routine in the exutils.c sample program. For further examples of using ct_bind, see the compute.c, ex_alib.c, getsend.c, and i18n.c sample programs.
ct_bind can be used to bind a regular or cursor result column, a compute column, a return parameter, or a stored procedure status number. When binding a regular or cursor column, multiple rows of the column can be bound with a single call to ct_bind.
Message, describe, row format, and compute format results
are not bound. This is because result sets of type CS_MSG_RESULT, CS_DESCRIBE_RESULT, CS_ROWFMT_RESULT,
and CS_COMPUTEFMT_RESULT contain
no fetchable data. Instead, these result sets indicate that certain
types of information are available. An application can retrieve
the information by calling other Client-Library routines, such as ct_res_info.
For more information about processing these types of results, see “Results”.
Binding associates a result data item with a program variable. At fetch time, each ct_fetch call copies a row instance of the data item into the variable with which the item is associated.
If a result data item is very large (for example, a large text or image column), it is often more convenient for an application to use ct_get_data to retrieve the data item’s value in chunks, rather than copying the entire value to a bound variable. For more information about ct_get_data, see the ct_get_data reference page, and “text and image data handling”.
ct_bind binds only the current result type. ct_results indicates the current result type through its result_type parameter. For example, if ct_results sets *result_type to CS_STATUS_RESULT, a return status is available for binding.
An application can call ct_res_info to determine the number of items in the current result set and ct_describe to get a description of each item.
An application can only bind a result item to a single program variable. If an application binds a result item to multiple variables, only the last binding has any effect.
An application can use ct_bind to bind to Open Client user-defined datatypes for which conversion routines have been installed. To install a conversion routine for a user-defined datatype, an application calls cs_set_convert. For more information about Open Client user-defined types, see “Open Client user-defined datatypes”.
An application can rebind while actively fetching rows. That is, an application can call ct_bind inside a ct_fetch loop if it needs to change a result item’s binding.
Applications do not have to rebind interspersed regular row results and compute row results that are generated by the same command. If not changed, binding for a particular type of result remains in effect until ct_results returns CS_CMD_DONE to indicate that the results of a logical command are completely processed.
For example, a language command containing a select statement with compute and order by clauses can generate multiple regular row result sets intermixed with compute row result sets. Because they are generated by the same command, each regular row result set and each compute row result set will contain identical columns. An application need only bind each one time (before fetching the first result set of each type). These bindings will remain in effect until both result sets are completely processed (that is, until ct_results returns a result_type of CS_CMD_DONE).
This behavior is independent of the CS_STICKY_BINDS property value.
To clear the binding for a result item, call ct_bind with buffer, datafmt, copied, and indicator as NULL. If the CS_STICKY_BINDS property is enabled (CS_TRUE) for the command structure, then the result-item binding is cleared for all subsequent executions of the command.
To clear all bindings, call ct_bind with item as CS_UNUSED and buffer, datafmt, copied, and indicator as NULL. If the CS_STICKY_BINDS property is enabled (CS_TRUE) for the command structure, then the result-item bindings are cleared only until ct_results returns CS_CMD_DONE (in other words, only for the current execution of the command). If the same command is executed again, the command structure reverts to the previous bindings.
It is not an error to clear a non-existent binding.
By default, the binding between a result item and a program variable remains active until:
ct_results returns CS_CMD_DONE,
The application rebinds the result item, or
The application clears the binding.
The application can change the default duration of bindings by setting the CS_STICKY_BINDS command property. When this property is set to CS_TRUE, then result item bindings remain active across executions of the same server command. Specifically, the binding between a result item and a program variable remains active until:
The application initiates a new server on the same command structure with ct_command, ct_cursor, ct_dynamic, or ct_sendpassthru (but nested cursor-close, cursor-update, or cursor-delete commands do not clear bindings),
The application rebinds the result item,
The application clears the binding, or
The application calls ct_results and it finds a format mismatch between the result set format when the binds were established and the current result set.
The CS_STICKY_BINDS property is useful in batch-processing applications that repeatedly execute the same command.
Commands can return multiple result sets. When the CS_STICKY_BINDS property is CS_TRUE, then Client-Library preserves all bindings for all result sets returned by the first execution of a command for use with later executions of the same command. During first-time command execution, Client-Library also saves information about the formats and sequencing of the returned result sets. After subsequent executions of the same command, each call to ct_results compares the current result formats to the saved result formats. If ct_results finds a mismatch, then it clears all bindings, raises an informational error, and returns CS_SUCCEED.
The result formats from repeated execution of the same command can only vary if the command contains conditional server-side logic (for example, an Adaptive Server stored procedure that contains an if or a while statement).
Applications can check the value of the CS_HAVE_BINDS command property to see if binds were saved from a previous execution of the current command. A value of CS_TRUE indicates one or more binds is active for the current result set. For example, a batch processing application might use the following logic to retrieve result rows:
retrieve CS_HAVE_BINDS property with ct_cmd_props
if CS_HAVE_BINDS is CS_FALSE
bind variables with ct_bind
end if
while ct_fetch returns CS_SUCCEED or CS_ROW_FAIL
process row data
end while
Calling ct_bind does not change the value of CS_HAVE_BINDS. The property reflects whether binds established during a previous execution of the command are still in effect.
As long as a result item binding remains active, the memory addresses given as ct_bind’s buffer parameter must remain valid. Each call to ct_fetch writes data to the buffer address. If the address is invalid, the application will experience memory corruption or a memory access violation. For example, if an application’s C routine binds the address of an automatic variable, and the routine returns before the application calls ct_fetch, then the bound address will be invalid.
Array binding is the process of binding a result column to an array of program variables. At fetch time, multiple rows are copied to an array of variables with a single ct_fetch or ct_scroll_fetch call. An application indicates array binding by setting datafmt−>count to a value greater than 1.
Array binding is only practical for regular row and cursor results. This is because other types of results are considered to be the equivalent of a single row.
When binding columns to arrays, all ct_bind calls in the sequence of calls binding the columns must use the same value for datafmt−>count. For example, when binding three columns to arrays, it is an error to use a count of five in the first two ct_bind calls and a count of three in the last.
However, an application can intermix counts of 0 and 1. counts of 0 and 1 are considered to be equivalent because they both cause ct_fetch to fetch a single row.
If the CS_CURSOR_ROWS value is greater than 1, and you are using a scrollable client cursor, array binding must be used. Failure to use array binding may result in lost efficiency and undefined behavior.
For non-scrollable cursors, either arrays or regular program variables can be used.
ct_describe, ct_fetch, ct_res_info, ct_results, Datatypes support