Subject Re: API: Retrieve/fetch numerical data from database (like an integer/long)
Author nitaligavino <Dan.Crea@apropos.com>
Hello:

Sorry Henrik, I was unable to follow your code snip-it so I don't
have a suggestion on your specific code. However, I have included
some code that I use to allocate the XSQLDA structure after calling
describe, isc_dsql_describe(…), and before calling isc_dsql_fetch
(…). Maybe this will help you:

Once I have allocated the necessary storage I then pass the XSQLDA to
the isc_dsql_fetch(…) to get the results.


I first call this helper to allocate an XSQLDA structure to hold the
result set:

bool IBRecord::Helper_AllocCS(XSQLDA **pDataObj, AT_CUSHORT usFields)
{
// Don't re-allocate if we have enough space already
if(*pDataObj && (usFields <= (*pDataObj)->sqln))
return(true);

// Allocate control storage in bytes
if(usFields > 0 && (*pDataObj = (XSQLDA *)new char
[XSQLDA_LENGTH(usFields)]))
{
// Fill in the version and size
(*pDataObj)->version = SQLDA_VERSION1;
(*pDataObj)->sqln = usFields; // Number of
elements in sqlvar array

// Clear the sql variants being pointed to so we have
a known state
// Since we have one contiguous buffer we can simply
clear from the start
// of the sqlvar structures through the end
memset((void *)(*pDataObj)->sqlvar, 0, (usFields *
sizeof(XSQLVAR)));
return(true);
}

return(false);
}

After the XSQLDA structure is allocated, a call to this method is
made, I loop through the described result set to properly allocate
the variant storage based on the column's described type and null-
ability:

bool IBRecord::Helper_AllocVS(XSQLDA **pDataObj)
{
if(*pDataObj)
{
// Allocate the needed storage
for(int iAlloc=0;iAlloc < (*pDataObj)->sqld;iAlloc++)
{
// Get a pointer to the variant
XSQLVAR *pSqlVar = &(*pDataObj)->sqlvar
[iAlloc];

// Coerce the type from a varying to a text
switch(pSqlVar->sqltype)
{
// Set the varying to NOT NULL text
case SQL_VARYING:
pSqlVar->sqltype = SQL_TEXT;
break;

// Set the varying to nullable text
case SQL_VARYING + 1:
pSqlVar->sqltype = SQL_TEXT +
1;
break;
};

// Allocate sqllen bytes, if we fail then
return false
if((pSqlVar->sqldata = new char[pSqlVar-
>sqllen]) == 0)
{
// Free anything that might have been
allocated
Helper_FreeVS(pDataObj);
return(false);
}

// See if we need to allocate space for the
null indicator flag
if(pSqlVar->sqltype & 1)
pSqlVar->sqlind = new short;

}

return(true);
}

return(false);
}

Best regards,
Dan
--- In ib-support@yahoogroups.com, "Henrik Sitter"
<henrik.sitter@e...> wrote:
> Hello,
>
> I'm working on and off with the Firebird API, and right now I'm
trying
> to retrieve/fetch data from my test database.
>
> As long as the data is stored as VarChar or char, everything works
like
> it should, but when it's stored as numerical data (like an
integer), the
> database returns just BS.
>
> In the coercing and allocating part of my code I use (I suspect
> something is wrong here):
>
> #define ALIGN(ptr, n) ((ptr + n - 1) & ~(n - 1))
> char *r_buffer, *rec_buffer;
> .
> .
> case SQL_LONG:
> r_buffer = (char *)malloc(sizeof(long)+sizeof(int));
> rec_buffer = (char *)ALIGN((long)r_buffer, (sizeof(long)+sizeof
(int)));
> var->sqldata = (char *)((long)rec_buffer);
> break;
> .
> .
>
> In the fetching part I use (this part works, at least when fetching
char
> and VarChar):
>
> .
> .
> int fetch_stat;
> while ((fetch_stat = isc_dsql_fetch(status_vector, &st1, 1,
my_xsqlda))
> == 0)
> {
> for (i = 0; i < my_xsqlda->sqld; i++)
> {
> // process_column is a function that prints the content of
> my_xsqlda->sqlvar[i] to the console.
> process_column(&(my_xsqlda->sqlvar[i]));
> }
> }
> .
> .
>
> Anybody have a clue?