On 06/22/2016 09:21 AM, Jiří Činčura wrote:
> Hello,
>
> when I finally grasped the FB_MESSAGE I realized that's not going to
> help me. It generates struct and I have to know in advance the shape of
> it. Which I don't know for whatever external procedure user writes.
Yes, that works only for fixed formats.
> So any other way to read/write the values? Basically just set of
> methods/extensions, that I can call based on type from input/output
> metadata.
input/output metadata (that's IMessageMetadata, yes?) provide you with a
set of methods needed to access data in buffer correctly
unavoidable one is getOffset() - it returns offset in a buffer where
data is placed
> Maybe I can convert the data to XSQLDA/XSQLVAR shape? For these I
> already have routines to read/write it.
>
Yes, you can - but that's ugly choice. You loose for example ability to
access objects with names >31 symbol long.
And you get an old hell of placing character set id in different non-std
places.
In isql I use the following struct instead:
struct IsqlVar
{
const char* field;
const char* relation;
const char* owner;
const char* alias;
int subType, scale;
unsigned type, length, charSet;
bool nullable;
short* nullInd;
union TypeMix
{
ISC_TIMESTAMP* asDateTime;
ISC_TIME* asTime;
ISC_DATE* asDate;
SSHORT* asSmallint;
SLONG* asInteger;
SINT64* asBigint;
float* asFloat;
double* asDouble;
FB_BOOLEAN* asBoolean;
ISC_QUAD* blobid;
vary* asVary;
char* asChar;
void* setPtr;
};
TypeMix value;
};
And the following routine fills it:
processing_state ISQL_fill_var(IsqlVar* var,
Firebird::IMessageMetadata* msg,
unsigned index,
UCHAR* buf)
{
var->field = msg->getField(fbStatus, index); if (failed())
return ps_ERR;
var->relation = msg->getRelation(fbStatus, index); if (failed())
return ps_ERR;
var->owner = msg->getOwner(fbStatus, index); if (failed())
return ps_ERR;
var->alias = msg->getAlias(fbStatus, index); if (failed())
return ps_ERR;
var->subType = msg->getSubType(fbStatus, index); if (failed())
return ps_ERR;
var->scale = msg->getScale(fbStatus, index); if (failed())
return ps_ERR;
var->type = msg->getType(fbStatus, index); if (failed())
return ps_ERR;
var->length = msg->getLength(fbStatus, index); if (failed())
return ps_ERR;
var->charSet = msg->getCharSet(fbStatus, index); if (failed())
return ps_ERR;
var->nullable = msg->isNullable(fbStatus, index); if (failed())
return ps_ERR;
var->nullInd = (short*) &buf[msg->getNullOffset(fbStatus, index)];
if (failed()) return ps_ERR;
var->value.setPtr = &buf[msg->getOffset(fbStatus, index)];
if (failed()) return ps_ERR;
return CONT;
}
fbStatus here is CheckStatusWrapper (I was not ready to rework errors
handling in isql), if you use ThrowStatusWrapper instead code "if
(failed()) return ps_ERR;" is not needed.
------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
Firebird-Devel mailing list, web interface at
https://lists.sourceforge.net/lists/listinfo/firebird-devel