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

1884 lines
51 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
----
//[_] [\_]
//characters [1] verbatim: [$] [$]
//characters [2] formula: [$] [$]
//characters [3] capital: [\textsc{] [}]
//characters [4] teletype: [\texttt{] [}]
1 Implementation file "XTreeAlgebra.cpp"[4]
January-May 2008, Mirko Dibbert
*/
#include "Algebra.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
#include "XTree.h"
extern NestedList *nl;
extern QueryProcessor *qp;
extern AlgebraManager *am;
using namespace std;
using namespace gta;
namespace xtreeAlgebra
{
/********************************************************************
1.1 Type constructor ~xtree~
********************************************************************/
static ListExpr XTreeProp()
{
ListExpr examplelist = nl->TextAtom();
nl->AppendText(examplelist, "<relation> creatextree [<attrname>]"
" where <attrname> is the key");
return (nl->TwoElemList(
nl->TwoElemList(nl->StringAtom("Creation"),
nl->StringAtom("Example Creation")),
nl->TwoElemList(examplelist,
nl->StringAtom("(let myxtree = pictures "
"creatextree[pic] "))));
}
ListExpr OutXTree(ListExpr type_Info, Word w)
{
#ifdef __XTREE_OUTFUN_PRINT_STATISTICS
static_cast<XTree*>(w.addr)->printTreeInfos();
#endif
return nl->TheEmptyList();
}
Word InXTree(
ListExpr type_Info, ListExpr value,
int errorPos, ListExpr &error_Info, bool &correct)
{
correct = false;
return SetWord(Address(0));
}
Word CreateXTree(const ListExpr type_Info)
{ return SetWord(new XTree()); }
void DeleteXTree(const ListExpr type_Info, Word &w)
{
static_cast<XTree*>(w.addr)->deleteFile();
delete static_cast<XTree*>(w.addr);
w.addr = 0;
}
bool OpenXTree(
SmiRecord &valueRecord, size_t &offset,
const ListExpr type_Info, Word &w)
{
SmiFileId fileid;
valueRecord.Read(&fileid, sizeof(SmiFileId), offset);
offset += sizeof(SmiFileId);
XTree *xtree = new XTree(fileid);
w = SetWord(xtree);
return true;
}
bool SaveXTree(
SmiRecord &valueRecord, size_t &offset,
const ListExpr type_Info, Word &w)
{
SmiFileId fileId;
XTree *xtree = static_cast<XTree*>(w.addr);
fileId = xtree->fileId();
if (fileId)
{
valueRecord.Write(&fileId, sizeof(SmiFileId), offset);
offset += sizeof(SmiFileId);
return true;
}
else
{
return false;
}
}
void CloseXTree(const ListExpr type_Info, Word &w)
{
XTree *xtree = (XTree*)w.addr;
delete xtree;
}
Word CloneXTree(const ListExpr type_Info, const Word &w)
{ return SetWord(Address(0)); }
int SizeOfXTree()
{ return sizeof(XTree); }
bool CheckXTree(ListExpr typeName, ListExpr &error_Info)
{ return nl->IsEqual(typeName, XTree::BasicType()); }
TypeConstructor xtreeTC(
XTree::BasicType(), XTreeProp,
OutXTree, InXTree,
0, 0,
CreateXTree, DeleteXTree,
OpenXTree, SaveXTree,
CloseXTree, CloneXTree,
0,
SizeOfXTree,
CheckXTree);
/********************************************************************
1.1 Operators
1.1.1 Value mappings
1.1.1.1 creatextreeHPointRel[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a relation and the name of a hpoint attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeHPointRel_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
Relation *relation =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
Tuple *tuple;
GenericRelationIterator *iter = relation->MakeScan();
unsigned dim=0;
while ((tuple = iter->GetNextTuple()))
{
HPointAttr *attr = static_cast<HPointAttr*>(
tuple->GetAttribute(attrIndex));
if(attr->IsDefined())
{
if (xtree->isInitialized())
{
if(attr->dim() != dim)
{
const string seperator =
"\n" + string(70, '-') + "\n";
cmsg.error()
<< seperator
<< "Operator creatextree: " << endl
<< "Got hpoint attributes of variing "
<< "dimensions!"
<< seperator << endl;
cmsg.send();
tuple->DeleteIfAllowed();
delete iter;
return CANCEL;
}
}
else
{ // initialize xtree
dim = attr->dim();
xtree->initialize(
dim, configName, "hpoint", 0,
HPointReg::defaultName("hpoint"));
}
// insert attribute into xtree
xtreeAlgebra::LeafEntry *e =
new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(), attr->hpoint());
xtree->insert(e);
}
tuple->DeleteIfAllowed();
}
delete iter;
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 creatextreeHRectRel[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a relation and the name of a hrect attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeHRectRel_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
Relation *relation =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
Tuple *tuple;
GenericRelationIterator *iter = relation->MakeScan();
unsigned dim=0;
while ((tuple = iter->GetNextTuple()))
{
HRectAttr *attr = static_cast<HRectAttr*>(
tuple->GetAttribute(attrIndex));
if(attr->IsDefined())
{
if (xtree->isInitialized())
{
if(attr->dim() != dim)
{
const string seperator =
"\n" + string(70, '-') + "\n";
cmsg.error()
<< seperator
<< "Operator creatextree: " << endl
<< "Got hrect attributes of variing "
<< "dimensions!"
<< seperator << endl;
cmsg.send();
tuple->DeleteIfAllowed();
delete iter;
return CANCEL;
}
}
else
{ // initialize xtree
dim = attr->dim();
xtree->initialize(
dim, configName, "hrect", 0,
BBoxReg::defaultName("hrect"));
}
// insert attribute into xtree
xtreeAlgebra::LeafEntry *e =
new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(), attr->hrect());
xtree->insert(e);
}
tuple->DeleteIfAllowed();
}
delete iter;
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 creatextreeRel[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a relation and the name of a non hpoint and non hrect attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeRel_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
Relation *relation =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
string typeName =
static_cast<CcString*>(args[paramCnt+2].addr)->GetValue();
int getdataType =
static_cast<CcInt*>(args[paramCnt+3].addr)->GetIntval();
string getdataName =
static_cast<CcString*>(args[paramCnt+4].addr)->GetValue();
HPointInfo hpoint_info;
BBoxInfo bbox_info;
// init hpoint_info or bbox_info
if (getdataType == 0)
hpoint_info = HPointReg::getInfo(typeName, getdataName);
else
bbox_info = BBoxReg::getInfo(typeName, getdataName);
Tuple *tuple;
GenericRelationIterator *iter = relation->MakeScan();
while ((tuple = iter->GetNextTuple()))
{
Attribute *attr = tuple->GetAttribute(attrIndex);
if(attr->IsDefined())
{
xtreeAlgebra::LeafEntry *e;
if (getdataType == 0)
{
e = new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(),
hpoint_info.getHPoint(attr));
}
else
{
e = new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(),
bbox_info.getBBox(attr));
}
if (!xtree->isInitialized())
{ // initialize xtree
xtree->initialize(
e->bbox()->dim(), configName, typeName,
getdataType, getdataName);
}
xtree->insert(e);
}
tuple->DeleteIfAllowed();
}
delete iter;
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 creatextreeHPointStream[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a tuple stream and the name of a hpoint attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeHPointStream_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
void *stream =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
Word wTuple;
qp->Open(stream);
qp->Request(stream, wTuple);
unsigned dim=0;
while (qp->Received(stream))
{
Tuple *tuple = static_cast<Tuple*>(wTuple.addr);
HPointAttr *attr = static_cast<HPointAttr*>(
tuple->GetAttribute(attrIndex));
if(attr->IsDefined())
{
if (xtree->isInitialized())
{
if(attr->dim() != dim)
{
const string seperator =
"\n" + string(70, '-') + "\n";
cmsg.error()
<< seperator
<< "Operator creatextree: " << endl
<< "Got hpoint attributes of variing "
<< "dimensions!"
<< seperator << endl;
cmsg.send();
tuple->DeleteIfAllowed();
qp->Close(stream);
return CANCEL;
}
}
else
{ // initialize xtree
dim = attr->dim();
xtree->initialize(
dim, configName, "hpoint", 0,
HPointReg::defaultName("hpoint"));
}
// insert attribute into xtree
xtreeAlgebra::LeafEntry *e =
new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(), attr->hpoint());
xtree->insert(e);
}
tuple->DeleteIfAllowed();
qp->Request(stream, wTuple);
}
qp->Close(stream);
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 creatextreeHRectStream[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a tuple stream and the name of a hrect attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeHRectStream_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
void *stream =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
Word wTuple;
qp->Open(stream);
qp->Request(stream, wTuple);
unsigned dim=0;
while (qp->Received(stream))
{
Tuple *tuple = static_cast<Tuple*>(wTuple.addr);
HRectAttr *attr = static_cast<HRectAttr*>(
tuple->GetAttribute(attrIndex));
if(attr->IsDefined())
{
if (xtree->isInitialized())
{
if(attr->dim() != dim)
{
const string seperator =
"\n" + string(70, '-') + "\n";
cmsg.error()
<< seperator
<< "Operator creatextree: " << endl
<< "Got hrect attributes of variing "
<< "dimensions!"
<< seperator << endl;
cmsg.send();
tuple->DeleteIfAllowed();
qp->Close(stream);
return CANCEL;
}
}
else
{ // initialize xtree
dim = attr->dim();
xtree->initialize(
dim, configName, "hrect", 0,
BBoxReg::defaultName("hrect"));
}
// insert attribute into xtree
xtreeAlgebra::LeafEntry *e =
new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(), attr->hrect());
xtree->insert(e);
}
tuple->DeleteIfAllowed();
qp->Request(stream, wTuple);
}
qp->Close(stream);
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 creatextreeStream[_]VM
This value mapping function is used for all "creatextree"[4] operators, which expects a tuple stream and the name of a non hpoint and non hrect attribute as parameter. It is designed as template function, which expects the count of arguments as template paremeter.
********************************************************************/
template<unsigned paramCnt>
int creatextreeStream_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
result = qp->ResultStorage(s);
XTree *xtree = static_cast<XTree*>(result.addr);
void *stream =
static_cast<Relation*>(args[0].addr);
int attrIndex =
static_cast<CcInt*>(args[paramCnt].addr)->GetIntval();
string configName =
static_cast<CcString*>(args[paramCnt+1].addr)->GetValue();
string typeName =
static_cast<CcString*>(args[paramCnt+2].addr)->GetValue();
int getdataType =
static_cast<CcInt*>(args[paramCnt+3].addr)->GetIntval();
string getdataName =
static_cast<CcString*>(args[paramCnt+4].addr)->GetValue();
HPointInfo hpoint_info;
BBoxInfo bbox_info;
// init hpoint_info or bbox_info
if (getdataType == 0)
hpoint_info = HPointReg::getInfo(typeName, getdataName);
else
bbox_info = BBoxReg::getInfo(typeName, getdataName);
Word wTuple;
qp->Open(stream);
qp->Request(stream, wTuple);
while (qp->Received(stream))
{
Tuple *tuple = static_cast<Tuple*>(wTuple.addr);
Attribute *attr = tuple->GetAttribute(attrIndex);
if(attr->IsDefined())
{
xtreeAlgebra::LeafEntry *e;
if (getdataType == 0)
{
e = new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(),
hpoint_info.getHPoint(attr));
}
else
{
e = new xtreeAlgebra::LeafEntry(
tuple->GetTupleId(),
bbox_info.getBBox(attr));
}
if (!xtree->isInitialized())
{ // initialize xtree
xtree->initialize(
e->bbox()->dim(), configName, typeName,
getdataType, getdataName);
}
xtree->insert(e);
}
tuple->DeleteIfAllowed();
qp->Request(stream, wTuple);
}
qp->Close(stream);
#ifdef __XTREE_PRINT_INSERT_INFO
cout << endl;
#endif
return 0;
}
/********************************************************************
1.1.1.1 Search[_]LI
Local Info object for the search value mappings.
********************************************************************/
struct Search_LI
{
Relation *relation;
list<TupleId> *results;
list<TupleId>::iterator iter;
bool defined;
Search_LI(Relation *rel)
: relation(rel),
results(new list<TupleId>),
defined(false)
{}
void initResultIterator()
{
iter = results->begin();
defined = true;
}
~Search_LI()
{
delete results;
}
TupleId next()
{
if (iter != results->end())
{
TupleId tid = *iter;
*iter++;
return tid;
}
else
{
return 0;
}
}
};
/********************************************************************
1.1.1.1 rangesearchHPoint[_]VM
********************************************************************/
int rangesearchHPoint_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
Search_LI *li;
switch (message)
{
case OPEN :
{
XTree *xtree = static_cast<XTree*>(args[0].addr);
li = new Search_LI(static_cast<Relation*>(args[1].addr));
local = SetWord(li);
HPointAttr *attr =
static_cast<HPointAttr*>(args[2].addr);
double searchRad =
static_cast<CcReal*>(args[3].addr)->GetValue();
if (attr->dim() != xtree->dim())
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator rangesearch:" << endl
<< "The given hpoint has the dimension "
<< attr->dim() << ", but the xtree contains "
<< xtree->dim() << "-dimensional data!"
<< seperator << endl;
cmsg.send();
return CANCEL;
}
// compute square of searchRad, since the current
// implementation of the xtree uses the square of the eucledean
// metric as distance function
searchRad *= searchRad;
xtree->rangeSearch(attr->hpoint(), searchRad, li->results);
li->initResultIterator();
assert(li->relation != 0);
return 0;
}
case REQUEST :
{
li = (Search_LI*)local.addr;
if(!li->defined)
return CANCEL;
TupleId tid = li->next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = (Search_LI*)local.addr;
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 rangesearch[_]VM
********************************************************************/
int rangesearch_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
Search_LI *li;
switch (message)
{
case OPEN :
{
XTree *xtree = static_cast<XTree*>(args[0].addr);
li = new Search_LI(static_cast<Relation*>(args[1].addr));
local = SetWord(li);
Attribute *attr = static_cast<Attribute*>(args[2].addr);
double searchRad =
static_cast<CcReal*>(args[3].addr)->GetValue();
string typeName =
static_cast<CcString*>(args[4].addr)->GetValue();
// compute square of searchRad, since the current
// implementation of the xtree uses the square of the eucledean
// metric as distance function
searchRad *= searchRad;
if (xtree->typeName() != typeName)
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator rangesearch:" << endl
<< "Got an \"" << typeName << "\" attribute, but the "
<< "xtree contains \"" << xtree->typeName()
<< "\" attriubtes!" << seperator << endl;
cmsg.send();
return CANCEL;
}
HPoint *p;
if (xtree->getdataType() == 0)
{ // use gethpoint function
HPointInfo info = HPointReg::getInfo(
typeName, xtree->getdataName());
p = info.getHPoint(attr);
}
else
{ // use getbbox function
BBoxInfo info = BBoxReg::getInfo(
typeName, xtree->getdataName());
HRect *r = info.getBBox(attr);
p = new HPoint(r->center());
delete r;
}
xtree->rangeSearch(p, searchRad, li->results);
li->initResultIterator();
assert(li->relation != 0);
return 0;
}
case REQUEST :
{
li = (Search_LI*)local.addr;
if(!li->defined)
return CANCEL;
TupleId tid = li->next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = (Search_LI*)local.addr;
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 nnsearchHPoint[_]VM
********************************************************************/
int nnsearchHPoint_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
Search_LI *li;
switch (message)
{
case OPEN :
{
XTree *xtree = static_cast<XTree*>(args[0].addr);
li = new Search_LI(static_cast<Relation*>(args[1].addr));
local = SetWord(li);
HPointAttr *attr = static_cast<HPointAttr*>(args[2].addr);
int nnCount = static_cast<CcInt*>(args[3].addr)->GetValue();
if (attr->dim() != xtree->dim())
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator nnsearch:" << endl
<< "The given hpoint has the dimension "
<< attr->dim() << ", but the xtree contains "
<< xtree->dim() << "-dimensional data!"
<< seperator << endl;
cmsg.send();
return CANCEL;
}
xtree->nnSearch(attr->hpoint(), nnCount , li->results);
li->initResultIterator();
assert(li->relation != 0);
return 0;
}
case REQUEST :
{
li = (Search_LI*)local.addr;
if(!li->defined)
return CANCEL;
TupleId tid = li->next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = (Search_LI*)local.addr;
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 nnsearch[_]VM
********************************************************************/
int nnsearch_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
Search_LI *li;
switch (message)
{
case OPEN :
{
XTree *xtree = static_cast<XTree*>(args[0].addr);
li = new Search_LI(static_cast<Relation*>(args[1].addr));
local = SetWord(li);
Attribute *attr = static_cast<Attribute*>(args[2].addr);
int nnCount = static_cast<CcInt*>(args[3].addr)->GetValue();
string typeName =
static_cast<CcString*>(args[4].addr)->GetValue();
if (xtree->typeName() != typeName)
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator nnsearch:" << endl
<< "Got an \"" << typeName << "\" attribute, but the "
<< "xtree contains \"" << xtree->typeName()
<< "\" attriubtes!" << seperator << endl;
cmsg.send();
return CANCEL;
}
HPoint *p;
if (xtree->getdataType() == 0)
{ // use gethpoint function
HPointInfo info = HPointReg::getInfo(
typeName, xtree->getdataName());
p = info.getHPoint(attr);
}
else
{ // use getbbox function
BBoxInfo info = BBoxReg::getInfo(
typeName, xtree->getdataName());
HRect *r = info.getBBox(attr);
p = new HPoint(r->center());
delete r;
}
xtree->nnSearch(p, nnCount , li->results);
li->initResultIterator();
assert(li->relation != 0);
return 0;
}
case REQUEST :
{
li = (Search_LI*)local.addr;
if(!li->defined)
return CANCEL;
TupleId tid = li->next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = (Search_LI*)local.addr;
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 nnscan[_]LI
Local Info object for the nnscan value mapping.
********************************************************************/
struct nnscan_LI
{
XTree *xtree;
Relation *relation;
};
/********************************************************************
1.1.1.1 nnscanHPoint[_]VM
********************************************************************/
int nnscanHPoint_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
nnscan_LI *li;
li = static_cast<nnscan_LI*>(local.addr);
switch (message)
{
case OPEN :
{ if(li){
delete li;
}
li = new nnscan_LI();
li->xtree = static_cast<XTree*>(args[0].addr);
li->relation = static_cast<Relation*>(args[1].addr);
local = SetWord(li);
HPointAttr *attr = static_cast<HPointAttr*>(args[2].addr);
string typeName = static_cast<CcString*>(args[3].addr)->GetValue();
if (attr->dim() != li->xtree->dim())
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator nnscan:" << endl
<< "The given hpoint has the dimension "
<< attr->dim() << ", but the xtree contains "
<< li->xtree->dim() << "-dimensional data!"
<< seperator << endl;
cmsg.send();
return CANCEL;
}
li->xtree->nnscan_init(attr->hpoint());
assert(li->relation != 0);
return 0;
}
case REQUEST :
{ if(!li){
return CANCEL;
}
TupleId tid = li->xtree->nnscan_next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li->xtree->nnscan_cleanup();
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 nnscan[_]VM
********************************************************************/
int nnscan_VM(
Word* args, Word& result, int message,
Word& local, Supplier s)
{
nnscan_LI *li;
switch (message)
{
case OPEN :
{
li = new nnscan_LI();
li->xtree = static_cast<XTree*>(args[0].addr);
li->relation = static_cast<Relation*>(args[1].addr);
local = SetWord(li);
Attribute *attr = static_cast<Attribute*>(args[2].addr);
string typeName = static_cast<CcString*>(args[3].addr)->GetValue();
if (li->xtree->typeName() != typeName)
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator nnscan:" << endl
<< "Got an \"" << typeName << "\" attribute, but the "
<< "xtree contains \"" << li->xtree->typeName()
<< "\" attriubtes!" << seperator << endl;
cmsg.send();
return CANCEL;
}
HPoint *p;
if (li->xtree->getdataType() == 0)
{ // use gethpoint function
HPointInfo info = HPointReg::getInfo(
typeName, li->xtree->getdataName());
p = info.getHPoint(attr);
}
else
{ // use getbbox function
BBoxInfo info = BBoxReg::getInfo(
typeName, li->xtree->getdataName());
HRect *r = info.getBBox(attr);
p = new HPoint(r->center());
delete r;
}
li->xtree->nnscan_init(p);
return 0;
}
case REQUEST :
{
li = static_cast<nnscan_LI*>(local.addr);
TupleId tid = li->xtree->nnscan_next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = static_cast<nnscan_LI*>(local.addr);
li->xtree->nnscan_cleanup();
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1.1 windowintersects[_]VM
********************************************************************/
int windowintersects_VM(
Word *args, Word &result, int message,
Word &local, Supplier s)
{
Search_LI *li;
switch (message)
{
case OPEN :
{
XTree *xtree = static_cast<XTree*>(args[0].addr);
li = new Search_LI(
static_cast<Relation*>(args[1].addr));
local = SetWord(li);
HRectAttr *attr =
static_cast<HRectAttr*>(args[2].addr);
if (attr->dim() != xtree->dim())
{
const string seperator = "\n" + string(70, '-') + "\n";
cmsg.error() << seperator
<< "Operator windowintersects:" << endl
<< "The given hrect has the dimension "
<< attr->dim() << ", but the xtree contains "
<< xtree->dim() << "-dimensional data!"
<< seperator << endl;
cmsg.send();
return CANCEL;
}
xtree->windowIntersects(attr->hrect(), li->results);
li->initResultIterator();
assert(li->relation != 0);
return 0;
}
case REQUEST :
{
li = (Search_LI*)local.addr;
if(!li->defined)
return CANCEL;
TupleId tid = li->next();
if(tid)
{
Tuple *tuple = li->relation->GetTuple(tid, false);
result = SetWord(tuple);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :
{
li = (Search_LI*)local.addr;
delete li;
local.addr = 0;
return 0;
}
}
return 0;
}
/********************************************************************
1.1.1 Type mappings
1.1.1.1 creatextree[_]TM
********************************************************************/
template<unsigned paramCnt>
ListExpr creatextree_TM(ListExpr args)
{
NList args_NL(args);
if(!args_NL.hasLength(paramCnt)){
stringstream err;
err << "Expected " << paramCnt << " arguments!";
return listutils::typeError(err.str());
}
NList attrs;
NList relStream_NL = args_NL.first();
NList attr_NL = args_NL.second();
if(!relStream_NL.checkRel(attrs) && !relStream_NL.checkStreamTuple(attrs)){
return listutils::typeError(
"Argument 1 must be a relation or tuple stream!");
}
// check, if the specified attr. can be found in attribute list
if(!attr_NL.isSymbol()){
return listutils::typeError(
"Argument 2 must be a symbol or an atomar type!");
}
string attrName = attr_NL.str();
string typeName;
int attrIndex;
ListExpr attrTypeLE;
attrIndex = FindAttribute(attrs.listExpr(), attrName, attrTypeLE);
if(attrIndex <= 0){
stringstream err;
err << "Attribute name \"" << attrName << "\" is not known.\n"
<< "Known Attribute(s):\n" << attrs.convertToString();
return listutils::typeError(err.str());
}
--attrIndex;
NList attrType (attrTypeLE);
typeName = attrType.str();
// get config name
string configName;
if (paramCnt > 2){
if(!args_NL.third().isSymbol()){
listutils::typeError(
"Argument 3 must be the name of an existing config object!");
}
configName = args_NL.third().str();
}
else
configName = CONFIG_DEFAULT;
if (!XTreeConfigReg::isDefined(configName))
{
string errmsg;
errmsg = "Config \"" + configName +
"\" not defined, defined names:\n\n" +
XTreeConfigReg::definedNames();
return listutils::typeError(errmsg);
}
if ((typeName == "hpoint") || (typeName == "hrect"))
{
NList res1(Symbol::APPEND());
NList res2;
res2.append(NList(attrIndex));
res2.append(NList(configName, true));
NList res3(XTree::BasicType());
NList result(res1, res2, res3);
return result.listExpr();
}
// attribut is no hpoint and no hrect, try to find getpoint or
// getbbox function:
// get name of getdata-function
string getdataName;
int getdataType; // 0 = gethpoint, 1 = gethrect
if (paramCnt > 3) // creatextree3
{
NList getdataName_NL = args_NL.fourth();
string errmsg;;
errmsg = "Argument 4 must be the name of an existing "
"gethrect or getdata function!";
if(!getdataName_NL.isSymbol()){
return listutils::typeError(errmsg);
}
getdataName = getdataName_NL.str();
getdataType = 0;
if (!HPointReg::isDefined(typeName, getdataName))
{ // getdataName is no defined gethpoint function
// search in HRectReg
getdataType = 1;
string errmsg;
errmsg = "No gethpoint or getbbox function with name \""
+ getdataName + "\" for type constructor \"" +
typeName + "\" found! Possible names:"
"\ngethpoint: " +
HPointReg::definedNames(typeName) +
"\ngetbbox : " +
BBoxReg::definedNames(typeName);
if(!BBoxReg::isDefined(typeName, getdataName)){
return listutils::typeError(errmsg);
}
}
}
else // creatextree, creatextree2
{ // try default gethpoint function
getdataName = HPointReg::defaultName(typeName);
getdataType = 0;
if (getdataName == HPOINT_UNDEFINED)
{ // no default gethpoint function found
// try default getbbox function
getdataName = BBoxReg::defaultName(typeName);
getdataType = 1;
string errmsg;
errmsg = "No default gethpoint or getbbox function "
"defined for type constructor \"" +
typeName + "\"!";
if(getdataName == BBOX_UNDEFINED){
return listutils::typeError(errmsg);
}
}
}
NList res1(Symbol::APPEND());
NList res2;
res2.append(NList(attrIndex));
res2.append(NList(configName, true));
res2.append(NList(typeName, true));
res2.append(NList(getdataType));
res2.append(NList(getdataName, true));
NList res3(XTree::BasicType());
NList result(res1, res2, res3);
return result.listExpr();
}
/********************************************************************
1.1.1.1 rangesearch[_]TM
********************************************************************/
ListExpr rangesearch_TM(ListExpr args)
{
// initialize distance functions and distdata types
if (!DistfunReg::isInitialized())
DistfunReg::initialize();
NList args_NL(args);
if(!args_NL.hasLength(4)){
return listutils::typeError("Expected 4 arguments!");
}
NList attrs;
NList mtree_NL = args_NL.first();
NList rel_NL = args_NL.second();
NList data_NL = args_NL.third();
NList searchRad_NL = args_NL.fourth();
if(!mtree_NL.isEqual(XTree::BasicType())){
return listutils::typeError("First argument must be a xtree!");
}
if(!rel_NL.checkRel(attrs)){
return listutils::typeError("Argument 2 must be a relation!");
}
if(!data_NL.isSymbol()){
return listutils::typeError(
"Argument 3 must be a symbol or an atomar type!");
}
if(!searchRad_NL.isEqual(CcReal::BasicType())){
return listutils::typeError("Argument 4 must be an \"real\" value!");
}
/* further type checkings for the data parameter will be done
in the value mapping function, since that needs some data from
the xtree object */
NList append(Symbol::APPEND());
NList result (
append,
NList(data_NL.str(), true).enclose(),
NList(NList(Symbol::STREAM()), rel_NL.second()));
return result.listExpr();
}
/********************************************************************
1.1.1.1 nnsearch[_]TM
********************************************************************/
ListExpr nnsearch_TM(ListExpr args)
{
// initialize distance functions and distdata types
if (!DistfunReg::isInitialized())
DistfunReg::initialize();
NList args_NL(args);
if(!args_NL.hasLength(4)){
return listutils::typeError("Expected 4 arguments!");
}
NList attrs;
NList mtree_NL = args_NL.first();
NList rel_NL = args_NL.second();
NList data_NL = args_NL.third();
NList nnCount_NL = args_NL.fourth();
if(!mtree_NL.isEqual(XTree::BasicType())){
return listutils::typeError("First argument must be a xtree!");
}
if(!rel_NL.checkRel(attrs)){
return listutils::typeError("Argument 2 must be a relation!");
}
if(!data_NL.isSymbol()){
return listutils::typeError(
"Argument 3 must be a symbol or an atomar type!");
}
if(!nnCount_NL.isEqual(CcInt::BasicType())){
return listutils::typeError("Argument 4 must be an \"int\" value!");
}
/* further type checkings for the data parameter will be done
in the value mapping function, since that needs some data from
the xtree object */
NList append(Symbol::APPEND());
NList result (
append,
NList(data_NL.str(), true).enclose(),
NList(NList(Symbol::STREAM()), rel_NL.second()));
return result.listExpr();
}
/********************************************************************
1.1.1.1 windowintersects[_]TM
********************************************************************/
ListExpr windowintersects_TM(ListExpr args)
{
NList args_NL(args);
if(!args_NL.hasLength(3)){
return listutils::typeError("Expected 3 arguments!");
}
NList attrs;
NList xtree_NL = args_NL.first();
NList rel_NL = args_NL.second();
NList hrect_NL = args_NL.third();
if(!xtree_NL.isEqual(XTree::BasicType())){
return listutils::typeError("First argument must be a xtree!");
}
if(!rel_NL.checkRel(attrs)){
return listutils::typeError("Argument 2 must be a relation!");
}
if(!hrect_NL.isSymbol()){
return listutils::typeError(
"Argument 3 must be a symbol or an atomar type!");
}
string typeName = hrect_NL.str();
string error = "Expecting a \"hrect\" as third parameter!";
if(typeName != "hrect"){
return listutils::typeError(error);
}
NList stream_NL(Symbol::STREAM());
NList result(stream_NL, rel_NL.second());
return result.listExpr();
}
/********************************************************************
1.1.1.1 nnscan[_]TM
********************************************************************/
ListExpr nnscan_TM(ListExpr args)
{
// initialize distance functions and distdata types
if (!DistfunReg::isInitialized())
DistfunReg::initialize();
NList args_NL(args);
if(!args_NL.hasLength(3)){
return listutils::typeError("Expected 3 arguments!");
}
NList attrs;
NList mtree_NL = args_NL.first();
NList rel_NL = args_NL.second();
NList data_NL = args_NL.third();
if(!mtree_NL.isEqual(XTree::BasicType())){
return listutils::typeError("First argument must be a xtree!");
}
if(!rel_NL.checkRel(attrs)){
return listutils::typeError("Argument 2 must be a relation!");
}
if(!data_NL.isSymbol()){
return listutils::typeError(
"Argument 3 must be a symbol or an atomar type!");
}
/* further type checkings for the data parameter will be done
in the value mapping function, since that needs some data from
the xtree object */
NList append(Symbol::APPEND());
NList result (
append,
NList(data_NL.str(), true).enclose(),
NList(NList(Symbol::STREAM()), rel_NL.second()));
return result.listExpr();
}
/********************************************************************
1.1.1 Selection functions
********************************************************************/
int creatextree_Select(ListExpr args)
{
NList argsNL(args);
NList arg1 = argsNL.first();
NList attrs = arg1.second().second();
NList arg2 = argsNL.second();
// get type of selected attribute
string attrName = arg2.str();
ListExpr attrTypeLE;
FindAttribute(attrs.listExpr(), attrName, attrTypeLE);
NList attrType(attrTypeLE);
if (arg1.first().isEqual(Relation::BasicType()))
{ // relation
if (attrType.isEqual("hpoint"))
return 0;
else if (attrType.isEqual("hrect"))
return 1;
else
return 2;
}
else
{ // stream
if (attrType.isEqual("hpoint"))
return 3;
else if (attrType.isEqual("hrect"))
return 4;
else
return 5;
}
}
int creatextree3_Select(ListExpr args)
{
NList argsNL(args);
NList arg1 = argsNL.first();
if (arg1.first().isEqual(Relation::BasicType()))
return 0;
else
return 1;
}
int search_Select(ListExpr args)
{
NList argsNL(args);
NList arg3 = argsNL.third();
if (arg3.isEqual("hpoint"))
return 0;
else
return 1;
}
/********************************************************************
1.1.1 Value mapping arrays
********************************************************************/
ValueMapping creatextree_Map[] = {
creatextreeHPointRel_VM<2>,
creatextreeHRectRel_VM<2>,
creatextreeRel_VM<2>,
creatextreeHPointStream_VM<2>,
creatextreeHRectStream_VM<2>,
creatextreeStream_VM<2>,
};
ValueMapping creatextree2_Map[] = {
creatextreeHPointRel_VM<3>,
creatextreeHRectRel_VM<3>,
creatextreeRel_VM<3>,
creatextreeHPointStream_VM<3>,
creatextreeHRectStream_VM<3>,
creatextreeStream_VM<3>,
};
ValueMapping creatextree3_Map[] = {
creatextreeRel_VM<4>,
creatextreeStream_VM<4>,
};
ValueMapping rangesearch_Map[] = {
rangesearchHPoint_VM,
rangesearch_VM,
};
ValueMapping nnsearch_Map[] = {
nnsearchHPoint_VM,
nnsearch_VM,
};
ValueMapping nnscan_Map[] = {
nnscanHPoint_VM,
nnscan_VM,
};
/********************************************************************
1.1.1 Operator infos
********************************************************************/
struct creatextree_Info : OperatorInfo
{
creatextree_Info()
{
name = "creatextree";
signature =
"rel/tuple stream x attribute -> xtree";
syntax = "_ creatextree [_]";
meaning =
"Creates a new xtree from the relation or tuple stream "
"in argument 1. Argument 2 must be the name of the "
"attribute in the relation/tuple stream, that should "
"be indexed in the xtree. "
"This operator uses the default xtree config.";
example = "strassen creatextree[geoData]";
}
};
struct creatextree2_Info : OperatorInfo
{
creatextree2_Info()
{
name = "creatextree2";
signature =
"rel/tuple stream x attribute x config-name -> xtree";
syntax = "_ creatextree2 [_, _]";
meaning =
"Like creatextree, but additionaly allows to specify "
"another than the default xtree config.";
example = "strassen creatextree2[geoData, limit80e]";
}
};
struct creatextree3_Info : OperatorInfo
{
creatextree3_Info()
{
name = "creatextree3";
signature =
"rel/tuple stream x attribute x config-name x getdatafun-name -> xtree";
syntax = "_ creatextree3 [_, _, _]";
meaning =
"Like creatextree2, but additionaly allows to specify "
"another than the default gethpoint or getbbox function "
"(if a gethpoint and a getbbox function with the same name "
"are defined, the gethpoint function will be used).";
example = "strassen creatextree3[geoData, limit80e, native]";
}
};
struct rangesearch_Info : OperatorInfo
{
rangesearch_Info()
{
name = "rangesearch";
signature = "xtree x relation x hpoint x real -> tuple stream";
syntax = "_ _ rangesearch [_, _]";
meaning =
"Returns a tuple stream, which contains all attributes, "
"that could be found within the search radius "
"(argument 4, using the Euclidean metric) to the query "
"point. The relation must contain at least the same "
"tuples, that had been used to create the xtree.";
example = "xt strassen rangesearch [p, 5000.0]";
}
};
struct nnsearch_Info : OperatorInfo
{
nnsearch_Info()
{
name = "nnsearch";
signature = "xtree x relation x hpoint x int -> tuple stream";
syntax = "_ _ nnsearch [_, _]";
meaning =
"Returns a tuple stream, which contains the k nearest "
"neighbours of the query point. The relation must "
"contain at least the same tuples, that had been used "
"to create the xtree.";
example = "xt strassen nnsearch [p, 20]";
}
};
struct windowintersects_Info : OperatorInfo
{
windowintersects_Info()
{
name = "windowintersects";
signature = "xtree x relation x hrect -> tuple stream";
syntax = "_ _ rangesearch [_]";
meaning =
"Returns a tuple stream, which contains all attributes, "
"that intersects the search windows. The relation must "
"contain at least the same tuples, that had been used "
"to create the xtree.";
example = "xt strassen windowintersects [r]";
}
};
struct nnscan_Info : OperatorInfo
{
nnscan_Info()
{
name = "nnscan";
signature = "xtree x relation x fun x hpoint x int -> tuple stream";
syntax = "_ _ nnscan [_]";
meaning =
"Returns a tuple stream, which contains the ranking of the indized"
"elements, based on the distance to the query point. The relation "
"must contain at least the same tuples, that had been used "
"to create the xtree.";
example = "xt strassen nnscan [p] head[30] count";
}
};
/********************************************************************
1.1 Create and initialize the Algebra
********************************************************************/
class XTreeAlgebra
: public Algebra
{
public:
XTreeAlgebra()
: Algebra()
{
AddTypeConstructor(&xtreeTC);
AddOperator(creatextree_Info(),
creatextree_Map,
creatextree_Select,
creatextree_TM<2>);
AddOperator(creatextree2_Info(),
creatextree2_Map,
creatextree_Select,
creatextree_TM<3>);
AddOperator(creatextree3_Info(),
creatextree3_Map,
creatextree3_Select,
creatextree_TM<4>);
AddOperator(rangesearch_Info(),
rangesearch_Map,
search_Select,
rangesearch_TM);
AddOperator(nnsearch_Info(),
nnsearch_Map,
search_Select,
nnsearch_TM);
AddOperator(windowintersects_Info(),
windowintersects_VM,
windowintersects_TM);
AddOperator(nnscan_Info(),
nnscan_Map,
search_Select,
nnscan_TM);
}
~XTreeAlgebra()
{};
};
} // namespace xtreeAlgebra
extern "C"
Algebra *InitializeXTreeAlgebra(
NestedList *nlRef, QueryProcessor *qpRef)
{
nl = nlRef;
qp = qpRef;
return (new xtreeAlgebra::XTreeAlgebra());
}