On 03/11/14 15:58, Dimitry Sibiryakov wrote: >>> As the example: common/calsses/InternalMessageBuffer produces message >>> metadata from BLR >>> using MetadataFromBlr(). After that remote/client/BlrFromMessage produces >>> _different_ BLR >>> from input message metadata, but the rest of interface code works with >>> assumption, that >>> new BLR is compatible with old buffer, created for old BLR. >> Is it really incompatible? What specific format causes troubles? > Public API receives BLR and data buffer from external API. It cannot > expect that user > will always follow internal rules for creating them. So, it cannot be sure if > transformation "external BLR->metadata" and "metadata->internal BLR" is > completely symmetric. > > > Certainly this should be fixed. > > Fix every user application using API to create data buffers in exact > format? It is not > good because a) won't let change this format ever and b) too cruel.
I understand your worries. Will try to explain why they are they wrong in this case. In ISC API we had 2 documented ways to exchange data with firebird server - request with message, described by BLR (old one, used primarily by gsec & qli) and statement with SQLDA (new one, used by isql, most of known to me access components, etc.). First group is implemented by functions like isc_<do-something>_request (they are in IRequest now), second - by isc_dsql_exec<something>. But SQLDA is client-only object - it does not travel over the wire. And isc_dsql_exec* family of calls was not routed through yvalve - it was converted to BLR-based message by client and after it appropriate isc_dsql_exec<something>_m ('m' obviously stands for *M*essage here) was called. Exactly at this point fixed-format BLR came to play - it is the only format understood by undocumented _m functions. In objects API we leave request as is, just put it's functions into interface and expand messages limits. We do not support SQLDA at all, but add a set of functions that work with messages with format, described by IMessageMetadata. It's going to be documented that fields in message should go one by one, each with NULL indicator. We also emulate old API. SQLDA (after your patch) will be converted directly to IMessageMetadata, i.e. here is no place for user BLR. Request-related functions are mapped directly to functions in IRequest. The only place where user BLR can on theory arrive is a set of isc_dsql_exec<something>_m functions. But the are (1)undocumented, (2)never supported non-standard BLR and (3)are candidats to be replaced with error throw instead of supporting them in final FB3 release. Therefore you see - there is actually no place from where non-std BLR can arrive. What may be discussed is should we document exact order of fields in the message or probably let user create arbitrary one. If we decide to use 2 approach - them offsets really should travel over the wire. > Much better would be to hide internal buffer format from user by > interface that allow > to get and set data and null indicators. Something like this: > > class IDataBuffer: IRefCounted { > public: > IMesageMetadata* getMetadata() = 0; > void* getDataPointer(unsigned Index) = 0; > SSHORT* getNullIndPointer(unsigned Index) = 0; > } > > or better > > class IDataBuffer: IRefCounted { > public: > IMesageMetadata* getMetadata() = 0; > void* getDataPointer(unsigned Index) = 0; > bool isNull(unsigned Index) = 0; > vois setIsNull(unsigned Index, bool value) = 0; > } > > Even better would be interface which has getters and setters for every > supported data > type, but, probably, it will be hard to make such interface easily expandable > for new data > types. This is the simplest solution, but requires a lot of virtual calls per every row. Therefore we decided not to use it. >> If we collect all nulls in the beginning of the record not changing ODS, >> we will get unreadable databases. If we do it changing ODS, we have no >> problems. Same for data transfered over network - if we change protocol >> version when changing format of messages traveling between server and >> client - we have no problems. > We can (and I think that we should) separate these things: data received > from user > application, data traveling through network, data processed by engine and > data stored on > disk. Yes, it will add complexity at junctions, but allow to change one > module without > affecting the rest. We already have different formats for data received from user application, data traveling through network and data stored on disk. Just format of data received from user application and data processed by engine is the same according to OSRI requirements. > To accomplish that, every module should work with objects (interfaces) > coming from > outside without attempts to guess their implementation and using only their > API. And where do we guess? We use some documented suggestions. >> Yes, but it's not related with how we provide metadata information to >> client. > I'm not worried about metadata provided to application, but about > metadata received > from application. For example, currently IStatement::execute() receives > pointer to > IMessageMetadata and plain buffer. It can be (more of less) sure that every > single value > in buffer is placed at offset it get from metadata. > But there is no way to check if this metadata return offsets according to > network > buffer rules. No way to check if data in buffer is placed in right order. > Nevertheless, > this buffer is transfered to remote module without doubts. Well, I agree - it's OK to add a check for offsets returned by IMessageMetadata when converting it to BLR. ------------------------------------------------------------------------------ Learn Graph Databases - Download FREE O'Reilly Book "Graph Databases" is the definitive new guide to graph databases and their applications. Written by three acclaimed leaders in the field, this first edition is now available. Download your free book today! http://p.sf.net/sfu/13534_NeoTech Firebird-Devel mailing list, web interface at https://lists.sourceforge.net/lists/listinfo/firebird-devel