2009-10-21 02:42:38 +02:00
|
|
|
/*
|
|
|
|
* 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) 2008 Adriano dos Santos Fernandes <adrianosf@uol.com.br>
|
|
|
|
* and all contributors signed below.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
#include "../jrd/ValuesImpl.h"
|
|
|
|
#include "../jrd/ErrorImpl.h"
|
|
|
|
#include "../jrd/mov_proto.h"
|
|
|
|
#include "../jrd/align.h"
|
2010-01-03 11:46:42 +01:00
|
|
|
#include "../common/classes/MsgPrint.h"
|
|
|
|
#include "../jrd/msg_encode.h"
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
using namespace Firebird;
|
|
|
|
using Firebird::uint;
|
|
|
|
|
|
|
|
namespace Jrd {
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
ValuesImpl::IndividualQueue::IndividualQueue(MemoryPool& p, Error* /*error*/, ValuesImpl* aValues)
|
2009-10-22 01:48:07 +02:00
|
|
|
: PermanentStorage(p),
|
2009-10-21 02:42:38 +02:00
|
|
|
values(aValues),
|
|
|
|
valueCount(values->getCount()),
|
|
|
|
recordSize(0),
|
2009-10-22 01:48:07 +02:00
|
|
|
records(p),
|
2009-10-21 02:42:38 +02:00
|
|
|
enqueuePos(0),
|
|
|
|
recordNumber(0)
|
|
|
|
{
|
|
|
|
for (uint i = 1; i <= valueCount; ++i)
|
|
|
|
{
|
|
|
|
ValueImpl* value = values->getValue(i);
|
|
|
|
const dsc& desc = value->getDesc();
|
|
|
|
|
|
|
|
USHORT align = type_alignments[desc.dsc_dtype];
|
|
|
|
if (align)
|
|
|
|
recordSize = FB_ALIGN(recordSize, align);
|
|
|
|
|
|
|
|
recordSize += desc.dsc_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
nullsStart = recordSize;
|
|
|
|
recordSize += valueCount / 8 + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ValuesImpl::IndividualQueue::~IndividualQueue()
|
|
|
|
{
|
|
|
|
for (Array<UCHAR*>::iterator end = records.end(), i = records.begin(); i != end; ++i)
|
|
|
|
delete [] *i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
void FB_CALL ValuesImpl::IndividualQueue::enqueue(Error* /*error*/)
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
|
|
|
size_t recordCount = records.getCount();
|
2009-11-05 09:29:33 +01:00
|
|
|
UCHAR* const buffer = (enqueuePos < recordCount ?
|
2009-10-22 01:48:07 +02:00
|
|
|
records[enqueuePos] : FB_NEW(getPool()) UCHAR[recordSize]);
|
2009-10-21 02:42:38 +02:00
|
|
|
UCHAR* nullsBuffer = buffer + nullsStart;
|
|
|
|
uint pos = 0;
|
|
|
|
|
|
|
|
for (uint i = 1; i <= valueCount; ++i)
|
|
|
|
{
|
|
|
|
ValueImpl* value = values->getValue(i);
|
|
|
|
const dsc& desc = value->getDesc();
|
|
|
|
|
|
|
|
USHORT align = type_alignments[desc.dsc_dtype];
|
|
|
|
if (align)
|
|
|
|
pos = FB_ALIGN(pos, align);
|
|
|
|
|
|
|
|
if (value->isNull())
|
|
|
|
nullsBuffer[(i - 1) >> 3] |= 1 << ((i - 1) & 7);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nullsBuffer[(i - 1) >> 3] &= ~(1 << ((i - 1) & 7));
|
|
|
|
memcpy(buffer + pos, desc.dsc_address, desc.dsc_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += desc.dsc_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enqueuePos++ >= recordCount)
|
|
|
|
records.push(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
bool FB_CALL ValuesImpl::IndividualQueue::dequeue(Error* /*error*/)
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
|
|
|
if (recordNumber == enqueuePos)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const UCHAR* buffer = records[recordNumber++];
|
|
|
|
const UCHAR* nullsBuffer = buffer + nullsStart;
|
|
|
|
uint pos = 0;
|
|
|
|
|
|
|
|
for (uint i = 1; i <= valueCount; ++i)
|
|
|
|
{
|
|
|
|
ValueImpl* value = values->getValue(i);
|
|
|
|
dsc& desc = value->getDesc();
|
|
|
|
|
|
|
|
USHORT align = type_alignments[desc.dsc_dtype];
|
|
|
|
if (align)
|
|
|
|
pos = FB_ALIGN(pos, align);
|
|
|
|
|
|
|
|
if (nullsBuffer[(i - 1) >> 3] & (1 << ((i - 1) & 7)))
|
|
|
|
desc.dsc_flags |= DSC_null;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(desc.dsc_address, buffer + pos, desc.dsc_length);
|
|
|
|
desc.dsc_flags &= ~DSC_null;
|
|
|
|
}
|
|
|
|
|
|
|
|
pos += desc.dsc_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (recordNumber == enqueuePos)
|
|
|
|
{
|
|
|
|
recordNumber = 0;
|
|
|
|
enqueuePos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
ValuesImpl::MsgQueue::MsgQueue(MemoryPool& p, Error* /*error*/, UCHAR* aMsg, unsigned aMsgLength)
|
2009-10-22 01:48:07 +02:00
|
|
|
: PermanentStorage(p),
|
2009-10-21 02:42:38 +02:00
|
|
|
msg(aMsg),
|
|
|
|
msgLength(aMsgLength),
|
2009-10-22 01:48:07 +02:00
|
|
|
records(p),
|
2009-10-21 02:42:38 +02:00
|
|
|
enqueuePos(0),
|
|
|
|
recordNumber(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ValuesImpl::MsgQueue::~MsgQueue()
|
|
|
|
{
|
|
|
|
for (Array<UCHAR*>::iterator end = records.end(), i = records.begin(); i != end; ++i)
|
|
|
|
delete [] *i;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
void FB_CALL ValuesImpl::MsgQueue::enqueue(Error* /*error*/)
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
|
|
|
thread_db* tdbb = JRD_get_thread_data();
|
|
|
|
size_t recordCount = records.getCount();
|
|
|
|
UCHAR* buffer = (enqueuePos < recordCount ?
|
2009-10-22 01:48:07 +02:00
|
|
|
records[enqueuePos] : FB_NEW(getPool()) UCHAR[msgLength]);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
memcpy(buffer, msg, msgLength);
|
|
|
|
|
|
|
|
if (enqueuePos++ >= recordCount)
|
|
|
|
records.push(buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-05 09:29:33 +01:00
|
|
|
bool FB_CALL ValuesImpl::MsgQueue::dequeue(Error* /*error*/)
|
2009-10-21 02:42:38 +02:00
|
|
|
{
|
|
|
|
if (recordNumber == enqueuePos)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const UCHAR* buffer = records[recordNumber++];
|
|
|
|
memcpy(msg, buffer, msgLength);
|
|
|
|
|
|
|
|
if (recordNumber == enqueuePos)
|
|
|
|
{
|
|
|
|
recordNumber = 0;
|
|
|
|
enqueuePos = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------
|
|
|
|
|
|
|
|
|
|
|
|
Firebird::uint FB_CALL ValuesImpl::getIndexByName(Error* error, const char* name) const
|
|
|
|
{
|
2009-10-30 11:59:52 +01:00
|
|
|
const string nameStr(name);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
for (unsigned i = 0; i < count; ++i)
|
|
|
|
{
|
2009-10-22 01:48:07 +02:00
|
|
|
const char* valName = (*values)[i].getName(error);
|
2009-10-21 02:42:38 +02:00
|
|
|
|
|
|
|
if (valName)
|
|
|
|
{
|
|
|
|
if (nameStr == valName)
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Value* FB_CALL ValuesImpl::getValueByName(Error* error, const char* name) const
|
|
|
|
{
|
|
|
|
int index = getIndexByName(error, name);
|
|
|
|
|
|
|
|
if (index > 0)
|
|
|
|
return getValue(error, index);
|
2009-10-30 11:59:52 +01:00
|
|
|
|
|
|
|
return NULL;
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ValuesQueue* FB_CALL ValuesImpl::createQueue(Error* error)
|
|
|
|
{
|
|
|
|
if (msg)
|
2009-10-22 01:48:07 +02:00
|
|
|
return new MsgQueue(getPool(), error, msg, msgLength);
|
2009-10-30 11:59:52 +01:00
|
|
|
|
|
|
|
return new IndividualQueue(getPool(), error, this);
|
2009-10-21 02:42:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-03 11:46:42 +01:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
// Done here to not pull error numbers into ValuesImpl.h
|
|
|
|
const USHORT JRD_FACILITY = GET_FACILITY(isc_invalid_index_val);
|
|
|
|
const USHORT number = GET_CODE(isc_invalid_index_val);
|
|
|
|
TEXT errmsg[MAX_ERRMSG_LEN + 1];
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* ValuesImpl::getInvalidIdxMsg(int idx)
|
|
|
|
{
|
|
|
|
fb_msg_format(0, JRD_FACILITY, number, sizeof(errmsg), errmsg, MsgFormat::SafeArg() << idx);
|
|
|
|
return errmsg;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-21 02:42:38 +02:00
|
|
|
} // namespace Jrd
|