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

585 lines
15 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
----
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
//paragraph [10] Footnote: [{\footnote{] [}}]
//[TOC] [\tableofcontents]
[1] Implementation of Module Ordered Relation Algebra
Winter 2009 Nicolai Voget
[TOC]
1 Overview
The Ordered Relational Algebra implements the type constructor ~orel~.
For more information see the OrderedRelation.h header file.
2 Defines, includes, and constants
*/
#include "CompositeKey.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "Algebras/Standard-C++/LongInt.h"
using namespace std;
CompositeKey::CompositeKey(const Tuple* t, const vector<int>& keyElements,
const vector<SmiKey::KeyDataType>& keyElemTypes,
const bool append, const TupleId appendix):
IndexableAttribute(false),data(0) {
if((!append) xor (false)) {
return;
}
if(keyElements.size() != keyElemTypes.size())
return;
vector<void*> attributes(keyElements.size());
for(SmiSize i=0; i<keyElements.size(); i++) {
attributes[i] = t->GetAttribute(keyElements[i]);
}
init(attributes, keyElemTypes, (append?appendNumber:none), appendix);
}
CompositeKey::CompositeKey(const vector<void*>& attributes,
const vector<SmiKey::KeyDataType>& attrTypes,
const bool upper):
IndexableAttribute(false),data(0) {
if(attributes.size() != attrTypes.size())
return;
init(attributes, attrTypes, (upper?upperRange:none));
}
CompositeKey::CompositeKey(SmiKey& key):
IndexableAttribute(false),data(0) {
kdt = key.GetType();
if(kdt == SmiKey::Unknown)
return;
int32_t iVal;
int64_t lVal;
double dVal;
string sVal;
switch(kdt) {
case SmiKey::Integer:
key.GetKey(iVal);
charsize = sizeof(iVal);
data = malloc(charsize);
memcpy(data, &iVal, charsize);
break;
case SmiKey::Longint:
key.GetKey(lVal);
charsize = sizeof(lVal);
data = malloc(charsize);
memcpy(data, &lVal, charsize);
break;
case SmiKey::Float:
key.GetKey(dVal);
charsize = sizeof(dVal);
data = malloc(charsize);
memcpy(data, &dVal, charsize);
break;
case SmiKey::String:
key.GetKey(sVal);
charsize = sVal.length();
data = malloc(charsize);
sVal.copy((char*)data, charsize);
break;
case SmiKey::Composite:
charsize = key.GetLength();
key.GetKey(this);
return;
default: assert(false);
}
SetDefined(true);
}
CompositeKey::CompositeKey(SmiRecord& record):
IndexableAttribute(true),data(0) {
SmiSize offset = 0;
init(record, offset);
}
CompositeKey::CompositeKey(SmiRecord& record, SmiSize& offset):
IndexableAttribute(true),data(0) {
init(record, offset);
}
CompositeKey::CompositeKey(PrefetchingIterator* iter):
IndexableAttribute(true),data(0) {
SmiSize offset = 0;
init(iter, offset);
}
CompositeKey::CompositeKey(PrefetchingIterator* iter, SmiSize& offset):
IndexableAttribute(true),data(0) {
init(iter, offset);
}
CompositeKey::CompositeKey() :
IndexableAttribute(false),data(0){
}
CompositeKey::CompositeKey(const CompositeKey& src): IndexableAttribute(src),
kdt(src.kdt),charsize(src.charsize),data(0){
if(src.data){
data = malloc(charsize);
memcpy(data,src.data,charsize);
}
}
CompositeKey& CompositeKey::operator=(const CompositeKey& src){
IndexableAttribute::operator=(src);
kdt = src.kdt;
charsize = src.charsize;
if(src.data){
if(data){
data = realloc(data,charsize);
} else {
data = malloc(charsize);
}
memcpy(data,src.data,charsize);
} else {
if(data){
free(data);
data = 0;
}
}
return *this;
}
void CompositeKey::WriteTo(char* dest) const {
if(IsDefined())
memcpy(dest, data, charsize);
}
void CompositeKey::ReadFrom(const char* src) {
if(charsize > SMI_MAX_KEYLEN)
charsize = SMI_MAX_KEYLEN;
if(!data){
data = malloc(charsize);
} else {
data = realloc(data, charsize);
}
memcpy(data,src,charsize);
SetDefined(true);
}
SmiSize CompositeKey::SizeOfChars() const {
if(IsDefined())
return charsize;
return 0;
}
size_t CompositeKey::Sizeof() const {
return sizeof(this);
}
int CompositeKey::Compare(const Attribute* attr) const {
const CompositeKey* other = static_cast<const CompositeKey*>(attr);
if(!IsDefined() && !other->IsDefined()) return 0;
if(!IsDefined()) return -1;
if(!other->IsDefined()) return 1;
if(other->charsize == charsize) {
return memcmp(data,other->data,charsize);
}
else if(other->charsize < charsize) {
if(memcmp(data,other->data,other->charsize)>=0) {
return 1;
} else {
return -1;
}
} else {
if(memcmp(data,other->data,charsize)<=0) {
return -1;
} else {
return 1;
}
}
}
inline bool CompositeKey::Adjacent(const Attribute* attr) const {
return false;
}
inline CompositeKey* CompositeKey::Clone() const {
CompositeKey* result = new CompositeKey();
result->CopyFrom(this);
return result;
}
inline size_t CompositeKey::HashValue() const {
return charsize;
}
void CompositeKey::CopyFrom(const Attribute* attr) {
cout << "Composite::CopyFrom" << endl;
const CompositeKey* other = (CompositeKey*)attr;
if(data){
free(data);
data = 0;
}
SetDefined(other->IsDefined());
if(IsDefined()) {
kdt = other->kdt;
charsize = other->charsize;
data = malloc(charsize);
memcpy(data,other->data,charsize);
} else {
data = 0;
}
}
SmiKey::KeyDataType CompositeKey::GetType() const {
if(!IsDefined())
return SmiKey::Unknown;
return kdt;
}
bool CompositeKey::WriteToRecord(SmiRecord& record, SmiSize& offset) const {
if(!IsDefined())
return false;
if(record.Write(&kdt, sizeof(kdt), offset) != sizeof(kdt))
return false;
offset += sizeof(kdt);
if((kdt == SmiKey::Composite) || (kdt == SmiKey::String)) {
if(record.Write(&charsize, sizeof(charsize), offset) != sizeof(charsize))
return false;
offset += sizeof(charsize);
}
if(record.Write(data, charsize, offset) != charsize)
return false;
offset += charsize;
return true;
}
SmiKey CompositeKey::GetSmiKey() const {
if(!IsDefined())
return SmiKey();
int32_t iVal;
int64_t lVal;
double dVal;
string sVal;
switch(kdt) {
case SmiKey::Integer:
if(charsize != sizeof(iVal))
break;
memcpy(&iVal, data, charsize);
return SmiKey(iVal);
case SmiKey::Longint:
if(charsize != sizeof(lVal))
break;
memcpy(&lVal, data, charsize);
return SmiKey(lVal);
case SmiKey::Float:
if(charsize != sizeof(dVal))
break;
memcpy(&dVal, data, charsize);
return SmiKey(dVal);
case SmiKey::String:
sVal.assign((char*)data, charsize);
return SmiKey(sVal);
case SmiKey::Composite:
return SmiKey(this);
default: assert(false);
}
return SmiKey();
}
TupleId CompositeKey::GetAppendix() const {
TupleId lVal;
SmiKey::Unmap((void*)((char*)(data)+charsize-sizeof(lVal)), lVal);
return lVal;
}
CompositeKey::~CompositeKey() {
if(data){
free(data);
data = 0;
}
}
ListExpr CompositeKey::Out(const ListExpr typeInfo, Word value) {
return nl->TheEmptyList();
};
Word CompositeKey::In(const ListExpr typeInfo, const ListExpr value,
const int errorPos, ListExpr& errorInfo, bool& correct) {
// cout << "Composite::IN" << endl;
correct = false;
return SetWord((void*)0);
}
Word CompositeKey::Create(const ListExpr typeInfo) {
// cout << "Composite::Create" << endl;
return SetWord(new CompositeKey());
}
void CompositeKey::Delete(const ListExpr typeInfo, Word& value) {
// cout << "Composite::Delete" << endl;
delete (CompositeKey*)(value.addr);
value.addr = 0;
}
bool CompositeKey::Open(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
// cout << "Composite::Open" << endl;
CompositeKey* comp = new CompositeKey();
bool defined = comp->IsDefined();
valueRecord.Read(&(defined), sizeof(defined), offset);
offset += sizeof(defined);
if(defined) {
valueRecord.Read(&(comp->kdt), sizeof(comp->kdt), offset);
offset += sizeof(comp->kdt);
valueRecord.Read(&(comp->charsize), sizeof(comp->charsize), offset);
offset += sizeof(comp->charsize);
comp->data = malloc(comp->charsize);
valueRecord.Read(comp->data, comp->charsize, offset);
offset += comp->charsize;
}
value = SetWord(comp);
return (comp!=0);
}
bool CompositeKey::Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value) {
// cout << "Composite::Save" << endl;
CompositeKey* comp = (CompositeKey*)value.addr;
bool defined = comp->IsDefined();
valueRecord.Write(&defined, sizeof(defined), offset);
offset += sizeof(defined);
if(defined) {
valueRecord.Write(&(comp->kdt), sizeof(comp->kdt), offset);
offset += sizeof(comp->kdt);
valueRecord.Write(&(comp->charsize), sizeof(comp->charsize), offset);
offset += sizeof(comp->charsize);
comp->data = malloc(comp->charsize);
valueRecord.Write(comp->data, comp->charsize, offset);
offset += comp->charsize;
}
return true;
}
void CompositeKey::Close(const ListExpr typeInfo, Word& value) {
// cout << "Composite::Close" << endl;
delete (CompositeKey*)(value.addr);
value.addr = 0;
}
Word CompositeKey::Clone(const ListExpr typeInfo, const Word& value) {
// cout << "Composite::Clone" << endl;
return SetWord(((CompositeKey*)(value.addr))->Clone());
}
void* CompositeKey::Cast(void* addr) {
// cout << "Composite::Cast" << endl;
return new (addr) CompositeKey;
}
int CompositeKey::SizeOf() {
// cout << "Composite::SizeOf" << endl;
return sizeof(CompositeKey);
}
bool CompositeKey::CheckKind(const ListExpr typeInfo, ListExpr& errorInfo) {
return (nl->IsAtom(typeInfo) &&
nl->AtomType(typeInfo)==SymbolType &&
nl->SymbolValue(typeInfo) == "compkey");
}
const bool CompositeKey::operator==(const CompositeKey& other) const {
return (Compare(&other) == 0);
}
void CompositeKey::init(const vector<void*>& attributes,
const vector<SmiKey::KeyDataType>& attrTypes,
const Mode mode, const TupleId appendix) {
SmiSize maxSize = SMI_MAX_KEYLEN-1;
if(data==0){
data = malloc(maxSize);
} else {
data = realloc(data,maxSize);
}
if(mode == appendNumber) {
maxSize -= sizeof(TupleId);
}
charsize = 0;
int32_t iVal;
int64_t lVal;
double dVal;
string sVal;
IndexableAttribute* attr;
SmiSize tmpSize = 0;
void* tmpData = 0;
for(SmiSize i=0; (i < attributes.size()) && (charsize < maxSize); i++) {
switch (attrTypes[i]) {
case SmiKey::Integer:
iVal = (int32_t)(static_cast<CcInt*>(attributes[i])->GetValue());
tmpSize = sizeof(iVal);
tmpData = malloc(tmpSize);
SmiKey::Map(iVal, tmpData);
break;
case SmiKey::Longint:
lVal = (int64_t)(static_cast<LongInt*>(attributes[i])->GetValue());
tmpSize = sizeof(lVal);
tmpData = malloc(tmpSize);
SmiKey::Map(lVal, tmpData);
break;
case SmiKey::Float:
dVal = (double)(static_cast<CcReal*>(attributes[i])->GetValue());
tmpSize = sizeof(dVal);
tmpData = malloc(tmpSize);
SmiKey::Map(dVal, tmpData);
break;
case SmiKey::String:
sVal = (string)(static_cast<CcString*>(attributes[i])->GetValue());
tmpSize = sVal.length() + 1;
tmpData = malloc(tmpSize);
sVal.copy((char*)tmpData, tmpSize-1);
((char*)tmpData)[tmpSize-1] = 0;
break;
default:
attr = static_cast<IndexableAttribute*>(attributes[i]);
tmpSize = attr->SizeOfChars();
tmpData = malloc(tmpSize);
attr->WriteTo((char*)tmpData);
}
if(charsize+tmpSize>maxSize){
tmpSize = maxSize-charsize;
}
memcpy((void*)(((char*)data)+charsize), tmpData, tmpSize);
free(tmpData);
tmpData = 0;
charsize += tmpSize;
}
if(mode == appendNumber) {
SmiKey::Map((TupleId)appendix, (void*)(((char*)data)+charsize));
charsize += sizeof(TupleId);
maxSize += sizeof(TupleId);
} else if(mode == upperRange) {
while(charsize<maxSize) {
((char*)data)[charsize++] = (char)255;
}
}
if(charsize != maxSize)
data = realloc(data, charsize);
kdt = SmiKey::Composite;
SetDefined(true);
}
void CompositeKey::init(SmiRecord& record, SmiSize& offset) {
SetDefined(false);
if(record.Read(&kdt, sizeof(kdt), offset)!=sizeof(kdt))
return;
offset += sizeof(kdt);
switch(kdt) {
case SmiKey::Integer:
charsize = sizeof(int32_t);
break;
case SmiKey::Longint:
charsize = sizeof(int64_t);
break;
case SmiKey::Float:
charsize = sizeof(double);
break;
case SmiKey::String:
case SmiKey::Composite:
if(record.Read(&charsize, sizeof(charsize), offset) != sizeof(charsize))
return;
offset += sizeof(charsize);
break;
default:
return;
}
if(!data){
data = malloc(charsize);
} else {
data = realloc(data,charsize);
}
if(record.Read(data, charsize, offset) != charsize) {
free(data);
data = 0;
return;
}
offset += charsize;
SetDefined( true);
}
void CompositeKey::init(PrefetchingIterator* iter, SmiSize& offset) {
SetDefined(false);
if(iter->ReadCurrentData(&kdt, sizeof(kdt), offset) != sizeof(kdt))
return;
offset += sizeof(kdt);
switch(kdt) {
case SmiKey::Integer:
charsize = sizeof(int32_t);
break;
case SmiKey::Longint:
charsize = sizeof(int64_t);
break;
case SmiKey::Float:
charsize = sizeof(double);
break;
case SmiKey::String:
case SmiKey::Composite:
if(iter->ReadCurrentData(&charsize, sizeof(charsize), offset)
!= sizeof(charsize))
return;
offset += sizeof(charsize);
break;
default:
return;
}
if(!data){
data = malloc(charsize);
} else {
data = realloc(data,charsize);
}
if(iter->ReadCurrentData(data, charsize, offset) != charsize) {
free(data);
data = 0;
return;
}
offset += charsize;
SetDefined(true);
}