Allocating memory for a fetch array
About this task
To allocate memory for a fetch array:
Procedure
Example
The following example code illustrates how you would allocate
memory for fetch arrays for the following prepared query:
SELECT * from blobtab;
The
function is called init_sqlda():
/**********************************************************************
* Function: init_sqlda()
* Purpose: With the sqlda pointer that was returned from the DESCRIBE
* statement, function allocates memory for the fetch arrays
* in the sqldata fields of each column. The function uses
* FetArrSize to determine the size to allocate.
* Returns: < 0 for error
* > 0 error with messagesize
**********************************************************************/
int init_sqlda(struct sqlda *in_da, int print)
{
int i, j,
row_size=0,
msglen=0,
num_to_alloc;
struct sqlvar_struct *col_ptr;
ifx_loc_t *temp_loc;
char *type;
if (print)
printf("columns: %d. \n", in_da->sqld);
/* Step 1: determine row size */
for (i = 0, col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)
{
/* The msglen variable holds the sum of the column sizes in the
* database; these are the sizes that DESCRIBE returns. This
* sum is the amount of memory that ESQL/C needs to store
* one row from the database. This value is <= row_size. */
msglen += col_ptr->sqllen; /* get database sizes */
/* calculate size for C data: string columns get extra byte added
* to hold null terminator */
col_ptr->sqllen = rtypmsize(col_ptr->sqltype, col_ptr->sqllen);
/* The row_size variable holds the sum of the column sizes in
* the client application; these are the sizes that rtypmsize()
* returns. This sum is amount of memory that the client
* application needs to store one row. */
row_size += col_ptr->sqllen;
if(print)
printf("Column %d size: %d\n", i+1, col_ptr->sqllen);
}
if (print)
{
printf("Total message size = %d\n", msglen);
printf("Total row size = %d\n", row_size);
}
EXEC SQL select max(length(cat_descr)) into :blobsize from catalog;
/* Step 2: set FetArrSize global variable to number of elements
* in fetch array; this function calculates the FetArrSize
* value that can fit into the existing fetch buffer.
* If FetBufSize is not set (equals zero), the code assigns a
* default size of 4096 bytes (4 kilobytes). Alternatively, you
* could set FetArrSize to the number elements you wanted to
* have and let ESQL/C size the fetch buffer. See the text in
* "Allocating Memory for the Fetch Arrays" for more information.*/
if (FetArrSize <= 0) /* if FetArrSize not yet initialized */
{
if (FetBufSize == 0) /* if FetBufSize not set */
FetBufSize = 4096; /* default FetBufSize */
FetArrSize = FetBufSize/msglen;
}
num_to_alloc = (FetArrSize == 0)? 1: FetArrSize;
if (print)
{
printf("Fetch Buffer Size %d\n", FetBufSize);
printf("Fetch Array Size: %d\n", FetArrSize);
}
/* set type in sqlvar_struct structure to corresponding C type */
for (i = 0, col_ptr = in_da->sqlvar; i < in_da->sqld; i++,
col_ptr++)
{
switch(col_ptr->sqltype)
{
case SQLCHAR:
type = "char ";
col_ptr->sqltype = CCHARTYPE;
break;
case SQLINT:
case SQLSERIAL:
type = "int ";
col_ptr->sqltype = CINTTYPE;
break;
case SQLBYTES:
case SQLTEXT:
if (col_ptr->sqltype == SQLBYTES)
type = "blob ";
else
type = "text ";
col_ptr->sqltype = CLOCATORTYPE;
/* Step 3 (TEXT & BLOB only): allocate memory for sqldata
* that contains ifx_loc_t structures for TEXT or BYTE column */
temp_loc = (ifx_loc_t *)malloc(col_ptr->sqllen * num_to_alloc);
if (!temp_loc)
{
fprintf(stderr, "blob sqldata malloc failed\n");
return(-1);
}
col_ptr->sqldata = (char *)temp_loc;
/* Step 4 (TEXT & BLOB only): initialize ifx_loc_t structures to
hold blob values in a user-defined buffer in memory */
byfill( (char *)temp_loc, col_ptr->sqllen*num_to_alloc ,0);
for (j = 0; j< num_to_alloc; j++, temp_loc++)
{
/* blob data to go in memory */
temp_loc->loc_loctype = LOCMEMORY;
/* assume none of the blobs are larger than BLOBSIZE */
temp_loc->loc_bufsize = blobsize;
temp_loc->loc_buffer = (char *)malloc(blobsize+1);
if (!temp_loc->loc_buffer)
{
fprintf(stderr, "loc_buffer malloc failed\n");
return(-1);
}
temp_loc->loc_oflags = 0; /* clear flag */
} /* end for */
break;
default: /* all other data types */
fprintf(stderr, "not yet handled(%d)!\n", col_ptr->sqltype);
return(-1);
} /* switch */
/* Step 5: allocate memory for the indicator variable */
col_ptr->sqlind = (short *)malloc(sizeof(short) * num_to_alloc);
if (!col_ptr->sqlind)
{
printf("indicator malloc failed\n");
return -1;
}
/* Step 6 (other data types): allocate memory for sqldata. This function
* casts the pointer to this memory as a (char *). Subsequent
* accesses to the data would need to cast it back to the data
* type that corresponds to the column type. See the print_sqlda()
* function for an example of this casting. */
if (col_ptr->sqltype != CLOCATORTYPE)
{
col_ptr->sqldata = (char *) malloc(col_ptr->sqllen *
num_to_alloc);
if (!col_ptr->sqldata)
{
printf("sqldata malloc failed\n");
return -1;
}
if (print)
printf("column %3d, type = %s(%3d), len=%d\n", i+1, type,
col_ptr->sqltype, col_ptr->sqllen);
}
} /* end for */
return msglen;
}
For more information about how to allocate memory for the sqldata field, see Allocate memory for the sqlda structure.