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] |