8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-01 05:23:03 +01:00
firebird-mirror/src/common/classes/InternalMessageBuffer.cpp
alexpeshkoff fc12495d0e 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.
2013-02-17 12:08:53 +00:00

239 lines
5.2 KiB
C++

/*
* PROGRAM: FB interfaces.
* MODULE: InternalMessageBuffer.cpp
* DESCRIPTION: Old=>new message style converter.
*
* 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): ______________________________________.
*
* Alex Peshkov
*
*
*/
#include "firebird.h"
#include "../common/classes/InternalMessageBuffer.h"
#include "../common/MsgMetadata.h"
#include "../common/utils_proto.h"
#include "../intl/charsets.h"
#include "../common/classes/BlrReader.h"
using namespace Firebird;
namespace
{
class MetadataFromBlr : public MsgMetadata
{
public:
MetadataFromBlr(unsigned blrLength, const unsigned char* blr, unsigned aBufferLength);
};
MetadataFromBlr::MetadataFromBlr(unsigned aBlrLength, const unsigned char* aBlr, unsigned aLength)
{
if (aBlrLength == 0)
return;
BlrReader rdr(aBlr, aBlrLength);
UCHAR byte = rdr.getByte();
if (byte != blr_version4 && byte != blr_version5)
{
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)
#ifdef DEV_BUILD
<< Arg::Gds(isc_random) << "Wrong BLR version"
#endif
).raise();
}
if (rdr.getByte() != blr_begin || rdr.getByte() != blr_message)
{
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)
#ifdef DEV_BUILD
<< Arg::Gds(isc_random) << "Missing blr_begin / blr_message"
#endif
).raise();
}
rdr.getByte(); // skip the message number
unsigned count = rdr.getWord();
fb_assert(!(count & 1));
count /= 2;
unsigned offset = 0;
items.grow(count);
for (unsigned index = 0; index < count; index++)
{
Item* item = &items[index];
item->scale = 0;
item->subType = 0;
switch (rdr.getByte())
{
case blr_text:
item->type = SQL_TEXT;
item->charset = CS_dynamic;
item->length = rdr.getWord();
break;
case blr_varying:
item->type = SQL_VARYING;
item->charset = CS_dynamic;
item->length = rdr.getWord();
break;
case blr_text2:
item->type = SQL_TEXT;
item->charset = rdr.getWord();
item->length = rdr.getWord();
break;
case blr_varying2:
item->type = SQL_VARYING;
item->charset = rdr.getWord();
item->length = rdr.getWord();
break;
case blr_short:
item->type = SQL_SHORT;
item->length = sizeof(SSHORT);
item->scale = rdr.getByte();
break;
case blr_long:
item->type = SQL_LONG;
item->length = sizeof(SLONG);
item->scale = rdr.getByte();
break;
case blr_int64:
item->type = SQL_INT64;
item->length = sizeof(SINT64);
item->scale = rdr.getByte();
break;
case blr_quad:
item->type = SQL_QUAD;
item->length = sizeof(SLONG) * 2;
item->scale = rdr.getByte();
break;
case blr_float:
item->type = SQL_FLOAT;
item->length = sizeof(float);
break;
case blr_double:
case blr_d_float:
item->type = SQL_DOUBLE;
item->length = sizeof(double);
break;
case blr_timestamp:
item->type = SQL_TIMESTAMP;
item->length = sizeof(SLONG) * 2;
break;
case blr_sql_date:
item->type = SQL_TYPE_DATE;
item->length = sizeof(SLONG);
break;
case blr_sql_time:
item->type = SQL_TYPE_TIME;
item->length = sizeof(SLONG);
break;
case blr_blob2:
{
item->type = SQL_BLOB;
item->length = sizeof(ISC_QUAD);
item->subType = rdr.getWord();
item->charset = rdr.getWord();
}
break;
case blr_bool:
item->type = SQL_BOOLEAN;
item->length = sizeof(UCHAR);
break;
default:
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)
#ifdef DEV_BUILD
<< Arg::Gds(isc_random) << "Wrong BLR type"
#endif
).raise();
}
if (rdr.getByte() != blr_short || rdr.getByte() != 0)
{
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)
#ifdef DEV_BUILD
<< Arg::Gds(isc_random) << "Wrong BLR type for NULL indicator"
#endif
).raise();
}
item->finished = true;
}
makeOffsets();
if (rdr.getByte() != (UCHAR) blr_end || length != aLength)
{
(Arg::Gds(isc_sqlerr) << Arg::Num(-804) <<
Arg::Gds(isc_dsql_sqlda_err)
#ifdef DEV_BUILD
<< Arg::Gds(isc_random) << (length != aLength ? "Invalid message length" : "Missing blr_end")
#endif
).raise();
}
}
}
namespace Firebird
{
InternalMessageBuffer::InternalMessageBuffer(unsigned aBlrLength, const unsigned char* aBlr,
unsigned aBufferLength, unsigned char* aBuffer)
{
buffer = aBuffer;
metadata = new MetadataFromBlr(aBlrLength, aBlr, aBufferLength);
metadata->addRef();
}
InternalMessageBuffer::InternalMessageBuffer(IMessageMetadata* aMetadata, unsigned char* aBuffer)
{
buffer = aBuffer;
metadata = aMetadata;
metadata->addRef();
}
InternalMessageBuffer::~InternalMessageBuffer()
{
metadata->release();
}
}