|
From: <ale...@us...> - 2013-02-17 12:08:59
|
Revision: 57663
http://sourceforge.net/p/firebird/code/57663
Author: alexpeshkoff
Date: 2013-02-17 12:08:53 +0000 (Sun, 17 Feb 2013)
Log Message:
-----------
Modified IStatement interface in our API:
1. Never allocate empty statement - always use att->prepare() to create statement interface
2. Separated IStatement into 2 parts - statement itself and resultset.
3. Added stmt->openCursor() (and att->openCursor() for unprepared statements) to create IResultSet.
4. Always use IMessageMetadata (former IParametersMetadata) to pass message fromat info from client,
therefore avoiding need in BLR generation in client applications.
Modified Paths:
--------------
firebird/trunk/builds/posix/Makefile.in.plugins_examples
firebird/trunk/lang_helpers/gds_codes.ftn
firebird/trunk/lang_helpers/gds_codes.pas
firebird/trunk/src/auth/SecureRemotePassword/Message.h
firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp
firebird/trunk/src/common/StatementMetadata.cpp
firebird/trunk/src/common/StatementMetadata.h
firebird/trunk/src/common/classes/ImplementHelper.cpp
firebird/trunk/src/common/classes/ImplementHelper.h
firebird/trunk/src/common/classes/RefMutex.h
firebird/trunk/src/common/classes/objects_array.h
firebird/trunk/src/common/utils.cpp
firebird/trunk/src/common/utils_proto.h
firebird/trunk/src/dsql/DdlNodes.epp
firebird/trunk/src/dsql/DdlNodes.h
firebird/trunk/src/dsql/DsqlCompilerScratch.h
firebird/trunk/src/dsql/Nodes.h
firebird/trunk/src/dsql/StmtNodes.cpp
firebird/trunk/src/dsql/dsql.cpp
firebird/trunk/src/dsql/dsql.h
firebird/trunk/src/dsql/dsql_proto.h
firebird/trunk/src/include/firebird/ExternalEngine.h
firebird/trunk/src/include/firebird/Provider.h
firebird/trunk/src/include/gen/codetext.h
firebird/trunk/src/include/gen/iberror.h
firebird/trunk/src/include/gen/msgs.h
firebird/trunk/src/include/gen/sql_code.h
firebird/trunk/src/include/gen/sql_state.h
firebird/trunk/src/include/types_pub.h
firebird/trunk/src/jrd/Database.h
firebird/trunk/src/jrd/EngineInterface.h
firebird/trunk/src/jrd/ExtEngineManager.cpp
firebird/trunk/src/jrd/ExtEngineManager.h
firebird/trunk/src/jrd/PreparedStatement.cpp
firebird/trunk/src/jrd/PreparedStatement.h
firebird/trunk/src/jrd/ResultSet.cpp
firebird/trunk/src/jrd/cch.cpp
firebird/trunk/src/jrd/constants.h
firebird/trunk/src/jrd/exe.h
firebird/trunk/src/jrd/extds/InternalDS.cpp
firebird/trunk/src/jrd/extds/InternalDS.h
firebird/trunk/src/jrd/jrd.cpp
firebird/trunk/src/jrd/met.epp
firebird/trunk/src/jrd/par.cpp
firebird/trunk/src/jrd/par_proto.h
firebird/trunk/src/jrd/val.h
firebird/trunk/src/msgs/facilities2.sql
firebird/trunk/src/msgs/messages2.sql
firebird/trunk/src/msgs/system_errors2.sql
firebird/trunk/src/remote/client/interface.cpp
firebird/trunk/src/remote/protocol.h
firebird/trunk/src/remote/remote.h
firebird/trunk/src/remote/server/server.cpp
firebird/trunk/src/yvalve/YObjects.h
firebird/trunk/src/yvalve/gds.cpp
firebird/trunk/src/yvalve/why.cpp
Added Paths:
-----------
firebird/trunk/src/common/MsgMetadata.cpp
firebird/trunk/src/common/MsgMetadata.h
firebird/trunk/src/common/classes/BlrReader.h
firebird/trunk/src/common/classes/BlrWriter.cpp
firebird/trunk/src/common/classes/BlrWriter.h
firebird/trunk/src/common/classes/InternalMessageBuffer.cpp
firebird/trunk/src/common/classes/InternalMessageBuffer.h
firebird/trunk/src/dsql/BlrDebugWriter.cpp
firebird/trunk/src/dsql/BlrDebugWriter.h
firebird/trunk/src/remote/client/BlrFromMessage.cpp
firebird/trunk/src/remote/client/BlrFromMessage.h
Removed Paths:
-------------
firebird/trunk/src/dsql/BlrWriter.cpp
firebird/trunk/src/dsql/BlrWriter.h
firebird/trunk/src/jrd/BlrReader.h
Modified: firebird/trunk/builds/posix/Makefile.in.plugins_examples
===================================================================
--- firebird/trunk/builds/posix/Makefile.in.plugins_examples 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/builds/posix/Makefile.in.plugins_examples 2013-02-17 12:08:53 UTC (rev 57663)
@@ -52,7 +52,8 @@
.PHONY: all udrcpp_example dc_example kh_example
-all: udrcpp_example dc_example kh_example
+#all: udrcpp_example dc_example kh_example
+all: dc_example kh_example
UDR_Objects = $(call makeObjects,../examples/udr,UdrCppExample.cpp)
Modified: firebird/trunk/lang_helpers/gds_codes.ftn
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.ftn 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/lang_helpers/gds_codes.ftn 2013-02-17 12:08:53 UTC (rev 57663)
@@ -1508,6 +1508,12 @@
PARAMETER (GDS__ee_blr_mismatch_names_count = 335545047)
INTEGER*4 GDS__ee_blr_mismatch_name_not_found
PARAMETER (GDS__ee_blr_mismatch_name_not_found = 335545048)
+ INTEGER*4 GDS__bad_result_set
+ PARAMETER (GDS__bad_result_set = 335545049)
+ INTEGER*4 GDS__wrong_message_length
+ PARAMETER (GDS__wrong_message_length = 335545050)
+ INTEGER*4 GDS__no_output_format
+ PARAMETER (GDS__no_output_format = 335545051)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw
Modified: firebird/trunk/lang_helpers/gds_codes.pas
===================================================================
--- firebird/trunk/lang_helpers/gds_codes.pas 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/lang_helpers/gds_codes.pas 2013-02-17 12:08:53 UTC (rev 57663)
@@ -761,6 +761,9 @@
gds_max_args_exceeded = 335545046;
gds_ee_blr_mismatch_names_count = 335545047;
gds_ee_blr_mismatch_name_not_found = 335545048;
+ gds_bad_result_set = 335545049;
+ gds_wrong_message_length = 335545050;
+ gds_no_output_format = 335545051;
gds_gfix_db_name = 335740929;
gds_gfix_invalid_sw = 335740930;
gds_gfix_incmp_sw = 335740932;
Modified: firebird/trunk/src/auth/SecureRemotePassword/Message.h
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/Message.h 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/src/auth/SecureRemotePassword/Message.h 2013-02-17 12:08:53 UTC (rev 57663)
@@ -1,157 +1,265 @@
-#include "../jrd/align.h"
#include "../common/classes/alloc.h"
+#include "../common/classes/auto.h"
+#include "../common/StatusHolder.h"
+#include "../common/MsgMetadata.h"
+
+// This class helps to work with metadata iface
+class Meta : public Firebird::RefPtr<Firebird::IMessageMetadata>
+{
+public:
+ explicit Meta(Firebird::IStatement* stmt, bool out)
+ {
+ Firebird::LocalStatus s;
+ Firebird::IMessageMetadata* m = out ? stmt->getOutputMetadata(&s) : stmt->getInputMetadata(&s);
+ if (!s.isSuccess())
+ {
+ Firebird::status_exception::raise(s.get());
+ }
+ *((Firebird::RefPtr<Firebird::IMessageMetadata>*)this) = m;
+ m->release(); // reference added by function returning iface
+ }
+};
+
+
// This class helps to fill FbMessage with correct values
class Message : public Firebird::FbMessage, public Firebird::GlobalStorage
{
public:
- Message()
- : blrBuf(getPool()), dataBuf(getPool())
+ Message(Firebird::IMessageMetadata* aMeta)
+ : dataBuf(getPool()), fieldCount(0)
{
- blrLength = 0;
- blr = NULL;
- bufferLength = 0;
- buffer = NULL;
+ Firebird::LocalStatus st;
+ metadata = aMeta;
+ buffer = dataBuf.getBuffer(metadata->getMessageLength(&st));
+ check(&st);
+ metadata->addRef();
+ }
- // start message BLR
- blrBuf.add(blr_version5);
- blrBuf.add(blr_begin);
- blrBuf.add(blr_message);
- blrBuf.add(0);
- countOffset = blrBuf.getCount();
- blrBuf.add(0);
- blrBuf.add(0);
-
- varCount = 0;
+ ~Message()
+ {
+ metadata->release();
}
template <typename T>
- unsigned genBlr()
+ static bool checkType(unsigned t, unsigned sz)
{
- // for special types call type-specific BLR generator
- // for generic types use specialization of whole call
- return T::genBlr(blrBuf);
+ return T::unknownDataType();
}
template <typename T>
- void add(unsigned& pos, unsigned& null)
+ unsigned add(unsigned& t, unsigned& sz)
{
- if (blr)
- {
- (Firebird::Arg::Gds(isc_random) << "This is already constructed message").raise();
- }
+ Firebird::LocalStatus st;
- // generate code for variable
- unsigned align = genBlr<T>();
- if (align)
+ unsigned l = metadata->getCount(&st);
+ check(&st);
+ if (fieldCount >= metadata->getMessageLength(&st))
{
- bufferLength = FB_ALIGN(bufferLength, align);
+ (Firebird::Arg::Gds(isc_random) <<
+ "Attempt to add to the message more variables then possible").raise();
}
- pos = bufferLength;
- bufferLength += sizeof(T);
- // generate code for null flag
- blrBuf.add(blr_short);
- blrBuf.add(0);
- align = type_alignments[dtype_short];
- if (align)
+ t = metadata->getType(&st, fieldCount);
+ check(&st);
+ sz = metadata->getLength(&st, fieldCount);
+ check(&st);
+ if (!checkType<T>(t, sz))
{
- bufferLength = FB_ALIGN(bufferLength, align);
+ (Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
}
- null = bufferLength;
- bufferLength += sizeof(short);
- ++varCount;
+ return fieldCount++;
}
- void ready()
+ static void check(Firebird::IStatus* status)
{
- if (blr)
- return;
-
- // Adjust number of variables
- blrBuf[countOffset] = (varCount * 2) & 0xFF;
- blrBuf[countOffset + 1] = ((varCount * 2) >> 8) & 0xFF;
-
- // Complete blr
- blrBuf.add(blr_end);
- blrBuf.add(blr_eoc);
- blrLength = blrBuf.getCount();
- blr = blrBuf.begin();
-
- // Allocate buffer
- buffer = dataBuf.getBuffer(bufferLength);
+ if (!status->isSuccess())
+ {
+ Firebird::status_exception::raise(status->get());
+ }
}
- Firebird::UCharBuffer blrBuf, dataBuf;
- unsigned countOffset, varCount;
+private:
+ Firebird::UCharBuffer dataBuf;
+ unsigned fieldCount;
};
template <>
-unsigned Message::genBlr<SLONG>()
+bool Message::checkType<SLONG>(unsigned t, unsigned sz)
{
- blrBuf.add(blr_long);
- blrBuf.add(0); // scale
- return type_alignments[dtype_long];
+ return t == SQL_LONG && sz == sizeof(SLONG);
}
+
// With template magic, we make the fields strongly-typed.
-template <class T>
+template <typename T>
class Field
{
public:
+ class Null
+ {
+ public:
+ Null()
+ : ptr(NULL)
+ { }
+
+ void linkMessage(short* p)
+ {
+ ptr = p;
+ *ptr = -1; // mark as null initially
+ }
+
+ operator FB_BOOLEAN() const
+ {
+ return (*ptr) ? FB_TRUE : FB_FALSE;
+ }
+
+ FB_BOOLEAN operator=(FB_BOOLEAN val)
+ {
+ *ptr = val ? -1 : 0;
+ return val;
+ }
+
+ private:
+ short* ptr;
+ };
+
explicit Field(Message& m)
- : msg(m), pos(~0), nullPos(~0)
+ : ptr(NULL), type(0), size(0)
{
- msg.add<T>(pos, nullPos);
+ unsigned ind = m.add<T>(type, size);
+
+ Firebird::LocalStatus st;
+ unsigned tmp = m.metadata->getOffset(&st, ind);
+ Message::check(&st);
+ ptr = (T*)(m.buffer + tmp);
+
+ tmp = m.metadata->getNullOffset(&st, ind);
+ Message::check(&st);
+ null.linkMessage((short*)(m.buffer + tmp));
}
- T& operator()()
+ operator T()
{
- msg.ready();
- return *(T*) (msg.buffer + pos);
+ return *ptr;
}
- short& null()
+ T operator= (T newVal)
{
- msg.ready();
- return *(short*) (msg.buffer + nullPos);
+ *ptr = newVal;
+ null = FB_FALSE;
+ return newVal;
}
-private:
- Message& msg;
- unsigned pos, nullPos;
-};
+ operator const char*()
+ {
+ if (!charBuffer)
+ {
+ charBuffer.reset(FB_NEW(*getDefaultMemoryPool()) char[size + 1]);
+ }
-template <short N>
-class VarChar
-{
-public:
- short len;
- char data[N]; // This guarantees N > 0
+ getStrValue(charBuffer);
+ return charBuffer;
+ }
- static unsigned genBlr(Firebird::UCharBuffer& blr)
+ const char* operator= (const char* newVal)
{
- blr.add(blr_varying);
- blr.add(N & 0xFF);
- blr.add((N >> 8) & 0xFF);
- return type_alignments[dtype_varying];
+ setStrValue(newVal, strlen(newVal));
+ null = FB_FALSE;
+ return newVal;
}
- const VarChar& operator=(const char* str)
+ void set(unsigned length, const void* newVal)
{
- strncpy(data, str, N);
- len = strlen(str);
- if (len > N)
- len = N;
- return *this;
+ setStrValue(newVal, length);
+ null = FB_FALSE;
}
- void set(unsigned short l, void* bytes)
+private:
+ void getStrValue(char* to)
{
- if (l > (unsigned short) N)
- l = N;
- memcpy(data, bytes, l);
- len = l;
+ T::incompatibleDataType();
+ //(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
}
+
+ void setStrValue(const void* from, unsigned len)
+ {
+ T::incompatibleDataType();
+ //(Firebird::Arg::Gds(isc_random) << "Incompatible data type").raise();
+ }
+
+ T* ptr;
+ Firebird::AutoPtr<char, Firebird::ArrayDelete<char> > charBuffer;
+
+public:
+ Null null;
+ unsigned type, size;
};
+
+struct Varying
+{
+ short len;
+ char data[1];
+};
+
+template <>
+bool Message::checkType<Varying>(unsigned t, unsigned /*sz*/)
+{
+ return t == SQL_VARYING;
+}
+
+template<>
+void Field<Varying>::getStrValue(char* to)
+{
+ unsigned len = ptr->len;
+ if (len > size)
+ len = size;
+ memcpy(to, ptr->data, len);
+ to[len] = 0;
+}
+
+template<>
+void Field<Varying>::setStrValue(const void* from, unsigned len)
+{
+ if (len > size)
+ len = size;
+ memcpy(ptr->data, from, len);
+ ptr->len = len;
+}
+
+struct Text
+{
+ char data[1];
+};
+
+template <>
+bool Message::checkType<Text>(unsigned t, unsigned /*sz*/)
+{
+ return t == SQL_TEXT;
+}
+
+template<>
+void Field<Text>::getStrValue(char* to)
+{
+ memcpy(to, ptr->data, size);
+ to[size] = 0;
+ unsigned len = size;
+ while(len--)
+ {
+ if (to[len] == ' ')
+ to[len] = 0;
+ else
+ break;
+ }
+}
+
+template<>
+void Field<Text>::setStrValue(const void* from, unsigned len)
+{
+ if (len > size)
+ len = size;
+ memcpy(ptr->data, from, len);
+ if (len < size)
+ memset(&ptr->data[len], ' ', size - len);
+}
Modified: firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/src/auth/SecureRemotePassword/manage/SrpManagement.cpp 2013-02-17 12:08:53 UTC (rev 57663)
@@ -44,60 +44,64 @@
const unsigned int SZ_LOGIN = 31;
const unsigned int SZ_NAME = 31;
+typedef Field<Varying> Varfield;
+typedef Field<Text> Name;
-template <short N>
-void setField(Field<VarChar<N> >& to, Auth::ICharUserField* from)
+void setField(Name& to, Auth::ICharUserField* from)
{
if (from->entered())
{
- to() = from->get();
- to.null() = 0;
+ to = from->get();
}
else
{
- to.null() = -1;
+ to.null = FB_TRUE;
}
}
-// Domains
-typedef Field<VarChar<SZ_LOGIN> > Login;
-typedef Field<VarChar<Auth::RemotePassword::SRP_VERIFIER_SIZE> > Verifier;
-typedef Field<VarChar<Auth::RemotePassword::SRP_SALT_SIZE> > Salt;
-typedef Field<VarChar<SZ_NAME> > Name;
-void allocField(Firebird::AutoPtr<Name>& field, Message& up, Auth::ICharUserField* value, Firebird::string& update, const char* name)
+void allocField(Auth::ICharUserField* value, Firebird::string& update, const char* name)
{
if (value->entered() || value->specified())
{
- field = new Name(up);
update += ' ';
update += name;
update += "=?,";
}
}
+void allocField(Firebird::AutoPtr<Name>& field, Message& up, Auth::ICharUserField* value, const char* name)
+{
+ if (value->entered() || value->specified())
+ {
+ field = new Name(up);
+ }
+}
+
void assignField(Firebird::AutoPtr<Name>& field, Auth::ICharUserField* name)
{
if (field.hasData())
{
if (name->entered())
{
- (*field)() = name->get();
- field->null() = 0;
+ *field = name->get();
+ field->null = FB_FALSE;
}
else
{
fb_assert(name->specified());
- field->null() = -1;
+ field->null = FB_TRUE;
}
}
}
-template <short N>
-void listField(Auth::ICharUserField* to, Field<VarChar<N> >& from)
+void listField(Auth::ICharUserField* to, Name& from)
{
- to->set(from().data);
- to->setEntered(from.null() == 0 ? 1 : 0);
+ to->setEntered(from.null ? 0 : 1);
+ if (!from.null)
+ {
+ to->set(from);
+ }
}
}
@@ -137,27 +141,18 @@
Firebird::LocalStatus s;
Firebird::RefPtr<Firebird::ITransaction> ddlTran(att->startTransaction(&s, 0, NULL));
- if (!s.isSuccess())
- {
- Firebird::status_exception::raise(s.get());
- }
+
try
{
for (const char** sql = script; *sql; ++sql)
{
- att->execute(&s, ddlTran, 0, *sql, 3, 0, NULL, NULL);
- if (!s.isSuccess())
- {
- Firebird::status_exception::raise(s.get());
- }
+ att->execute(&s, ddlTran, 0, *sql, 3, NULL, NULL);
+ check(&s);
}
ddlTran->commit(&s);
- if (!s.isSuccess())
- {
- Firebird::status_exception::raise(s.get());
- }
+ check(&s);
}
catch (const Firebird::Exception&)
{
@@ -218,16 +213,10 @@
Firebird::DispatcherPtr p;
att = p->attachDatabase(status, secDbName, dpb.getBufferLength(), dpb.getBuffer());
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ check(status);
tra = att->startTransaction(status, 0, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ check(status);
}
catch (const Firebird::Exception& ex)
{
@@ -266,11 +255,8 @@
Firebird::string sql;
sql.printf("ALTER ROLE RDB$ADMIN %s AUTO ADMIN MAPPING",
user->operation() == MAP_SET_OPER ? "SET" : "DROP");
- att->execute(status, tra, sql.length(), sql.c_str(), 3, 0, NULL, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ att->execute(status, tra, sql.length(), sql.c_str(), 3, NULL, NULL);
+ check(status);
}
break;
@@ -280,166 +266,211 @@
"INSERT INTO plg$srp_view(PLG$USER_NAME, PLG$VERIFIER, PLG$SALT, PLG$FIRST, PLG$MIDDLE, PLG$LAST) "
"VALUES(?, ?, ?, ?, ?, ?)";
- Message add;
- Login login(add);
- Verifier verifier(add);
- Salt slt(add);
- Name first(add), middle(add), last(add);
+ Firebird::IStatement* stmt = NULL;
+ try
+ {
+ for (unsigned repeat = 0; ; ++repeat)
+ {
+ stmt = att->prepare(status, tra, 0, insert, 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
+ if (status->isSuccess())
+ {
+ break;
+ }
+ else if (repeat > 0)
+ {
+ Firebird::status_exception::raise(status->get());
+ }
- setField(login, user->userName());
- setField(first, user->firstName());
- setField(middle, user->middleName());
- setField(last, user->lastName());
+ const ISC_STATUS* v = status->get();
+ while (v[0] == isc_arg_gds)
+ {
+ if (v[1] == isc_dsql_relation_err)
+ {
+ prepareDataStructures();
+ tra->commit(status);
+ check(status);
+ tra = att->startTransaction(status, 0, NULL);
+ check(status);
+ break;
+ }
+ do
+ {
+ v += 2;
+ } while (v[0] != isc_arg_warning && v[0] != isc_arg_gds && v[0] != isc_arg_end);
+ }
+ }
+ fb_assert(stmt);
+
+ Meta im(stmt, false);
+ Message add(im);
+ Name login(add);
+ Varfield verifier(add), slt(add);
+ Name first(add), middle(add), last(add);
+
+ setField(login, user->userName());
+ setField(first, user->firstName());
+ setField(middle, user->middleName());
+ setField(last, user->lastName());
+
#if SRP_DEBUG > 1
- Firebird::BigInteger salt("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
+ Firebird::BigInteger salt("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
#else
- Firebird::BigInteger salt;
- salt.random(RemotePassword::SRP_SALT_SIZE);
+ Firebird::BigInteger salt;
+ salt.random(RemotePassword::SRP_SALT_SIZE);
#endif
- Firebird::UCharBuffer s;
- salt.getBytes(s);
- slt().set(s.getCount(), s.begin());
- slt.null() = 0;
+ Firebird::UCharBuffer s;
+ salt.getBytes(s);
+ slt.set(s.getCount(), s.begin());
- dumpIt("salt", s);
+ dumpIt("salt", s);
#if SRP_DEBUG > 0
- fprintf(stderr, ">%s< >%s<\n", user->userName()->get(), user->password()->get());
+ fprintf(stderr, ">%s< >%s<\n", user->userName()->get(), user->password()->get());
#endif
- Firebird::string s1;
- salt.getText(s1);
- server.computeVerifier(user->userName()->get(), s1, user->password()->get()).getBytes(s);
- dumpIt("verifier", s);
- verifier().set(s.getCount(), s.begin());
- verifier.null() = 0;
+ Firebird::string s1;
+ salt.getText(s1);
+ server.computeVerifier(user->userName()->get(), s1, user->password()->get()).getBytes(s);
+ dumpIt("verifier", s);
+ verifier.set(s.getCount(), s.begin());
- for (unsigned repeat = 0; ; ++repeat)
+ stmt->execute(status, tra, &add, NULL);
+ check(status);
+
+ stmt->free(status);
+ check(status);
+ }
+ catch (const Firebird::Exception&)
{
- att->execute(status, tra, 0, insert, 3, 0, &add, NULL);
- if (status->isSuccess() || repeat > 0)
+ if (stmt)
{
- break;
+ stmt->release();
}
-
- const ISC_STATUS* v = status->get();
- while (v[0] == isc_arg_gds)
- {
- if (v[1] == isc_dsql_relation_err)
- {
- prepareDataStructures();
- tra->commit(status);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
- tra = att->startTransaction(status, 0, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
- break;
- }
- do
- {
- v += 2;
- } while (v[0] != isc_arg_warning && v[0] != isc_arg_gds && v[0] != isc_arg_end);
- }
+ throw;
}
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
}
break;
case MOD_OPER:
{
- Message up;
-
Firebird::string update = "UPDATE plg$srp_view SET ";
- Firebird::AutoPtr<Verifier> verifier;
- Firebird::AutoPtr<Salt> slt;
+ Firebird::AutoPtr<Varfield> verifier, slt;
if (user->password()->entered())
{
- verifier = new Verifier(up);
- slt = new Salt(up);
update += "PLG$VERIFIER=?,PLG$SALT=?,";
}
Firebird::AutoPtr<Name> first, middle, last;
- allocField(first, up, user->firstName(), update, "PLG$FIRST");
- allocField(middle, up, user->middleName(), update, "PLG$MIDDLE");
- allocField(last, up, user->lastName(), update, "PLG$LAST");
+ allocField(user->firstName(), update, "PLG$FIRST");
+ allocField(user->middleName(), update, "PLG$MIDDLE");
+ allocField(user->lastName(), update, "PLG$LAST");
if (update[update.length() - 1] != ',')
{
return 0;
}
update.rtrim(",");
-
update += " WHERE PLG$USER_NAME=?";
- Login login(up);
- if (verifier.hasData())
+ Firebird::IStatement* stmt = NULL;
+ try
{
+ stmt = att->prepare(status, tra, 0, update.c_str(), 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
+ check(status);
+
+ Meta im(stmt, false);
+ Message up(im);
+
+ if (user->password()->entered())
+ {
+ verifier = new Varfield(up);
+ slt = new Varfield(up);
#if SRP_DEBUG > 1
- Firebird::BigInteger salt("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
+ Firebird::BigInteger salt("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
#else
- Firebird::BigInteger salt;
- salt.random(RemotePassword::SRP_SALT_SIZE);
+ Firebird::BigInteger salt;
+ salt.random(RemotePassword::SRP_SALT_SIZE);
#endif
- Firebird::UCharBuffer s;
- salt.getBytes(s);
- (*slt)().set(s.getCount(), s.begin());
- slt->null() = 0;
+ Firebird::UCharBuffer s;
+ salt.getBytes(s);
+ slt->set(s.getCount(), s.begin());
- dumpIt("salt", s);
+ dumpIt("salt", s);
#if SRP_DEBUG > 0
- fprintf(stderr, ">%s< >%s<\n", user->userName()->get(), user->password()->get());
+ fprintf(stderr, ">%s< >%s<\n", user->userName()->get(), user->password()->get());
#endif
- Firebird::string s1;
- salt.getText(s1);
- server.computeVerifier(user->userName()->get(), s1, user->password()->get()).getBytes(s);
- dumpIt("verifier", s);
- (*verifier)().set(s.getCount(), s.begin());
- verifier->null() = 0;
- }
+ Firebird::string s1;
+ salt.getText(s1);
+ server.computeVerifier(user->userName()->get(), s1, user->password()->get()).getBytes(s);
+ dumpIt("verifier", s);
+ verifier->set(s.getCount(), s.begin());
+ }
- assignField(first, user->firstName());
- assignField(middle, user->middleName());
- assignField(last, user->lastName());
- setField(login, user->userName());
+ allocField(first, up, user->firstName(), "PLG$FIRST");
+ allocField(middle, up, user->middleName(), "PLG$MIDDLE");
+ allocField(last, up, user->lastName(), "PLG$LAST");
- att->execute(status, tra, 0, update.c_str(), 3, 0, &up, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
+ Name login(up);
+
+ assignField(first, user->firstName());
+ assignField(middle, user->middleName());
+ assignField(last, user->lastName());
+ setField(login, user->userName());
+
+ stmt->execute(status, tra, &up, NULL);
+ check(status);
+
+ if (!checkCount(status, &upCount, isc_info_update_count))
+ {
+ return -1;
+ }
+
+ stmt->free(status);
+ check(status);
}
-
- if (!checkCount(status, &upCount, isc_info_update_count))
+ catch (const Firebird::Exception&)
{
- return -1;
+ if (stmt)
+ {
+ stmt->release();
+ }
+ throw;
}
}
break;
case DEL_OPER:
{
- Message dl;
const char* del = "DELETE FROM plg$srp_view WHERE PLG$USER_NAME=?";
- Login login(dl);
- setField(login, user->userName());
+ Firebird::IStatement* stmt = NULL;
+ try
+ {
+ stmt = att->prepare(status, tra, 0, del, 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
+ check(status);
- att->execute(status, tra, 0, del, 3, 0, &dl, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
+ Meta im(stmt, false);
+ Message dl(im);
+ Name login(dl);
+ setField(login, user->userName());
+
+ stmt->execute(status, tra, &dl, NULL);
+ check(status);
+
+ if (!checkCount(status, &delCount, isc_info_delete_count))
+ {
+ return -1;
+ }
+
+ stmt->free(status);
+ check(status);
}
-
- if (!checkCount(status, &delCount, isc_info_delete_count))
+ catch (const Firebird::Exception&)
{
- return -1;
+ if (stmt)
+ {
+ stmt->release();
+ }
+ throw;
}
}
break;
@@ -452,75 +483,62 @@
user->groupName()->setEntered(0);
user->password()->setEntered(0);
- Message di;
Firebird::string disp = "SELECT PLG$USER_NAME, PLG$FIRST, PLG$MIDDLE, PLG$LAST, "
" CASE WHEN RDB$RELATION_NAME IS NULL THEN 0 ELSE 1 END "
"FROM PLG$SRP_VIEW LEFT JOIN RDB$USER_PRIVILEGES "
" ON PLG$SRP_VIEW.PLG$USER_NAME = RDB$USER_PRIVILEGES.RDB$USER "
" AND RDB$RELATION_NAME = 'RDB$ADMIN' "
" AND RDB$PRIVILEGE = 'M' ";
- Firebird::AutoPtr<Message> par;
if (user->userName()->entered())
{
- par = new Message;
- Login login(*par);
- setField(login, user->userName());
disp += " WHERE PLG$USER_NAME = ?";
}
- Login login(di);
- Name first(di), middle(di), last(di);
- Field<SLONG> admin(di);
- di.ready();
-
- Firebird::RefPtr<Firebird::IStatement> stmt;
+ Firebird::IStatement* stmt = NULL;
+ Firebird::IResultSet* rs = NULL;
try
{
- stmt = att->allocateStatement(status);
- if (!status->isSuccess())
+ stmt = att->prepare(status, tra, 0, disp.c_str(), 3, Firebird::IStatement::PREPARE_PREFETCH_METADATA);
+ check(status);
+
+ Meta om(stmt, true);
+ Message di(om);
+ Name login(di);
+ Name first(di), middle(di), last(di);
+ Field<SLONG> admin(di);
+
+ Firebird::AutoPtr<Message> par;
+ if (user->userName()->entered())
{
- Firebird::status_exception::raise(status->get());
+ Meta im(stmt, false);
+ par = new Message(im);
+ Name login(*par);
+ setField(login, user->userName());
}
- stmt->prepare(status, tra, disp.length(), disp.c_str(), 3,
- Firebird::IStatement::PREPARE_PREFETCH_NONE);
- if (!status->isSuccess())
+
+ rs = stmt->openCursor(status, tra, par, om);
+ check(status);
+
+ while (rs->fetch(status, di.buffer))
{
- Firebird::status_exception::raise(status->get());
- }
- stmt->execute(status, tra, 0, par, NULL);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
- while (stmt->fetch(status, &di) == 0)
- {
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ check(status);
listField(user->userName(), login);
listField(user->firstName(), first);
listField(user->middleName(), middle);
listField(user->lastName(), last);
- user->admin()->set(admin());
+ user->admin()->set(admin);
callback->list(user);
}
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ check(status);
- stmt->free(status, DSQL_drop);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ stmt->free(status);
+ check(status);
}
catch (const Firebird::Exception&)
{
- if (stmt.hasData())
+ if (stmt)
{
stmt->release();
}
@@ -609,10 +627,7 @@
{
unsigned char buffer[100];
att->getInfo(status, 1, &item, sizeof(buffer), buffer);
- if (!status->isSuccess())
- {
- Firebird::status_exception::raise(status->get());
- }
+ check(status);
if (gds__vax_integer(buffer + 1, 2) != 6)
{
@@ -624,6 +639,14 @@
*count = newCount;
return newCount == oldCount + 1;
}
+
+ void check(Firebird::IStatus* status)
+ {
+ if (!status->isSuccess())
+ {
+ Firebird::status_exception::raise(status->get());
+ }
+ }
};
// register plugin
Modified: firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp
===================================================================
--- firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/src/auth/SecureRemotePassword/server/SrpServer.cpp 2013-02-17 12:08:53 UTC (rev 57663)
@@ -147,15 +147,8 @@
}
HANDSHAKE_DEBUG(fprintf(stderr, "Srv SRP1: started transaction\n"));
- stmt = att->allocateStatement(status);
- if (!status->isSuccess())
- {
- status_exception::raise(status->get());
- }
-
const char* sql = "SELECT PLG$VERIFIER, PLG$SALT FROM PLG$SRP WHERE PLG$USER_NAME = ?";
- stmt->prepare(status, tra, 0, sql, 3, 0);
-
+ stmt = att->prepare(status, tra, 0, sql, 3, IStatement::PREPARE_PREFETCH_METADATA);
if (!status->isSuccess())
{
const ISC_STATUS* v = status->get();
@@ -176,25 +169,29 @@
status_exception::raise(status->get());
}
- Message par;
- Field<VarChar<SZ_LOGIN> > login(par);
- login() = account.c_str();
- login.null() = 0;
+ Meta im(stmt, false);
+ Message par(im);
+ Field<Text> login(par);
+ login = account.c_str();
+
+ Meta om(stmt, true);
+ Message dat(om);
+ if (!status->isSuccess())
+ {
+ status_exception::raise(status->get());
+ }
+ Field<Varying> verify(dat);
+ Field<Varying> slt(dat);
HANDSHAKE_DEBUG(fprintf(stderr, "Srv SRP1: Ready to run statement with login '%s'\n", account.c_str()));
- Message dat;
- Field <VarChar<RemotePassword::SRP_VERIFIER_SIZE> > verify(dat);
- Field <VarChar<RemotePassword::SRP_SALT_SIZE> > slt(dat);
- dat.ready();
-
- stmt->execute(status, tra, 0, &par, &dat);
+ stmt->execute(status, tra, &par, &dat);
if (!status->isSuccess())
{
status_exception::raise(status->get());
}
HANDSHAKE_DEBUG(fprintf(stderr, "Srv SRP1: Executed statement\n"));
- stmt->free(status, DSQL_drop);
+ stmt->free(status);
if (!status->isSuccess())
{
status_exception::raise(status->get());
@@ -208,7 +205,7 @@
}
tra = NULL;
- att->detach(status); // It will close statement
+ att->detach(status);
if (!status->isSuccess())
{
status_exception::raise(status->get());
@@ -217,10 +214,10 @@
server = new RemotePassword;
- verifier.assign(reinterpret_cast<UCHAR*>(verify().data), RemotePassword::SRP_VERIFIER_SIZE);
+ verifier.assign(reinterpret_cast<const UCHAR*>((const char*)verify), RemotePassword::SRP_VERIFIER_SIZE);
dumpIt("Srv: verifier", verifier);
UCharBuffer s;
- s.assign(reinterpret_cast<UCHAR*>(slt().data), RemotePassword::SRP_SALT_SIZE);
+ s.assign(reinterpret_cast<const UCHAR*>((const char*)slt), RemotePassword::SRP_SALT_SIZE);
BigInteger(s).getText(salt);
dumpIt("Srv: salt", salt);
server->genServerKey(serverPubKey, verifier);
@@ -277,7 +274,7 @@
{
if (stmt)
{
- stmt->free(status, DSQL_drop);
+ stmt->free(status);
}
if (tra)
{
Added: firebird/trunk/src/common/MsgMetadata.cpp
===================================================================
--- firebird/trunk/src/common/MsgMetadata.cpp (rev 0)
+++ firebird/trunk/src/common/MsgMetadata.cpp 2013-02-17 12:08:53 UTC (rev 57663)
@@ -0,0 +1,153 @@
+/*
+ * 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 Adriano dos Santos Fernandes
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2011 Adriano dos Santos Fernandes <adrianosf at gmail.com>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ * Alex Peshkoff
+ *
+ */
+
+#include "firebird.h"
+#include "../common/MsgMetadata.h"
+#include "../common/utils_proto.h"
+
+using namespace Firebird;
+
+namespace {
+
+class CoerceMetadata : public RefCntIface<ICoerceMetadata, FB_COERCE_METADATA_VERSION>
+{
+public:
+ CoerceMetadata(const MsgMetadata* from)
+ : msgMetadata(new MsgMetadata)
+ {
+ msgMetadata->items = from->items;
+ }
+
+ virtual int FB_CARG release()
+ {
+ if (--refCounter != 0)
+ {
+ return 1;
+ }
+
+ delete this;
+ return 0;
+ }
+
+ // ICoerceMetadata implementation
+ virtual void FB_CARG setType(IStatus* status, unsigned index, unsigned type)
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ if (!indexError(status, index, "setType"))
+ msgMetadata->items[index].type = type;
+ }
+
+ virtual void FB_CARG setSubType(IStatus* status, unsigned index, unsigned subType)
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ if (!indexError(status, index, "setSubType"))
+ msgMetadata->items[index].subType = subType;
+ }
+
+ virtual void FB_CARG setLength(IStatus* status, unsigned index, unsigned length)
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ if (!indexError(status, index, "setLength"))
+ msgMetadata->items[index].length = length;
+ }
+
+ virtual void FB_CARG setScale(IStatus* status, unsigned index, unsigned scale)
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ if (!indexError(status, index, "setScale"))
+ msgMetadata->items[index].scale = scale;
+ }
+
+ virtual IMessageMetadata* FB_CARG getMetadata(IStatus* status)
+ {
+ MutexLockGuard g(mtx, FB_FUNCTION);
+
+ msgMetadata->makeOffsets();
+ IMessageMetadata* rc = msgMetadata;
+ rc->addRef();
+ msgMetadata = NULL;
+ return rc;
+ }
+
+private:
+ RefPtr<MsgMetadata> msgMetadata;
+ Mutex mtx;
+
+ bool indexError(IStatus* status, unsigned index, const char* functionName)
+ {
+ if (!msgMetadata)
+ {
+ status->set((Arg::Gds(isc_random) <<
+ (string("Coerce interface is already inactive: ICoerceMetadata::") + functionName)).value());
+ return true;
+ }
+
+ if (index < msgMetadata->items.getCount())
+ {
+ status->set((Arg::Gds(isc_invalid_index_val) <<
+ Arg::Num(index) << (string("ICoerceMetadata::") + functionName)).value());
+ return true;
+ }
+
+ return false;
+ }
+};
+
+} // namespace anonymous
+
+
+namespace Firebird {
+
+
+void MsgMetadata::makeOffsets()
+{
+ length = 0;
+
+ for (unsigned n = 0; n < items.getCount(); ++n)
+ {
+ Item* param = &items[n];
+ if (!param->finished)
+ {
+ length = 0;
+ return;
+ }
+ length = fb_utils::sqlTypeToDsc(length, param->type, param->length,
+ NULL /*dtype*/, NULL /*length*/, ¶m->offset, ¶m->nullInd);
+ }
+}
+
+
+ICoerceMetadata* MsgMetadata::coerce(IStatus* status) const
+{
+ ICoerceMetadata* rc = new CoerceMetadata(this);
+ rc->addRef();
+ return rc;
+}
+
+
+} // namespace Firebird
Property changes on: firebird/trunk/src/common/MsgMetadata.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
Added: firebird/trunk/src/common/MsgMetadata.h
===================================================================
--- firebird/trunk/src/common/MsgMetadata.h (rev 0)
+++ firebird/trunk/src/common/MsgMetadata.h 2013-02-17 12:08:53 UTC (rev 57663)
@@ -0,0 +1,247 @@
+/*
+ * 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 Adriano dos Santos Fernandes
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2011 Adriano dos Santos Fernandes <adrianosf at gmail.com>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ * Alex Peshkov
+ *
+ */
+
+#ifndef COMMON_MSG_METADATA_H
+#define COMMON_MSG_METADATA_H
+
+#include "firebird/Provider.h"
+#include "iberror.h"
+#include "../common/classes/fb_string.h"
+#include "../common/classes/objects_array.h"
+#include "../common/classes/ImplementHelper.h"
+
+namespace Firebird {
+
+
+class MsgMetadata : public RefCntIface<IMessageMetadata, FB_MESSAGE_METADATA_VERSION>
+{
+public:
+ struct Item
+ {
+ explicit Item(MemoryPool& pool)
+ : field(pool),
+ relation(pool),
+ owner(pool),
+ alias(pool),
+ type(0),
+ subType(0),
+ length(0),
+ scale(0),
+ charset(0),
+ offset(0),
+ nullInd(0),
+ nullable(false),
+ finished(false)
+ {
+ }
+
+ Item(MemoryPool& pool, const Item& v)
+ : field(pool, v.field),
+ relation(pool, v.relation),
+ owner(pool, v.owner),
+ alias(pool, v.alias),
+ type(v.type),
+ subType(v.subType),
+ length(v.length),
+ scale(v.scale),
+ charset(v.charset),
+ offset(v.offset),
+ nullInd(v.nullInd),
+ nullable(v.nullable),
+ finished(v.finished)
+ {
+ }
+
+ string field;
+ string relation;
+ string owner;
+ string alias;
+ unsigned type;
+ unsigned subType;
+ unsigned length;
+ unsigned scale;
+ unsigned charset;
+ unsigned offset;
+ unsigned nullInd;
+ bool nullable;
+ bool finished;
+ };
+
+public:
+ MsgMetadata()
+ : items(getPool()),
+ length(0)
+ {
+ }
+
+ virtual int FB_CARG release()
+ {
+ if (--refCounter != 0)
+ {
+ return 1;
+ }
+
+ delete this;
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getCount(IStatus* /*status*/) const
+ {
+ return (unsigned) items.getCount();
+ }
+
+ virtual const char* FB_CARG getField(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].field.c_str();
+
+ raiseIndexError(status, index, "getField");
+ return NULL;
+ }
+
+ virtual const char* FB_CARG getRelation(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].relation.c_str();
+
+ raiseIndexError(status, index, "getRelation");
+ return NULL;
+ }
+
+ virtual const char* FB_CARG getOwner(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].owner.c_str();
+
+ raiseIndexError(status, index, "getOwner");
+ return NULL;
+ }
+
+ virtual const char* FB_CARG getAlias(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].alias.c_str();
+
+ raiseIndexError(status, index, "getAlias");
+ return NULL;
+ }
+
+ virtual unsigned FB_CARG getType(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].type;
+
+ raiseIndexError(status, index, "getType");
+ return 0;
+ }
+
+ virtual FB_BOOLEAN FB_CARG isNullable(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].nullable;
+
+ raiseIndexError(status, index, "isNullable");
+ return false;
+ }
+
+ virtual unsigned FB_CARG getSubType(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].subType;
+
+ raiseIndexError(status, index, "getSubType");
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getLength(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].length;
+
+ raiseIndexError(status, index, "getLength");
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getScale(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].scale;
+
+ raiseIndexError(status, index, "getScale");
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getCharset(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].charset;
+
+ raiseIndexError(status, index, "getCharset");
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getOffset(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].offset;
+
+ raiseIndexError(status, index, "getOffset");
+ return 0;
+ }
+
+ virtual unsigned FB_CARG getNullOffset(IStatus* status, unsigned index) const
+ {
+ if (index < items.getCount())
+ return items[index].nullInd;
+
+ raiseIndexError(status, index, "getOffset");
+ return 0;
+ }
+
+ virtual ICoerceMetadata* FB_CARG coerce(IStatus* status) const;
+
+ virtual unsigned FB_CARG getMessageLength(IStatus* /*status*/) const
+ {
+ return length;
+ }
+
+public:
+ void makeOffsets();
+
+private:
+ void raiseIndexError(IStatus* status, unsigned index, const char* method) const
+ {
+ status->set((Arg::Gds(isc_invalid_index_val) <<
+ Arg::Num(index) << (string("IMessageMetadata::") + method)).value());
+ }
+
+public:
+ ObjectsArray<Item> items;
+ unsigned length;
+};
+
+
+} // namespace Firebird
+
+#endif // COMMON_MSG_METADATA_H
Property changes on: firebird/trunk/src/common/MsgMetadata.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-chdr
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: firebird/trunk/src/common/StatementMetadata.cpp
===================================================================
--- firebird/trunk/src/common/StatementMetadata.cpp 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/src/common/StatementMetadata.cpp 2013-02-17 12:08:53 UTC (rev 57663)
@@ -18,14 +18,18 @@
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
+ * Alex Peshkoff
*
*/
+
+#include "firebird.h"
#include "../common/StatementMetadata.h"
#include "memory_routines.h"
#include "../common/StatusHolder.h"
#include "../jrd/inf_pub.h"
#include "../yvalve/gds_proto.h"
+#include "../common/utils_proto.h"
namespace Firebird {
@@ -151,21 +155,23 @@
}
// Get statement input parameters.
-const IParametersMetadata* StatementMetadata::getInputParameters()
+IMessageMetadata* StatementMetadata::getInputMetadata()
{
- if (!inputParameters.fetched)
- fetchParameters(isc_info_sql_bind, &inputParameters);
+ if (!inputParameters->fetched)
+ fetchParameters(isc_info_sql_bind, inputParameters);
- return &inputParameters;
+ inputParameters->addRef();
+ return inputParameters;
}
// Get statement output parameters.
-const IParametersMetadata* StatementMetadata::getOutputParameters()
+IMessageMetadata* StatementMetadata::getOutputMetadata()
{
- if (!outputParameters.fetched)
- fetchParameters(isc_info_sql_select, &outputParameters);
+ if (!outputParameters->fetched)
+ fetchParameters(isc_info_sql_select, outputParameters);
- return &outputParameters;
+ outputParameters->addRef();
+ return outputParameters;
}
// Get number of records affected by the statement execution.
@@ -201,9 +207,9 @@
{
type.specified = false;
legacyPlan = detailedPlan = "";
- inputParameters.items.clear();
- outputParameters.items.clear();
- inputParameters.fetched = outputParameters.fetched = false;
+ inputParameters->items.clear();
+ outputParameters->items.clear();
+ inputParameters->fetched = outputParameters->fetched = false;
}
// Parse an info response buffer.
@@ -231,11 +237,11 @@
}
case isc_info_sql_select:
- parameters = &outputParameters;
+ parameters = outputParameters;
break;
case isc_info_sql_bind:
- parameters = &inputParameters;
+ parameters = inputParameters;
break;
case isc_info_sql_num_variables:
@@ -323,6 +329,26 @@
}
}
+ if (parameters->fetched)
+ {
+ unsigned off = 0;
+ for (unsigned n = 0; n < parameters->items.getCount(); ++n)
+ {
+ Parameters::Item* param = ¶meters->items[n];
+ if (!param->finished)
+ {
+ parameters->fetched = false;
+ break;
+ }
+ off = fb_utils::sqlTypeToDsc(off, param->type, param->length,
+ NULL /*dtype*/, NULL /*length*/, ¶m->offset, ¶m->nullInd);
+ }
+ if (parameters->fetched)
+ {
+ parameters->length = off;
+ }
+ }
+
break;
}
@@ -340,18 +366,18 @@
// or we'll need extra info calls (done by methods of this class) to parse only the info we
// can understand.
- for (ObjectsArray<Parameters::Item>::iterator i = inputParameters.items.begin();
- i != inputParameters.items.end() && inputParameters.fetched;
+ for (ObjectsArray<Parameters::Item>::iterator i = inputParameters->items.begin();
+ i != inputParameters->items.end() && inputParameters->fetched;
++i)
{
- inputParameters.fetched = i->finished;
+ inputParameters->fetched = i->finished;
}
- for (ObjectsArray<Parameters::Item>::iterator i = outputParameters.items.begin();
- i != outputParameters.items.end() && outputParameters.fetched;
+ for (ObjectsArray<Parameters::Item>::iterator i = outputParameters->items.begin();
+ i != outputParameters->items.end() && outputParameters->fetched;
++i)
{
- outputParameters.fetched = i->finished;
+ outputParameters->fetched = i->finished;
}
}
Modified: firebird/trunk/src/common/StatementMetadata.h
===================================================================
--- firebird/trunk/src/common/StatementMetadata.h 2013-02-16 02:34:05 UTC (rev 57662)
+++ firebird/trunk/src/common/StatementMetadata.h 2013-02-17 12:08:53 UTC (rev 57663)
@@ -18,6 +18,7 @@
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
+ * Alex Peshkov
*
*/
@@ -30,7 +31,7 @@
#include "../common/classes/array.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/objects_array.h"
-#include "../common/classes/ImplementHelper.h"
+#include "../common/MsgMetadata.h"
namespace Firebird {
@@ -39,153 +40,23 @@
class StatementMetadata : public PermanentStorage
{
public:
- class Parameters : public VersionedIface<IParametersMetadata, FB_PARAMETERS_METADATA_VERSION>,
- public PermanentStorage
+ class Parameters : public MsgMetadata
{
public:
- struct Item : public PermanentStorage
- {
- explicit Item(MemoryPool& pool)
- : PermanentStorage(pool),
- field(pool),
- relation(pool),
- owner(pool),
- alias(pool),
- type(0),
- subType(0),
- length(0),
- scale(0),
- nullable(false),
- finished(false)
- {
- }
+ Parameters()
+ : MsgMetadata(), fetched(false)
+ { }
- string field;
- string relation;
- string owner;
- string alias;
- unsigned type;
- unsigned subType;
- unsigned length;
- unsigned scale;
- bool nullable;
- bool finished;
- };
-
- public:
- explicit Parameters(MemoryPool& pool)
- : PermanentStorage(pool),
- items(pool),
- fetched(false)
- {
- }
-
- virtual unsigned FB_CARG getCount(IStatus* /*status*/) const
- {
- return (unsigned) items.getCount();
- }
-
- virtual const char* FB_CARG getField(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].field.c_str();
-
- raiseIndexError(status, index, "getField");
- return NULL;
- }
-
- virtual const char* FB_CARG getRelation(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].relation.c_str();
-
- raiseIndexError(status, index, "getRelation");
- return NULL;
- }
-
- virtual const char* FB_CARG getOwner(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].owner.c_str();
-
- raiseIndexError(status, index, "getOwner");
- return NULL;
- }
-
- virtual const char* FB_CARG getAlias(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].alias.c_str();
-
- raiseIndexError(status, index, "getAlias");
- return NULL;
- }
-
- virtual unsigned FB_CARG getType(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].type;
-
- raiseIndexError(status, index, "getType");
- return 0;
- }
-
- virtual bool FB_CARG isNullable(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].nullable;
-
- raiseIndexError(status, index, "isNullable");
- return false;
- }
-
- virtual unsigned FB_CARG getSubType(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].subType;
-
- raiseIndexError(status, index, "getSubType");
- return 0;
- }
-
- virtual unsigned FB_CARG getLength(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].length;
-
- raiseIndexError(status, index, "getLength");
- return 0;
- }
-
- virtual unsigned FB_CARG getScale(IStatus* status, unsigned index) const
- {
- if (index < items.getCount())
- return items[index].scale;
-
- raiseIndexError(status, index, "getScale");
- return 0;
- }
-
- private:
- void raiseIndexError(IStatus* status, unsigned index, const char* method) const
- {
- status->set((Arg::Gds(isc_invalid_index_val) <<
- Arg::Num(index) << (string("IParametersMetadata::") + method)).value());
- }
-
- public:
- ObjectsArray<Item> items;
bool fetched;
};
-public:
StatementMetadata(MemoryPool& pool, IStatement* aStatement)
: PermanentStorage(pool),
statement(aStatement),
legacyPlan(pool),
detailedPlan(pool),
- inputParameters(pool),
- outputParameters(pool)
+ inputParameters(new Parameters),
+ outputParameters(new Parameters)
{
}
@@ -194,8 +65,8 @@
unsigned getType();
const char* getPlan(bool detailed);
- const IParametersMetadata* getInputParameters();
- const IParametersMetadata* getOutputParameters();
+ IMessageMetadata* getInputMetadata();
+ IMessageMetadata* getOutputMetadata();
ISC_UINT64 getAffectedRecords();
void clear();
@@ -210,7 +81,7 @@
IStatement* statement;
Nullable<unsigned> type;
string legacyPlan, detailedPlan;
- Parameters inputParameters, outputParameters;
+ RefPtr<Parameters> inputParameters, outputParameters;
};
Copied: firebird/trunk/src/common/classes/BlrReader.h (from rev 57662, firebird/trunk/src/jrd/BlrReader.h)
===================================================================
--- firebird/trunk/src/common/classes/BlrReader.h (rev 0)
+++ firebird/trunk/src/common/classes/BlrReader.h 2013-02-17 12:08:53 UTC (rev 57663)
@@ -0,0 +1,159 @@
+/*
+ * 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 Adriano dos Santos Fernandes
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2009 Adriano dos Santos Fernandes <adr...@uo...>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#ifndef COMMON_CLASSES_BLR_READER_H
+#define COMMON_CLASSES_BLR_READER_H
+
+#include "iberror.h"
+
+namespace Firebird {
+
+
+class BlrReader
+{
+public:
+ BlrReader(const UCHAR* buffer, unsigned maxLen)
+ : start(buffer),
+ end(buffer + maxLen),
+ pos(buffer)
+ {
+ // ASF: A big maxLen like MAX_ULONG could overflow the pointer size and
+ // points to something before start. In this case, we set the end to the
+ // max possible address.
+ if (end < start)
+ end = (UCHAR*) ~U_IPTR(0);
+ }
+
+ BlrReader()
+ : start(NULL),
+ end(NULL),
+ pos(NULL)
+ {
+ }
+
+public:
+ const UCHAR* getPos() const
+ {
+ fb_assert(pos);
+ return pos;
+ }
+
+ void setPos(const UCHAR* newPos)
+ {
+ fb_assert(newPos >= start && newPos < end);
+ pos = newPos;
+ }
+
+ void seekBackward(unsigned n)
+ {
+ setPos(getPos() - n);
+ }
+
+ void seekForward(unsigned n)
+ {
+ setPos(getPos() + n);
+ }
+
+ unsigned getOffset() const
+ {
+ return getPos() - start;
+ }
+
+ UCHAR peekByte() const
+ {
+ fb_assert(pos);
+
+ if (pos >= end)
+ (Firebird::Arg::Gds(isc_invalid_blr) << Firebird::Arg::Num(getOffset())).raise();
+
+ return *pos;
+ }
+
+ UCHAR getByte()
+ {
+ UCHAR byte = peekByte();
+ ++pos;
+ return byte;
+ }
+
+ USHORT getWord()
+ {
+ const UCHAR low = getByte();
+ const UCHAR high = getByte();
+
+ return high * 256 + low;
+ }
+
+ ULONG getLong()
+ {
+ const UCHAR b1 = getByte();
+ const UCHAR b2 = getByte();
+ const UCHAR b3 = getByte();
+ const UCHAR b4 = getByte();
+
+ return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
+ }
+
+ UCHAR checkByte(UCHAR expected)
+ {
+ using namespace Firebird;
+
+ UCHAR byte = getByte();
+
+ if (byte != expected)
+ {
+ status_exception::raise(Arg::Gds(isc_syntaxerr) <<
+ Arg::Num(expected) <<
+ Arg::Num(getOffset() - 1) <<
+ Arg::Num(byte));
+ }
+
+ return byte;
+ }
+
+ USHORT checkWord(USHORT expected)
+ {
+ using namespace Firebird;
+
+ USHORT word = getWord();
+
+ if (word != expected)
+ {
+ status_exception::raise(Arg::Gds(isc_syntaxerr) <<
+ Arg::Num(expected) <<
+ Arg::Num(getOffset() - 2) <<
+ Arg::Num(word));
+ }
+
+ return word;
+ }
+
+private:
+ const UCHAR* start;
+ const UCHAR* end;
+ const UCHAR* pos;
+};
+
+
+} // namespace
+
+#endif // COMMON_CLASSES_BLR_READER_H
Property changes on: firebird/trunk/src/common/classes/BlrReader.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Copied: firebird/trunk/src/common/classes/BlrWriter.cpp (from rev 57597, firebird/trunk/src/dsql/BlrWriter.cpp)
===================================================================
--- firebird/trunk/src/common/classes/BlrWriter.cpp (rev 0)
+++ firebird/trunk/src/common/classes/BlrWriter.cpp 2013-02-17 12:08:53 UTC (rev 57663)
@@ -0,0 +1,120 @@
+/*
+ * The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
+ *
+ * Software distributed under the License is distributed on an
+ * "AS IS" basis, 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 Inprise Corporation
+ * and its predecessors. Portions created by Inprise Corporation are
+ * Copyright (C) Inprise Corporation.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ * Adriano dos Santos Fernandes - refactored from others modules.
+ */
+
+#include "firebird.h"
+#include "consts_pub.h"
+#include "dyn_consts.h"
+#include "gen/iberror.h"
+#include "../common/classes/BlrWriter.h"
+#include "../jrd/blr.h"
+
+
+namespace Firebird {
+
+
+// Write out a string valued attribute.
+void BlrWriter::appendString(UCHAR verb, const char* string, USHORT length)
+{
+ // TMN: Doesn't this look pretty awkward? If we are given
+ // a verb, the length is a ushort, else it's uchar.
+ if (verb)
+ {
+ appendUChar(verb);
+ appendUShort(length);
+ }
+ else
+ {
+ fb_assert(length <= MAX_UCHAR);
+ appendUChar(length);
+ }
+
+ if (string)
+ appendBytes(reinterpret_cast<const UCHAR*>(string), length);
+}
+
+// Input
+// blr_ptr: current position of blr being generated
+// verb: blr byte of which number is an argument
+// number: value to be written to blr
+// Function
+// Write out a numeric valued attribute.
+void BlrWriter::appendNumber(UCHAR verb, SSHORT number)
+{
+ if (verb)
+ appendUChar(verb);
+
+ appendUShortWithLength(number);
+}
+
+void BlrWriter::appendUShortWithLength(USHORT val)
+{
+ // append an USHORT value, prepended with the USHORT length of an USHORT
+ appendUShort(2);
+ appendUShort(val);
+}
+
+void BlrWriter::appendULongWithLength(ULONG val)
+{
+ // append an ULONG value, prepended with the USHORT length of an ULONG
+ appendUShort(4);
+ appendULong(val);
+}
+
+void BlrWriter::appendVersion()
+{
+ appendUChar(isVersion4() ? blr_version4 : blr_version5);
+}
+
+// Write out a string of blr as part of a ddl string, as in a view or computed field definition.
+void BlrWriter::beginBlr(UCHAR verb)
+{
+ if (verb)
+ appendUChar(verb);
+
+ baseOffset = blrData.getCount();
+
+ // put in a place marker for the size of the blr, since it is unknown
+ appendUShort(0);
+ appendVersion()...
[truncated message content] |