Files
secondo/Algebras/CRel/GAttrArray.cpp
2026-01-23 17:03:45 +08:00

701 lines
16 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#include "GAttrArray.h"
#include "AlgebraManager.h"
#include <algorithm>
#include <cstring>
#include "ListUtils.h"
#include "SecondoException.h"
#include "SmiUtils.h"
#include "TypeUtils.h"
using listutils::emptyErrorInfo;
using std::max;
using std::string;
extern AlgebraManager *am;
namespace CRelAlgebra {
GAttrArrayInfo::GAttrArrayInfo()
{
}
GAttrArrayInfo::GAttrArrayInfo(ListExpr attributeTypeExpr)
{
int attributeAlgebraId,
attributeTypeId;
ResolveTypeOrThrow(attributeTypeExpr, attributeAlgebraId, attributeTypeId);
TypeConstructor &typeConstructor = *am->GetTC(attributeAlgebraId,
attributeTypeId);
attributeSize = typeConstructor.SizeOf();
attributeCastFunction = am->Cast(attributeAlgebraId, attributeTypeId);
attributeFLOBCount = max(typeConstructor.NumOfFLOBs(), 0);
}
GAttrArray::GAttrArray(const PGAttrArrayInfo &info, SmiFileId flobFileId) :
m_header(0, flobFileId),
m_info(info),
m_capacity(0),
m_size(sizeof(GAttrArray)),
m_attributesEnd(nullptr)
{
}
GAttrArray::GAttrArray(const PGAttrArrayInfo &info, Reader &source) :
GAttrArray(info, source, source.ReadOrThrow<GAttrArrayHeader>())
{
}
GAttrArray::GAttrArray(const PGAttrArrayInfo &info, Reader &source,
const GAttrArrayHeader &header) :
m_header(header),
m_info(info),
m_capacity(m_header.count),
m_size(sizeof(GAttrArray) + (m_header.count * info->attributeSize)),
m_data(m_header.count * info->attributeSize)
{
const uint64_t count = m_header.count;
if (count > 0)
{
const uint64_t attributeSize = info->attributeSize;
char *attribute = m_data.GetPointer();
m_attributesEnd = attribute + (attributeSize * count);
source.ReadOrThrow(attribute, attributeSize * count);
ObjectCast cast = m_info->attributeCastFunction;
char *end = m_attributesEnd;
while (attribute < end)
{
cast((Attribute*)attribute);
attribute += attributeSize;
}
}
else
{
m_attributesEnd = nullptr;
}
}
GAttrArray::GAttrArray(const GAttrArray &array,
const SharedArray<const uint64_t> &filter) :
AttrArray(filter),
m_header(array.m_header),
m_info(array.m_info),
m_capacity(array.m_capacity),
m_size(array.m_size),
m_data(array.m_data),
m_attributesEnd(array.m_attributesEnd)
{
}
GAttrArray::~GAttrArray()
{
const uint64_t count = m_header.count;
if (count > 0)
{
const GAttrArrayInfo &info = *m_info;
const uint64_t flobCount = info.attributeFLOBCount,
attributeSize = info.attributeSize;
if (flobCount > 0)
{
char *currentAttribute = m_data.GetPointer(),
*attributesEnd = m_attributesEnd;
while (currentAttribute < attributesEnd)
{
Attribute *attribute = (Attribute*)currentAttribute;
for (uint64_t i = 0; i < flobCount; i++)
{
attribute->GetFLOB(i)->~Flob();
}
currentAttribute += attributeSize;
}
}
}
}
AttrArray *GAttrArray::Filter(const SharedArray<const uint64_t> filter) const
{
return new GAttrArray(*this, filter);
}
const PGAttrArrayInfo &GAttrArray::GetInfo() const
{
return m_info;
}
uint64_t GAttrArray::GetCount() const
{
return m_header.count;
}
uint64_t GAttrArray::GetSize() const
{
return m_size;
}
void GAttrArray::Save(Writer &target, bool includeHeader) const
{
if (includeHeader)
{
target.WriteOrThrow(m_header);
}
const uint64_t count = m_header.count;
if (count > 0)
{
target.WriteOrThrow(m_data.GetPointer(), count * m_info->attributeSize);
}
}
void GAttrArray::DeleteRecords()
{
/*
Delete all ~Flob~ records.
*/
const GAttrArrayInfo &info = *m_info;
const uint64_t flobCount = info.attributeFLOBCount;
if (m_header.flobFileId != 0 && flobCount > 0)
{
const uint64_t count = m_header.count;
if (count > 0)
{
const uint64_t attributeSize = info.attributeSize;
char *currentAttributeData = m_data.GetPointer(),
*attributeDataEnd = m_attributesEnd;
while (currentAttributeData < attributeDataEnd)
{
Attribute *attribute = (Attribute*)currentAttributeData;
for (uint64_t i = 0; i < flobCount; i++)
{
attribute->GetFLOB(i)->destroy();
}
currentAttributeData += attributeSize;
}
}
}
}
void GAttrArray::Append(const AttrArray &array, uint64_t row)
{
Append(((GAttrArray&)array).GetAt(row));
}
void GAttrArray::Append(Attribute &value)
{
const GAttrArrayInfo &info = *m_info;
const uint64_t attributeSize = info.attributeSize;
uint64_t capacity = m_capacity,
count = m_header.count;
char *attributeData,
*attributeDataEnd;
//resize?
if (capacity == count)
{
//first element?
if (capacity == 0)
{
capacity = 1;
attributeData = new char[attributeSize];
attributeDataEnd = m_attributesEnd = attributeData;
m_data = SharedArray<char>(attributeData, attributeSize);
}
else
{
const uint64_t oldByteCapacity = capacity * attributeSize,
byteCapacity = oldByteCapacity + oldByteCapacity;
capacity += capacity;
attributeData = new char[byteCapacity];
attributeDataEnd = m_attributesEnd = attributeData + oldByteCapacity;
//copy existing values
memcpy(attributeData, m_data.GetPointer(), oldByteCapacity);
m_data = SharedArray<char>(attributeData, byteCapacity);
}
m_capacity = capacity;
}
else
{
attributeData = m_data.GetPointer();
attributeDataEnd = m_attributesEnd;
}
Attribute *attribute = (Attribute*)attributeDataEnd;
//copy the new attribute's data
memcpy((void*)attribute, (void*) &value, attributeSize);
const uint64_t flobCount = info.attributeFLOBCount;
//copy Flobs?
if (flobCount > 0)
{
const SmiFileId flobFileId = m_header.flobFileId;
if (flobFileId != 0)
{
for (uint64_t j = 0; j < flobCount; j++)
{
Flob &sourceFlob = *value.GetFLOB(j),
*targetFlob = attribute->GetFLOB(j);
new (targetFlob) Flob(0);
sourceFlob.saveToFile(flobFileId, 0, *targetFlob);
}
}
else
{
for (uint64_t j = 0; j < flobCount; j++)
{
Flob &sourceFlob = *value.GetFLOB(j),
*targetFlob = attribute->GetFLOB(j);
new (targetFlob) Flob(sourceFlob);
}
}
}
//decrese the stored attribute's ref count to 1
while (attribute->NoRefs() > 1)
{
attribute->DeleteIfAllowed();
}
++m_header.count;
m_size += attributeSize;
m_attributesEnd += attributeSize;
}
void GAttrArray::Remove()
{
/*
Remove last ~Attribute~ and delete it's copied ~Flob~s
*/
const GAttrArrayInfo &info = *m_info;
const uint64_t flobCount = info.attributeFLOBCount,
count = m_header.count;
if (count > 0 && flobCount > 0 && m_header.flobFileId != 0)
{
const uint64_t attributeSize = info.attributeSize;
Attribute *attribute = (Attribute*)(m_attributesEnd -= attributeSize);
for (uint64_t i = 0; i < flobCount; i++)
{
attribute->GetFLOB(i)->destroy();
}
--m_header.count;
m_size -= attributeSize;
}
}
void GAttrArray::Clear()
{
if (m_header.count > 0)
{
DeleteRecords();
m_header.count = 0;
m_attributesEnd = m_data.GetPointer();
m_size = sizeof(GAttrArray);
}
}
Attribute &GAttrArray::GetAt(uint64_t row) const
{
return *(Attribute*)(m_data.GetPointer() + (row * m_info->attributeSize));
}
Attribute &GAttrArray::operator[](uint64_t row) const
{
return *(Attribute*)(m_data.GetPointer() + (row * m_info->attributeSize));
}
bool GAttrArray::IsDefined(uint64_t row) const
{
return GetAt(row).IsDefined();
}
int GAttrArray::Compare(uint64_t rowA, const AttrArray &arrayB,
uint64_t rowB) const
{
return GetAt(rowA).Compare(&((GAttrArray&)arrayB).GetAt(rowB));
}
int GAttrArray::Compare(uint64_t row, Attribute &value) const
{
return GetAt(row).Compare(&value);
}
int GAttrArray::CompareAlmost(uint64_t rowA, const AttrArray &arrayB,
uint64_t rowB) const
{
return GetAt(rowA).CompareAlmost(&((GAttrArray&)arrayB).GetAt(rowB));
}
int GAttrArray::CompareAlmost(uint64_t row, Attribute &value) const
{
return GetAt(row).CompareAlmost(&value);
}
bool GAttrArray::Equals(uint64_t rowA, const AttrArray &arrayB,
uint64_t rowB) const
{
return GetAt(rowA).Equal(&((GAttrArray&)arrayB).GetAt(rowB));
}
bool GAttrArray::Equals(uint64_t row, Attribute &value) const
{
return GetAt(row).Equal(&value);
}
uint64_t GAttrArray::GetHash(uint64_t row) const
{
return GetAt(row).HashValue();
}
Attribute *GAttrArray::GetAttribute(uint64_t row, bool clone) const
{
return clone ? GetAt(row).Clone() : GetAt(row).Copy();
}
GAttrArrayIterator GAttrArray::GetIterator() const
{
return GAttrArrayIterator(*this);
}
GAttrArrayIterator GAttrArray::begin() const
{
return GetIterator();
}
GAttrArrayIterator GAttrArray::end() const
{
return GAttrArrayIterator();
}
//GAttrArrayHeader-------------------------------------------
GAttrArrayHeader::GAttrArrayHeader()
{
}
GAttrArrayHeader::GAttrArrayHeader(uint64_t count, SmiFileId flobFileId) :
count(count),
flobFileId(flobFileId)
{
}
GAttrArrayHeader::GAttrArrayHeader(const AttrArrayHeader &header) :
count(header.count),
flobFileId(header.flobFileId)
{
}
//GSpatialAttrArray<dim>--------------------------------------------------------
template<int dim>
GSpatialAttrArray<dim>::GSpatialAttrArray(const PGAttrArrayInfo &info) :
m_array(info)
{
}
template<int dim>
GSpatialAttrArray<dim>::GSpatialAttrArray(const PGAttrArrayInfo &info,
SmiFileId flobFileId) :
m_array(info, flobFileId)
{
}
template<int dim>
GSpatialAttrArray<dim>::GSpatialAttrArray(const PGAttrArrayInfo &info,
Reader &source) :
m_array(info, source)
{
}
template<int dim>
GSpatialAttrArray<dim>::GSpatialAttrArray(const PGAttrArrayInfo &info,
Reader &source,
const GAttrArrayHeader &header) :
m_array(info, source, header)
{
}
template<int dim>
GSpatialAttrArray<dim>::GSpatialAttrArray(const GSpatialAttrArray &array,
const SharedArray<const uint64_t> &filter) :
m_array(array.m_array, filter)
{
}
template<int dim>
AttrArray *GSpatialAttrArray<dim>::Filter(
const SharedArray<const uint64_t> filter) const
{
return new GSpatialAttrArray<dim>(*this, filter);
}
template<int dim>
uint64_t GSpatialAttrArray<dim>::GetCount() const
{
return m_array.GetCount();
}
template<int dim>
uint64_t GSpatialAttrArray<dim>::GetSize() const
{
return m_array.GetSize();
}
template<int dim>
void GSpatialAttrArray<dim>::Save(Writer &target, bool includeHeader) const
{
m_array.Save(target, includeHeader);
}
template<int dim>
void GSpatialAttrArray<dim>::DeleteRecords()
{
m_array.DeleteRecords();
}
template<int dim>
void GSpatialAttrArray<dim>::Append(const AttrArray &array, uint64_t row)
{
m_array.Append(((GSpatialAttrArray<dim>&)array).m_array, row);
}
template<int dim>
void GSpatialAttrArray<dim>::Append(Attribute &value)
{
m_array.Append(value);
}
template<int dim>
void GSpatialAttrArray<dim>::Remove()
{
m_array.Remove();
}
template<int dim>
void GSpatialAttrArray<dim>::Clear()
{
m_array.Clear();
}
template<int dim>
StandardSpatialAttribute<dim> &GSpatialAttrArray<dim>::GetAt(
uint64_t index) const
{
return (StandardSpatialAttribute<dim>&)m_array.GetAt(index);
}
template<int dim>
StandardSpatialAttribute<dim> &GSpatialAttrArray<dim>::operator[](
uint64_t index) const
{
return (StandardSpatialAttribute<dim>&)m_array.GetAt(index);
}
template<int dim>
bool GSpatialAttrArray<dim>::IsDefined(uint64_t row) const
{
return m_array.IsDefined(row);
}
template<int dim>
int GSpatialAttrArray<dim>::Compare(uint64_t rowA, const AttrArray &arrayB,
uint64_t rowB) const
{
return m_array.Compare(rowA, ((GSpatialAttrArray<dim>&)arrayB).m_array, rowB);
}
template<int dim>
int GSpatialAttrArray<dim>::Compare(uint64_t row, Attribute &value) const
{
return m_array.Compare(row, value);
}
template<int dim>
int GSpatialAttrArray<dim>::CompareAlmost(uint64_t rowA,
const AttrArray &arrayB,
uint64_t rowB) const
{
return m_array.CompareAlmost(rowA,
((GSpatialAttrArray<dim>&)arrayB).m_array, rowB);
}
template<int dim>
int GSpatialAttrArray<dim>::CompareAlmost(uint64_t row, Attribute &value) const
{
return m_array.CompareAlmost(row, value);
}
template<int dim>
bool GSpatialAttrArray<dim>::Equals(uint64_t rowA, const AttrArray &arrayB,
uint64_t rowB) const
{
return m_array.Equals(rowA, ((GSpatialAttrArray<dim>&)arrayB).m_array, rowB);
}
template<int dim>
bool GSpatialAttrArray<dim>::Equals(uint64_t row, Attribute &value) const
{
return m_array.Equals(row, value);
}
template<int dim>
bool GSpatialAttrArray<dim>::EqualsAlmost(uint64_t rowA,
const AttrArray &arrayB,
uint64_t rowB) const
{
return m_array.EqualsAlmost(rowA,
((GSpatialAttrArray<dim>&)arrayB).m_array, rowB);
}
template<int dim>
bool GSpatialAttrArray<dim>::EqualsAlmost(uint64_t row, Attribute &value) const
{
return m_array.EqualsAlmost(row, value);
}
template<int dim>
uint64_t GSpatialAttrArray<dim>::GetHash(uint64_t row) const
{
return m_array.GetHash(row);
}
template<int dim>
Attribute *GSpatialAttrArray<dim>::GetAttribute(uint64_t row, bool clone) const
{
return m_array.GetAttribute(row, clone);
}
template<int dim>
Rectangle<dim> GSpatialAttrArray<dim>::GetBoundingBox(uint64_t row,
const Geoid* geoid) const
{
return GetAt(row).BoundingBox(geoid);
}
template<int dim>
double GSpatialAttrArray<dim>::GetDistance(uint64_t row,
const Rectangle<dim>& rect,
const Geoid* geoid) const
{
return GetAt(row).Distance(rect, geoid);
}
template<int dim>
bool GSpatialAttrArray<dim>::Intersects(uint64_t row,
const Rectangle<dim>& rect,
const Geoid* geoid) const
{
return GetAt(row).Intersects(rect, geoid);
}
template<int dim>
bool GSpatialAttrArray<dim>::IsEmpty(uint64_t row) const
{
return GetAt(row).IsEmpty();
}
template<int dim>
GSpatialAttrArrayIterator<dim> GSpatialAttrArray<dim>::GetIterator() const
{
return GSpatialAttrArrayIterator<dim>(*this);
}
template<int dim>
GSpatialAttrArrayIterator<dim> GSpatialAttrArray<dim>::begin() const
{
return GSpatialAttrArrayIterator<dim>(*this);
}
template<int dim>
GSpatialAttrArrayIterator<dim> GSpatialAttrArray<dim>::end() const
{
return GSpatialAttrArrayIterator<dim>();
}
template class GSpatialAttrArray<1>;
template class GSpatialAttrArray<2>;
template class GSpatialAttrArray<3>;
template class GSpatialAttrArray<4>;
template class GSpatialAttrArray<8>;
} // end of namepsace