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