Bind a program variable to a database column.
CS_RETCODE blk_bind(blkdesc, colnum, datafmt, buffer, datalen, indicator) CS_BLKDESC *blkdesc; CS_INT colnum; CS_DATAFMT *datafmt; CS_VOID *buffer; CS_INT *datalen; CS_SMALLINT *indicator;
A pointer to the CS_BLKDESC that is serving as a control block for the bulk-copy operation. blk_alloc allocates a CS_BLKDESC structure.
The number of the column to bind to the program variable. The first column in a table is column number 1, the second is number 2, and so forth.
A pointer to the CS_DATAFMT structure that describes the program variable to bind to the column.
Table 4-1 lists the fields in *datafmt that are used by blk_bind and contains general information about the fields. blk_bind ignores fields that it does not use:
Field name |
When used |
Sets the field to |
---|---|---|
name |
Not used. |
Not applicable. |
namelen |
Not used. |
Not applicable. |
datatype |
Always. |
A type constant (CS_xxx_TYPE) representing the datatype of the program variable. All type constants listed on the “Types” topics page in the Open Client Client-Library/C Reference Manual are valid. Open Client user-defined types are not valid. blk_bind supports a wide range of type conversions, so datatype can be different from the column’s type. For instance, by specifying a variable type of CS_FLOAT_TYPE, a money column can be bound to a CS_FLOAT program variable. blk_rowxfer_mult or blk_rowxfer perform appropriate conversions when transferring data. For a list of the data conversions provided by Client-Library, see cs_convert in Chapter 2, “CS-Library Routines.” If datatype is CS_BOUNDARY_TYPE or CS_SENSITIVITY_TYPE, the *buffer program variable must be of type CS_CHAR. |
format |
When binding to character- or binary-type destination variables during copy-out operations; otherwise, CS_FMT_UNUSED. |
For variable-length datatypes, the setting is a bit mask that indicates the format of data to be read or the format to write data in. For bulk-copy-out operations, the format flags are the same as for ct_bind. For bulk-copy-in operations, the only format flag is CS_BLK_ARRAY_MAXLEN. For more information on the use of this flag, see “Array binding”. |
maxlength |
When binding to a variable length datatype. When binding to a fixed-length datatype, maxlength is ignored. |
The maximum length of the *buffer program variable. When binding character or binary variables, maxlength must describe the total maximum length of the program variable, including any space required for special terminating bytes, such as a null terminator. During a bulk-copy-in operation, maxlength specifies the maximum length of the data that will be copied from the *buffer program variable. During a bulk-copy-out operation, maxlength is the length of the *buffer program variable. |
scale |
Only when binding to numeric or decimal variables. |
The scale of the program 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 |
Only when binding numeric or decimal destinations. |
The precision of the program 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 |
Always. |
count is the number of rows to transfer per blk_rowxfer_mult or blk_rowxfer call. If count is greater than 1, array binding is considered to be in effect. During a bulk-copy-out operation, if count is larger than the number of available rows, only the available rows are copied. count must have the same value for all columns being transferred, with one exception: An application can intermix counts of 0 and 1. This is because when count is 0, 1 row is transferred. |
usertype |
Not used. |
Not applicable. |
locale |
If supplied, locale is used. Otherwise, default localization applies. |
A pointer to a CS_LOCALE structure containing locale information for the *buffer program variable. |
The address of the program variable to be bound to the column specified by colnum.
For a bulk-copy-in operations, *buffer is the program variable from which blk_rowxfer_mult copies the data.
For bulk-copy-out operations, buffer* is the program variable in which blk_rowxfer_mult places the copied data. If datafmt−>maxlength indicates that *buffer is not large enough to hold the copied data, blk_rowxfer_mult truncates the data at row transfer time. If this occurs, Bulk-Library sets *indicator to the actual length of the available data.
A NULL buffer indicates that data for the column will be transferred using the blk_textxfer routine.
A pointer to the length, in bytes, of the *buffer data.
For bulk-copy-in operations:
If *buffer is not NULL, *datalen represents the actual length of the data contained in the *buffer program variable. An application must set this length before calling blk_rowxfer_mult or blk_rowxfer to transfer rows. In case of variable-length data, the length may be different for each row. If the data is fixed-length, *datalen can be CS_UNUSED, except for array binding. If *datalen is 0, the value of *indicator is used to determine whether the column’s default value or a NULL should be inserted. See Table 4-2 for details.
If *buffer is NULL (indicating that the data will be transferred with blk_textxfer), *datalen indicates the total length of the value to be transferred.
For bulk-copy-out operations:
*datalen represents the actual length of the data copied to *buffer. blk_rowxfer_mult or blk_rowxfer sets *datalen each time it is called to transfer a row.
Since blk_rowxfer_mult or blk_rowxfer sets datalen each time it is called to transfer a row, the datalen parameter must remain local to the function calling blk_bind() and blk_rowxfer(), or blk_rowxfer_mult(). Failure to do so causes invalid results.
A pointer to a CS_INT variable, or for array binding, an array of CS_INT. At row-transfer time, blk_rowxfer_mult or blk_rowxfer read the indicator’s contents to determine certain conditions about the bulk-copy data. See the “List of Bulk-Library routines” section for details.
blk_bind returns:
Returns |
Indicates |
---|---|
CS_SUCCEED |
The routine completed successfully. |
CS_FAIL |
The routine failed. |
blk_bind returns CS_FAIL if the application has not called blk_init to initialize the bulk-copy operation.
/*
** BulkCopyIn()
** BLKDATA and DATA_END are defined in the bulk copy
** example program.
*/
CS_STATIC CS_RETCODE
BulkCopyIn(connection)
CS_CONNECTION *connection;
{
CS_BLKDESC *blkdesc;
CS_DATAFMT datafmt; /* variable descriptions */
Blk_Data *dptr; /* data for transfer */
CS_INT datalen[5]; /* variable data length */
CS_INT len;
CS_INT numrows;
/*
** Ready to start the bulk copy in now that all the
** connections have been made and have a table name.
** Start by getting the bulk descriptor initializing.
*/
...CODE DELETED.....
/*
** Bind the variables to the columns and
** transfer the data.
*/
datafmt.locale = 0;
datafmt.count = 1;
dptr = BLKDATA;
while (dptr->pub_id != DATA_END)
{
datafmt.datatype = CS_INT_TYPE;
datafmt.maxlength = sizeof(CS_INT);
datalen[0] = CS_UNUSED;
if (blk_bind(blkdesc, 1, &datafmt, &dptr->pub_id,
&datalen[0], NULL) != CS_SUCCEED)
{
ex_error("BulkCopyIn: blk_bind(1) failed");
return CS_FAIL;
}
datafmt.datatype = CS_CHAR_TYPE;
datafmt.maxlength = MAX_PUBNAME - 1;
datalen[1] = strlen(dptr->pub_name);
if (blk_bind(blkdesc, 2, &datafmt, dptr->pub_name,
&datalen[1], NULL) != CS_SUCCEED)
{
ex_error("BulkCopyIn: blk_bind(2) failed");
return CS_FAIL;
}
datafmt.maxlength = MAX_PUBCITY - 1;
datalen[2] = strlen(dptr->pub_city);
if (blk_bind(blkdesc, 3, &datafmt, dptr->pub_city,
&datalen[2], NULL) != CS_SUCCEED)
{
ex_error("BulkCopyIn: blk_bind(3) failed");
return CS_FAIL;
}
datafmt.maxlength = MAX_PUBST - 1;
datalen[3] = strlen(dptr->pub_st);
if (blk_bind(blkdesc, 4, &datafmt, dptr->pub_st,
&datalen[3], NULL) != CS_SUCCEED)
{
ex_error("BulkCopyIn: blk_bind(4) failed");
return CS_FAIL;
}
datafmt.maxlength = MAX_BIO - 1;
datalen[4] = strlen((char *)dptr->pub_bio);
if (blk_bind(blkdesc, 5, &datafmt, dptr->pub_bio,
&datalen[4], NULL) != CS_SUCCEED)
{
ex_error("BulkCopyIn: blk_bind(5) failed");
return CS_FAIL;
}
if (blk_rowxfer (blkdesc) == CS_FAIL)
{
ex_error("BulkCopyIn: blk_rowxfer() failed");
return CS_FAIL;
}
dptr++;
}
/* Mark the operation complete and then clean up */
...CODE DELETED.....
return CS_SUCCEED;
}
blk_bind is a client-side routine.
blk_bind binds program variables to table columns in the database. Once variables are bound, subsequent calls to blk_rowxfer_mult copy row data between the database and the bound variables. The copy direction is determined by the application’s earlier call to blk_init.
When copying into a database, an application must call blk_bind once for each column in the database table. When copying out, an application need not call blk_bind for columns in which it has no interest.
To indicate that a column value will be transferred using blk_textxfer, an application calls blk_bind with buffer as NULL. A typical application will use blk_textxfer to transfer large text or image values.
If a text, image, boundary, or sensitivity datatype column is marked for transfer using blk_textxfer, all subsequent columns of these types must also be marked for transfer using blk_textxfer. For example, an application cannot mark the first text column in a row for transfer using blk_textxfer and then bind a subsequent text column to a program variable.
An application can call blk_bind in between calls to blk_rowxfer_mult to reflect changes in a variable’s address or length. If an application calls blk_bind multiple times for a single column or variable, only the last binding takes effect.
An application can call blk_describe to initialize a CS_DATAFMT structure that describes the format of a particular column.
The following table summarizes blk_bind usage when used for bulk-copy-in operations. For information on datafmt fields, see Table 4-1.
When calling blk_bind to |
buffer is |
datalen is |
*indicator is |
---|---|---|---|
Bind to a scalar or array variable from which blk_rowxfer_mult will read column values |
The address of a program variable or array |
A pointer to a variable or array that indicates the length of the values to be read from *buffer.
|
The address of a variable or array that supplies indicator values for the column. *indicator is only considered when *datalen is 0:
|
Indicate that a column value will be transferred using blk_textxfer |
NULL |
The total length of the data that will be sent using blk_textxfer. In this case, datafmt−>maxlength is ignored. |
Ignored. |
When a Bulk-Library application calls blk_bind in a bulk-copy-in operation the buffer, datalen, and indicator pointers passed to blk_bind are recorded. The data at those locations must remain valid until it is read during the call to blk_rowxfer or blk_rowxfer_mult.
The following table summarizes blk_bind usage when used for bulk-copy-out operations. For information on datafmt fields, see Table 4-1.
When calling blk_bind to |
buffer is |
*datalen is |
*indicator is |
---|---|---|---|
Bind to a scalar or array variable into which blk_rowxfer_mult will write column values |
The address of a program variable or array |
A pointer to a variable or to a CS_INT variable for an array, where blk_rowxfer_mult places the length of the values written to *buffer. |
The address of a variable or array that supplies indicator values for the column. blk_rowxfer_mult sets *indicator as follows:
|
Indicate that a column value will be transferred using blk_textxfer |
NULL |
Ignored. In this case, datafmt−>maxlength represents the length of the *buffer data space. |
Ignored. |
When copying in, an application can instruct blk_rowxfer_mult to use a column’s default value by setting *datalen to 0 and *indicator to 0 before calling blk_rowxfer_mult. If no default value is defined for the column, blk_rowxfer_mult inserts a NULL value.
To instruct blk_rowxfer_mult to insert a NULL regardless of a column’s default value, set *datalen to 0 and *indicator to -1 before calling blk_rowxfer_mult.
To clear a binding, call blk_bind with buffer, datafmt, datalen, and indicator as NULL. Otherwise, bindings remain in effect until an application calls blk_done with type as CS_BLK_ALL to indicate that the bulk-copy operation is complete.
To clear all bindings, pass colnum as CS_UNUSED, with buffer, datafmt, datalen, and indicator as NULL. An application typically clears all bindings when it needs to change the count that is being used for array binding.
Array binding is the process of binding a column to an array of program variables. At row-transfer time, multiple rows of the column are transferred either to or from the array of variables with a single blk_rowxfer_mult call. An application indicates array binding by setting datafmt−>count to a value greater than 1.
Array binding works differently for bulk-copy-in and bulk-copy-out operations.
For bulk-copy-in operations that use array binding, you must call blk_bind with buffer, datalen, and indicator pointing to arrays. Each length and indicator variable describes the corresponding data in the buffer array. For fixed-length data, buffer is always a pointer to an array of fixed-length values. For variable-length data (specifically character or binary data), buffer is a pointer to an array of bytes. In the latter case, the packing of values can be loose or dense. The application specifies the packing method for each column by setting flags in the datafmt−>format field:
Setting the BLK_ARRAY_MAXLEN bit in datafmt−>format specifies loose packing of values in the array. blk_rowxfer_mult retrieves the value i by reading datalen[i-1] bytes starting at the byte position computed as:
(i -1) * datafmt−>maxlength
If the BLK_ARRAY_MAXLEN bit is not set in datafmt−>format, column values must be densely packed for blk_rowxfer_mult. Each value must be placed in the column array immediately after the previous value, without padding. blk_rowxfer_mult gets value i by reading datalen[i-1] bytes starting at the byte position computed as:
datalen[i-2] + datalen[i-3] + ... + datalen[0]
In other words, the first value starts at 0, the second at datalen[0], the third at datalen[1] + datalen[0], and so forth.
For example, consider a character column that will receive the values “girl,” “boy,” “man,” and “woman,” and assume that this column is bound with datafmt−>maxlength passed as 7. With loose array binding, the buffer and datalen contents would be:
buffer: girl boy man woman
0 7 14 21
datalen: 4, 3, 3, 5
With densely-packed array binding, the buffer and datalen contents would be:
buffer: girlboymanwoman
0 4 7 10
datalen: 4, 3, 3, 5
For bulk-copy-out operations, array binding performed with blk_bind works the same as array binding performed with ct_bind. Column arrays for bulk-copy-out are always loosely packed.
While using array binding during a bulk-copy-out operation, it is possible for conversion, memory, or truncation errors to occur while blk_rowxfer_mult is writing to the destination arrays. In this case, blk_rowxfer_mult writes a partial result to the destination arrays and returns CS_ROW_FAIL.
If array binding is in effect (for either direction), an application cannot use blk_textxfer to transfer data.