isc_array_put_slice2()

From InterBase

Go Up to API Function Reference


Writes data into an array column.

Syntax

 ISC_STATUS isc_array_put_slice2(
 ISC_STATUS *status_vector, 
 isc_db_handle *db_handle, 
 isc_tr_handle *trans_handle,
 ISC_QUAD *array_id,
 ISC_ARRAY_DESC_V2 *desc,
 void *source_array,
 ISC_LONG *slice_length);
Parameter Type Description

status_vector

ISC_STATUS *

Pointer to the error status vector

db_handle

isc_db_handle *

Pointer to a database handle set by a previous call to ­isc_attach_database(); the handle identifies the database containing the array column.

db_handle returns an error in status_vector if it is NULL.

trans_handle

isc_tr_handle *

Pointer to a transaction handle whose value has been set by a previous isc_start_transaction() call; trans_handle returns an error if NULL.

array_id

ISC_QUAD *

On input, NULL (if you are creating a new array), or the internal identifier for an array to be modified, as assigned by the InterBase engine. This internal identifier must have been determined by previous calls to DSQL functions.

This function changes array_id to be the identifier for the array it creates or modifies (see below).

desc

ISC_ARRAY_DESC _V2*

Descriptor defining the array slice (entire array or subset) to be written to.

source_array

void *

Pointer to a buffer of length ­slice_length, that contains the slice of data that will be copied to the array by this function.

slice_length

ISC_LONG *

Length, in bytes, of the source_array buffer

Description

isc_array_put_slice2() writes data into an array column. You can either store into all the array elements in that column, or into an array slice, a subset of contiguous array elements. The boundaries passed to the function in the array descriptor, desc, specify which elements are to be stored into.

InterBase copies the elements from the buffer, source_array, whose size is specified by slice_length.

The array identifier (array ID), array_id, should be passed as NULL if you are calling ­isc_array_put_slice2() to create a new array. If you are calling it to modify an existing array, then array_id should be the identifier of the array to be modified. This must have been determined by previous calls to DSQL functions.

When ­isc_array_put_slice2() is called with an array ID of an existing array, it:

  • Creates a new array with the same dimensions, bounds, etc., as the specified array, and copies the existing array data to the new array.
  • Writes the data from the array buffer, source_array, to the new array (or slice of the array), per the bounds specified in the array descriptor, desc.
  • Returns in the same array_id variable the array ID of the new array.

When ­isc_array_put_slice2() is called with a NULL array ID, it:

  • Creates a new empty array with dimensions, bounds, etc., as declared for the array column whose name and table name are specified in the array descriptor, desc.
  • Writes the data from the array buffer, source_array, to the new array (or slice of the array)
  • Returns in the array_id variable the array ID of the new array.

Note that in both cases, a new array is created, and its array ID is returned in the array_id variable. The array is temporary until an UPDATE or INSERT statement is executed to associate the array with a particular column of a particular row.

You can make a single call to isc_array_put_slice2() to write all the data you wish to the array. Or, you can call isc_array_put_slice2() multiple times
to store data into various slices of the array. In this case, each call to isc_array_put_slice2() after the first call should pass the array ID of the temporary array. When ­isc_array_put_slice2() is called with the array ID of a temporary array, it copies the specified data to the specified slice of the temporary array (it will not create a new array), and it does not modify array_id.

Before calling isc_array_put_slice2(), there are many operations you must do in order to fill in the array descriptor, desc, determine the appropriate internal array identifier, array_id, and fetch the rows whose array columns you want to access.

For complete step-by-step instructions for setting up an array descriptor and writing array information, see Working with Array Data.

Note: Never execute a DSQL statement that tries to directly store data into an array column. The only way to access array column data is by calling isc_array_get_slice2() or isc_array_put_slice2(). The only supported array references in DSQL statements are ones that specify an entire array column (that is, just the column name) in order to get the internal identifier for the array, which is required by isc_array_get_slice2() and isc_array_put_slice2().

Example

The following program operates on a table named PROJ_DEPT_BUDGET. This table contains the quarterly head counts allocated for each project in each department of an organization. Each row of the table applies to a particular department and project. The quarterly head counts are contained in an array column named QUARTERLY_HEAD_CNT. Each table row has four elements in this column, one per quarter. Each element is a number of type long.

This program selects the rows containing 1994 information for the project named VBASE. For each such row, it calls isc_array_get_slice2() to retrieve a slice of the array, the quarterly head counts for the last two quarters. It then increments each, and calls isc_array_put_slice2() to store the updated values.

In addition to illustrating the usage of isc_array_lookup_desc2(), isc_array_get_slice2(), and isc_array_put_slice2(), the program shows data structure initializations and calls to the DSQL functions required to prepare and execute the SELECT and UPDATE statements, to obtain the array_id needed by isc_array_get_slice2() and isc_array_put_slice2(), to fetch the selected rows one by one, and to update the array ID.

#include <ibase.h>
#define Return_if_Error(stat) if (stat[0] == 1 && stat[1]) {
isc_print_status(stat);
return(1);
}

char *sel_str = "SELECT dept_no, quarterly_head_cnt
FROM proj_dept_budget
WHERE year = 1994 AND proj_id = 'VBASE'";
char *upd_str = "UPDATE proj_dept_budget
SET quarterly_head_count = ?
WHERE CURRENT OF S";
char dept_no[6];
long fetch_stat, SQLCODE, hcnt[2];
short len, i, flag0, flag1, flag2;
ISC_QUAD array_id;
ISC_ARRAY_DESC_V2 desc;
ISC_STATUS status_vector[20];
isc_stmt_handle stmt = NULL;
isc_stmt_handle ustmt = NULL;
char *cursor = "S";
XSQLDA *osqlda, *isqlda;

/* Set up the SELECT statement. */

/* Allocate the output XSQLDA for holding the array data. */
osqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(2));
osqlda->sqln = 2;
osqlda->version = SQLDA_CURRENT_VERSION;

/* Allocate a statement handle for the SELECT statement. */
isc_dsql_allocate_statement(status_vector, &database_handle, &stmt);
Return_if_Error(status_vector);

/* Prepare the query for execution. */
isc_dsql_prepare(status_vector, &tr_handle, &stmt, 0, sel_str, 1, osqlda);
Return_if_Error(status_vector);

/* Set up an XSQLVAR structure to allocate space for each
 * item to be retrieved. */

osqlda->sqlvar[0].sqldata = (char *) dept_no;
osqlda->sqlvar[0].sqltype = SQL_TEXT + 1;
osqlda->sqlvar[0].sqlind = &flag0;

osqlda->sqlvar[1].sqldata = (char *) &array_id;
osqlda->sqlvar[1].sqltype = SQL_ARRAY + 1;
osqlda->sqlvar[1].sqlind = &flag1;

/* Execute the SELECT statement. */
isc_dsql_execute(status_vector, &tr_handle, &stmt, 1, NULL);
Return_if_Error(status_vector);

/* Declare a cursor. */
isc_dsql_set_cursor_name(status_vector, &stmt, cursor, 0);
Return_if_Error(status_vector);

/* Set up the UPDATE statement. */

/* Allocate a statement handle for the UPDATE statement. */
isc_dsql_allocate_statement( status_vector, &database_handle, &ustmt);
Return_if_Error(status_vector);

/* Allocate the input XSQLDA. */
isqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(2));
isqlda->sqln = 1;
1sqlda->version = SQLDA_CURRENT_VERSION;

/* Prepare the UPDATE statement for execution. */
isc_dsql_prepare(status_vector, &tr_handle, &ustmt, 0, upd_str, 1, NULL);
Return_if_Error(status_vector);

/* Initialize the input XSQLDA. */
isc_dsql_describe_bind(status_vector, &ustmt, 1, isqlda);
Return_if_Error(status_vector);

/* Set up the input sqldata and sqlind fields. */
isqlda->sqlvar[0].sqldata = (char *) &array_id;
isqlda->sqlvar[0].sqlind = &flag2;

/* Set up the array descriptor. */
isc_array_lookup_desc2(status_vector,
&database_handle, /* Set by previous isc_attach_database() call. */
&tr_handle, /* Set by previous isc_start_transaction() call. */
"PROJ_DEPT_BUDGET", /* Table name. */
"QUARTERLY_HEAD_CNT", /* Array column name. */
&desc);
Return_if_Error(status_vector);

/* Set the descriptor bounds to those of the slice to be updated, that is, to
 * those of the last two elements. Assuming the array column was defined to
 * contain 4 elements, with a lower bound (subscript) of 1 and an upper bound
 * of 4, the last two elements are at subscripts 3 and 4. */
desc->array_desc_bounds[0].array_bound_lower = 3;
desc->array_desc_bounds[0].array_bound_upper = 4;

/* Fetch and process the rows of interest. */
while ((fetch_stat = isc_dsql_fetch(status_vector, &stmt, 1, osqlda)) == 0){
if (!flag1) {
/* There is array data; get values for last two quarters. */
len = sizeof(hcnt);
/* Fetch the data from the array slice into hcnt array. */
isc_array_get_slice2(status_vector, &database_handle, &tr_handle,
  &array_id, &desc, hcnt, &len);
Return_if_Error(status_vector);
/* Add 1 to each count. */
for (i = 0; i < 2; i++)
hcnt[i] = hcnt[i] + 1;
/* Save new values. */
isc_array_put_slice2(status_vector, &database_handle, &tr_handle,
&array_id, &desc, hcnt, &len);
Return_if_Error(status_vector);
/* Update the array ID. */
isc_dsql_execute( status_vector, &tr_handle, &ustmt, 1, isqlda);
Return_if_Error(status_vector);
};
};
if (fetch_stat != 100L){
SQLCODE = isc_sqlcode(status_vector);
isc_print_sqlerror(SQLCODE, status_vector);
return(1);
}

Return value

isc_array_put_slice2() returns the second element of the status vector. Zero indicates success. A nonzero value indicates an error. For InterBase errors, the first element of the status vector is set to 1, and the second element is set to ­isc_bad_stmt_handle, isc_bad_trans_handle, or another InterBase error code.

To check for an InterBase error, examine the first two elements of the status vector directly. For more information about examining the status vector, see Handling Error Conditions.

See Also

Advance To: