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

Reply via email to