|
From: <ale...@us...> - 2016-01-25 18:34:29
|
Revision: 62860
http://sourceforge.net/p/firebird/code/62860
Author: alexpeshkoff
Date: 2016-01-25 18:34:27 +0000 (Mon, 25 Jan 2016)
Log Message:
-----------
Implemented CORE-5083: Provide method to correcty set offsets in implemented by user IMessageMetadata
Modified Paths:
--------------
firebird/trunk/src/include/firebird/FirebirdInterface.idl
firebird/trunk/src/include/firebird/IdlFbInterfaces.h
firebird/trunk/src/yvalve/YObjects.h
firebird/trunk/src/yvalve/utl.cpp
Added Paths:
-----------
firebird/trunk/examples/interfaces/05.user_metadata.cpp
Added: firebird/trunk/examples/interfaces/05.user_metadata.cpp
===================================================================
--- firebird/trunk/examples/interfaces/05.user_metadata.cpp (rev 0)
+++ firebird/trunk/examples/interfaces/05.user_metadata.cpp 2016-01-25 18:34:27 UTC (rev 62860)
@@ -0,0 +1,260 @@
+/*
+ * PROGRAM: Object oriented API samples.
+ * MODULE: 05.user_metadata.cpp
+ * DESCRIPTION: A sample of user-implemented IMessageMetadata.
+ * Prints firebird user name (SYSDBA by default).
+ *
+ * Example for the following interfaces:
+ *
+ * IOffsetsCallback - callback for IUtil::setOffsets()
+ * IMessageMetadata - how to implement it yourself
+ *
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights
+ * and limitations under the License.
+ *
+ * The Original Code was created by Alexander Peshkoff
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2016 Alexander Peshkoff <pes...@ma...>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#include "ifaceExamples.h"
+
+static IMaster* master = fb_get_master_interface();
+
+/*
+ * Trivial sample of IMessageMetadata implementation.
+ * Metadata is created for a fixed outptu format with single char field.
+ * Therefore index parameter in all functions is ignored.
+ * Because the only possible error is index out of bounds status parameter is ignored too.
+ * Atomic operation is not used in IReferenceCounted cause we do not plan MT support.
+ * Non-array vars used to represent offset and nullOffset of that single field.
+ */
+
+class MyMetadata : public IMessageMetadataImpl<MyMetadata, ThrowStatusWrapper>
+{
+private:
+ class Callback : public IOffsetsCallbackImpl<Callback, ThrowStatusWrapper>
+ {
+ private:
+ MyMetadata* metadata;
+
+ public:
+ Callback(MyMetadata* pmeta)
+ : metadata(pmeta)
+ { }
+
+ //IOffsetsCallback implementation
+ void setOffset(ThrowStatusWrapper* status, unsigned /*index*/, unsigned offset, unsigned nullOffset)
+ {
+ // Typically setOffset() function should save passed offsets
+ // in your implementation of message metadata.
+ metadata->offset = offset;
+ metadata->nullOffset = nullOffset;
+ }
+ };
+
+public:
+ unsigned offset, nullOffset, length;
+
+ MyMetadata()
+ {
+ IUtil* utl = master->getUtilInterface();
+ ThrowStatusWrapper s(master->getStatus());
+ try
+ {
+ Callback cb(this);
+ length = utl->setOffsets(&s, this, &cb);
+ }
+ catch(...)
+ {
+ s.dispose();
+ throw;
+ }
+ s.dispose();
+ }
+
+ // Dummy IReferenceCounted implementation
+ // JUST a SAMPLE - interface will be placed on stack, ignore reference counts !!!
+ // In real life please use your favorite atomic incr/decr here
+ // and create reference counted interfaces on heap.
+ void addRef()
+ { }
+
+ int release()
+ {
+ return 1;
+ }
+
+ // IMessageMetadata implementation
+ unsigned getCount(ThrowStatusWrapper* /*status*/)
+ {
+ return 1;
+ }
+
+ const char* getField(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return NULL;
+ }
+
+ const char* getRelation(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return NULL;
+ }
+
+ const char* getOwner(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return NULL;
+ }
+
+ const char* getAlias(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return NULL;
+ }
+
+ unsigned getType(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return SQL_VARYING;
+ }
+
+ FB_BOOLEAN isNullable(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return false;
+ }
+
+ int getSubType(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return 0;
+ }
+
+ unsigned getLength(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return 20; // Want to make it fit
+ }
+
+ int getScale(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return 0;
+ }
+
+ unsigned getCharSet(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return 0;
+ }
+
+ unsigned getOffset(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return offset;
+ }
+
+ unsigned getNullOffset(ThrowStatusWrapper* /*status*/, unsigned /*index*/)
+ {
+ return nullOffset;
+ }
+
+ IMetadataBuilder* getBuilder(ThrowStatusWrapper* status)
+ {
+ ISC_STATUS err[] = {isc_arg_gds, isc_wish_list, isc_arg_end};
+ status->setErrors(err);
+ return NULL;
+ }
+
+ unsigned getMessageLength(ThrowStatusWrapper* /*status*/)
+ {
+ return length;
+ }
+};
+
+template <typename T>
+T to(const unsigned char* b, unsigned o)
+{
+ return *((T*)(b + o));
+}
+
+int main()
+{
+ int rc = 0;
+ unsigned char* buffer = NULL;
+
+ // set default password if none specified in environment
+ setenv("ISC_USER", "sysdba", 0);
+ setenv("ISC_PASSWORD", "masterkey", 0);
+
+ // status vector and main dispatcher
+ ThrowStatusWrapper status(master->getStatus());
+ IProvider* prov = master->getDispatcher();
+
+ // declare pointers to required interfaces
+ IAttachment* att = NULL;
+ ITransaction* tra = NULL;
+ IResultSet* curs = NULL;
+
+ // Instance of our metadata
+ MyMetadata meta;
+
+ // allocate output buffer
+ buffer = new unsigned char[meta.length];
+
+ try
+ {
+ // attach employee db
+ att = prov->attachDatabase(&status, "employee", 0, NULL);
+
+ // start default transaction
+ tra = att->startTransaction(&status, 0, NULL);
+
+ // open cursor
+ curs = att->openCursor(&status, tra, 0, "select current_user from rdb$database", 3, NULL, NULL, &meta, NULL, 0);
+
+ // fetch record from cursor and print it
+ curs->fetchNext(&status, buffer);
+ ISC_SHORT l = to<ISC_SHORT>(buffer, meta.offset);
+ printf("<%*.*s>\n", l, l, buffer + meta.offset + sizeof(ISC_SHORT));
+
+ // close interfaces
+ curs->close(&status);
+ curs = NULL;
+
+ tra->commit(&status);
+ tra = NULL;
+
+ att->detach(&status);
+ att = NULL;
+ }
+ catch (const FbException& error)
+ {
+ // handle error
+ rc = 1;
+
+ char buf[256];
+ master->getUtilInterface()->formatStatus(buf, sizeof(buf), error.getStatus());
+ fprintf(stderr, "%s\n", buf);
+ }
+
+ // release interfaces after error caught
+ if (curs)
+ curs->release();
+ if (tra)
+ tra->release();
+ if (att)
+ att->release();
+
+ prov->release();
+ status.dispose();
+
+ delete buffer;
+
+ return rc;
+}
Property changes on: firebird/trunk/examples/interfaces/05.user_metadata.cpp
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-c++src
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: firebird/trunk/src/include/firebird/FirebirdInterface.idl
===================================================================
--- firebird/trunk/src/include/firebird/FirebirdInterface.idl 2016-01-25 14:17:50 UTC (rev 62859)
+++ firebird/trunk/src/include/firebird/FirebirdInterface.idl 2016-01-25 18:34:27 UTC (rev 62860)
@@ -911,8 +911,7 @@
interface Util : Versioned
{
- void getFbVersion(Status status, Attachment att,
- VersionCallback callback);
+ void getFbVersion(Status status, Attachment att, VersionCallback callback);
void loadBlob(Status status, ISC_QUAD* blobId,
Attachment att, Transaction tra, const string file, boolean txt);
void dumpBlob(Status status, ISC_QUAD* blobId,
@@ -929,8 +928,14 @@
uint formatStatus(string buffer, uint bufferSize, Status status);
uint getClientVersion(); // Returns major * 256 + minor
XpbBuilder getXpbBuilder(Status status, uint kind, const uchar* buf, uint len);
+ uint setOffsets(Status status, MessageMetadata metadata, OffsetsCallback callback);
}
+interface OffsetsCallback : Versioned
+{
+ void setOffset(Status status, uint index, uint offset, uint nullOffset);
+}
+
interface XpbBuilder : Disposable
{
const uint DPB = 1;
Modified: firebird/trunk/src/include/firebird/IdlFbInterfaces.h
===================================================================
--- firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2016-01-25 14:17:50 UTC (rev 62859)
+++ firebird/trunk/src/include/firebird/IdlFbInterfaces.h 2016-01-25 18:34:27 UTC (rev 62860)
@@ -84,6 +84,7 @@
class ITimerControl;
class IVersionCallback;
class IUtil;
+ class IOffsetsCallback;
class IXpbBuilder;
class ITraceConnection;
class ITraceDatabaseConnection;
@@ -3446,6 +3447,7 @@
unsigned (CLOOP_CARG *formatStatus)(IUtil* self, char* buffer, unsigned bufferSize, IStatus* status) throw();
unsigned (CLOOP_CARG *getClientVersion)(IUtil* self) throw();
IXpbBuilder* (CLOOP_CARG *getXpbBuilder)(IUtil* self, IStatus* status, unsigned kind, const unsigned char* buf, unsigned len) throw();
+ unsigned (CLOOP_CARG *setOffsets)(IUtil* self, IStatus* status, IMessageMetadata* metadata, IOffsetsCallback* callback) throw();
};
protected:
@@ -3538,8 +3540,45 @@
StatusType::checkException(status);
return ret;
}
+
+ template <typename StatusType> unsigned setOffsets(StatusType* status, IMessageMetadata* metadata, IOffsetsCallback* callback)
+ {
+ StatusType::clearException(status);
+ unsigned ret = static_cast<VTable*>(this->cloopVTable)->setOffsets(this, status, metadata, callback);
+ StatusType::checkException(status);
+ return ret;
+ }
};
+ class IOffsetsCallback : public IVersioned
+ {
+ public:
+ struct VTable : public IVersioned::VTable
+ {
+ void (CLOOP_CARG *setOffset)(IOffsetsCallback* self, IStatus* status, unsigned index, unsigned offset, unsigned nullOffset) throw();
+ };
+
+ protected:
+ IOffsetsCallback(DoNotInherit)
+ : IVersioned(DoNotInherit())
+ {
+ }
+
+ ~IOffsetsCallback()
+ {
+ }
+
+ public:
+ static const unsigned VERSION = 2;
+
+ template <typename StatusType> void setOffset(StatusType* status, unsigned index, unsigned offset, unsigned nullOffset)
+ {
+ StatusType::clearException(status);
+ static_cast<VTable*>(this->cloopVTable)->setOffset(this, status, index, offset, nullOffset);
+ StatusType::checkException(status);
+ }
+ };
+
class IXpbBuilder : public IDisposable
{
public:
@@ -12257,6 +12296,7 @@
this->formatStatus = &Name::cloopformatStatusDispatcher;
this->getClientVersion = &Name::cloopgetClientVersionDispatcher;
this->getXpbBuilder = &Name::cloopgetXpbBuilderDispatcher;
+ this->setOffsets = &Name::cloopsetOffsetsDispatcher;
}
} vTable;
@@ -12424,6 +12464,21 @@
return static_cast<IXpbBuilder*>(0);
}
}
+
+ static unsigned CLOOP_CARG cloopsetOffsetsDispatcher(IUtil* self, IStatus* status, IMessageMetadata* metadata, IOffsetsCallback* callback) throw()
+ {
+ StatusType status2(status);
+
+ try
+ {
+ return static_cast<Name*>(self)->Name::setOffsets(&status2, metadata, callback);
+ }
+ catch (...)
+ {
+ StatusType::catchException(&status2);
+ return static_cast<unsigned>(0);
+ }
+ }
};
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUtil> > >
@@ -12451,9 +12506,61 @@
virtual unsigned formatStatus(char* buffer, unsigned bufferSize, IStatus* status) = 0;
virtual unsigned getClientVersion() = 0;
virtual IXpbBuilder* getXpbBuilder(StatusType* status, unsigned kind, const unsigned char* buf, unsigned len) = 0;
+ virtual unsigned setOffsets(StatusType* status, IMessageMetadata* metadata, IOffsetsCallback* callback) = 0;
};
template <typename Name, typename StatusType, typename Base>
+ class IOffsetsCallbackBaseImpl : public Base
+ {
+ public:
+ typedef IOffsetsCallback Declaration;
+
+ IOffsetsCallbackBaseImpl(DoNotInherit = DoNotInherit())
+ {
+ static struct VTableImpl : Base::VTable
+ {
+ VTableImpl()
+ {
+ this->version = Base::VERSION;
+ this->setOffset = &Name::cloopsetOffsetDispatcher;
+ }
+ } vTable;
+
+ this->cloopVTable = &vTable;
+ }
+
+ static void CLOOP_CARG cloopsetOffsetDispatcher(IOffsetsCallback* self, IStatus* status, unsigned index, unsigned offset, unsigned nullOffset) throw()
+ {
+ StatusType status2(status);
+
+ try
+ {
+ static_cast<Name*>(self)->Name::setOffset(&status2, index, offset, nullOffset);
+ }
+ catch (...)
+ {
+ StatusType::catchException(&status2);
+ }
+ }
+ };
+
+ template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IOffsetsCallback> > >
+ class IOffsetsCallbackImpl : public IOffsetsCallbackBaseImpl<Name, StatusType, Base>
+ {
+ protected:
+ IOffsetsCallbackImpl(DoNotInherit = DoNotInherit())
+ {
+ }
+
+ public:
+ virtual ~IOffsetsCallbackImpl()
+ {
+ }
+
+ virtual void setOffset(StatusType* status, unsigned index, unsigned offset, unsigned nullOffset) = 0;
+ };
+
+ template <typename Name, typename StatusType, typename Base>
class IXpbBuilderBaseImpl : public Base
{
public:
Modified: firebird/trunk/src/yvalve/YObjects.h
===================================================================
--- firebird/trunk/src/yvalve/YObjects.h 2016-01-25 14:17:50 UTC (rev 62859)
+++ firebird/trunk/src/yvalve/YObjects.h 2016-01-25 18:34:27 UTC (rev 62860)
@@ -567,6 +567,8 @@
unsigned getClientVersion();
Firebird::IXpbBuilder* getXpbBuilder(Firebird::CheckStatusWrapper* status,
unsigned kind, const unsigned char* buf, unsigned len);
+ unsigned setOffsets(Firebird::CheckStatusWrapper* status, Firebird::IMessageMetadata* metadata,
+ Firebird::IOffsetsCallback* callback);
};
} // namespace Why
Modified: firebird/trunk/src/yvalve/utl.cpp
===================================================================
--- firebird/trunk/src/yvalve/utl.cpp 2016-01-25 14:17:50 UTC (rev 62859)
+++ firebird/trunk/src/yvalve/utl.cpp 2016-01-25 18:34:27 UTC (rev 62860)
@@ -1054,6 +1054,42 @@
}
}
+unsigned UtilInterface::setOffsets(CheckStatusWrapper* status, IMessageMetadata* metadata,
+ IOffsetsCallback* callback)
+{
+ try
+ {
+ unsigned count = metadata->getCount(status);
+ check(status);
+
+ unsigned length = 0;
+
+ for (unsigned n = 0; n < count; ++n)
+ {
+ unsigned type = metadata->getType(status, n);
+ check(status);
+ unsigned len = metadata->getLength(status, n);
+ check(status);
+
+ unsigned offset, nullOffset;
+ length = fb_utils::sqlTypeToDsc(length, type, len,
+ NULL /*dtype*/, NULL /*length*/, &offset, &nullOffset);
+
+ callback->setOffset(status, n, offset, nullOffset);
+ check(status);
+ }
+
+ return length;
+ }
+ catch (const Exception& ex)
+ {
+ ex.stuffException(status);
+ }
+
+ return 0;
+}
+
+
} // namespace Why
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|