447 lines
12 KiB
C++
447 lines
12 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 the updatebtree and updatebtree2 Operator
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
0 Overview
|
||
|
|
|
||
|
|
1 Defines and Includes
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "op_updatebtree.h"
|
||
|
|
|
||
|
|
#include "ListUtils.h"
|
||
|
|
#include "QueryProcessor.h"
|
||
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
||
|
|
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
|
||
|
|
#include "Symbols.h"
|
||
|
|
|
||
|
|
#include "BTree2.h"
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
|
||
|
|
|
||
|
|
extern NestedList* nl;
|
||
|
|
extern QueryProcessor *qp;
|
||
|
|
|
||
|
|
namespace BTree2Algebra {
|
||
|
|
namespace Operators {
|
||
|
|
|
||
|
|
/*
|
||
|
|
2 Operators ~updatebtree~ and ~updatebtree2~
|
||
|
|
|
||
|
|
Updates the entries given in the tuple stream. updatebtree2
|
||
|
|
inserts a new entry, if an entry with the argument key does not
|
||
|
|
exist. If the valuetype is none, updatebtree2 simply tries to
|
||
|
|
insert an entry with the argument key.
|
||
|
|
|
||
|
|
Signature is
|
||
|
|
|
||
|
|
----
|
||
|
|
updatebtree: stream(tuple(X@[(a1\_old x1)...(ak\_old Tk)...(ak\_old xk )
|
||
|
|
(TID tid)])) x btree2 x ak -->stream(tuple(X@[(a1\_old x1)
|
||
|
|
...(ak\_old Tk)...(ak\_old xk ) (TID tid)]))
|
||
|
|
|
||
|
|
updatebtree2: stream(tuple(T)) x btree2 x ak x ad ->
|
||
|
|
stream(tuple(T))
|
||
|
|
----
|
||
|
|
|
||
|
|
2.1 TypeMappings
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr updatebtree::TypeMapping1(ListExpr args){
|
||
|
|
if(nl->ListLength(args) != 3){
|
||
|
|
return listutils::typeError("Operator updatebtree expects 3 arguments.");
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
Split argument in three parts
|
||
|
|
|
||
|
|
*/
|
||
|
|
int keyIndex;
|
||
|
|
ListExpr streamDescription = nl->First(args);
|
||
|
|
ListExpr btreeDescription = nl->Second(args);
|
||
|
|
ListExpr nameOfKeyAttribute = nl->Third(args);
|
||
|
|
|
||
|
|
if(!listutils::isTupleStream(streamDescription)){
|
||
|
|
return listutils::typeError("first arguments must be a tuple stream");
|
||
|
|
}
|
||
|
|
ListExpr attrList = nl->Second(nl->Second(streamDescription));
|
||
|
|
if(nl->ListLength(attrList)<3){
|
||
|
|
return listutils::typeError("stream must contains at least 3 attributes");
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Proceed to last attribute of stream-tuples
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr rest = attrList;
|
||
|
|
ListExpr next = nl->First(rest);
|
||
|
|
while (!(nl->IsEmpty(rest)))
|
||
|
|
{
|
||
|
|
next = nl->First(rest);
|
||
|
|
rest = nl->Rest(rest);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(nl->Second(next),TupleIdentifier::BasicType())){
|
||
|
|
return listutils::typeError("last attribut must be of type tid");
|
||
|
|
}
|
||
|
|
int tidIndex = nl->ListLength(attrList);
|
||
|
|
|
||
|
|
if(!listutils::isBTree2Description(btreeDescription)){
|
||
|
|
return listutils::typeError("second argument is not a valid btree2");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr btreeKey = nl->Second(btreeDescription);
|
||
|
|
ListExpr btreeValue = nl->Third(btreeDescription);
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(btreeValue, TupleIdentifier::BasicType())){
|
||
|
|
return listutils::typeError("Value type of btree has to be tid");
|
||
|
|
}
|
||
|
|
if(!listutils::isSymbol(nl->Fourth(btreeDescription), "multiple")){
|
||
|
|
return listutils::typeError("Keys have to be multiple");
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(nameOfKeyAttribute)){
|
||
|
|
return listutils::typeError("invalid attribute name for key");
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
check that attributelist has old and new attributenames
|
||
|
|
|
||
|
|
*/
|
||
|
|
if ((nl->ListLength(attrList) % 2) != 1){
|
||
|
|
return listutils::typeError("tuple stream must contain one attribute "
|
||
|
|
"of kind tid and the same amount of old and "
|
||
|
|
"new attributes.");
|
||
|
|
}
|
||
|
|
int split = (nl->ListLength(attrList) - 1) / 2;
|
||
|
|
ListExpr oldAttrList = attrList;
|
||
|
|
for (int i = 0; i < split; i++){
|
||
|
|
oldAttrList = nl->Rest(oldAttrList);
|
||
|
|
}
|
||
|
|
rest = attrList;
|
||
|
|
for (int i = 0; i < split; i++){
|
||
|
|
string oldName;
|
||
|
|
nl->WriteToString(oldName,
|
||
|
|
nl->First(nl->First(rest)));
|
||
|
|
oldName += "_old";
|
||
|
|
ListExpr oldAttribute = nl->TwoElemList(nl->SymbolAtom(oldName),
|
||
|
|
nl->Second(nl->First(rest)));
|
||
|
|
if(!nl->Equal(oldAttribute, nl->First(oldAttrList))){
|
||
|
|
return listutils::typeError("Second part of the "
|
||
|
|
"tupledescription of the stream without the last "
|
||
|
|
"attribute has to be the same as the tuple"
|
||
|
|
"description of the btree except that the "
|
||
|
|
"attributenames carry an additional '_old.'");
|
||
|
|
}
|
||
|
|
rest = nl->Rest(rest);
|
||
|
|
oldAttrList = nl->Rest(oldAttrList);
|
||
|
|
//i++;
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Test if attributename of the third argument exists as a name in the
|
||
|
|
attributelist of the streamtuples
|
||
|
|
|
||
|
|
*/
|
||
|
|
string attrname = nl->SymbolValue(nameOfKeyAttribute);
|
||
|
|
ListExpr attrtype;
|
||
|
|
keyIndex = listutils::findAttribute(attrList,attrname,attrtype);
|
||
|
|
if(keyIndex==0){
|
||
|
|
return listutils::typeError("attribute name of key not found");
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!nl->Equal(attrtype, btreeKey)){
|
||
|
|
return listutils::typeError("key attribute type "
|
||
|
|
"different from indexed type");
|
||
|
|
}
|
||
|
|
ListExpr outList = nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->IntAtom(keyIndex),
|
||
|
|
nl->IntAtom(tidIndex)),streamDescription);
|
||
|
|
return outList;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ListExpr updatebtree::TypeMapping2(ListExpr args){
|
||
|
|
|
||
|
|
if(nl->ListLength(args) != 4){
|
||
|
|
return listutils::typeError("Operator updatebtree2 expects 4 arguments.");
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Split argument in four parts
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr streamDescription = nl->First(args);
|
||
|
|
ListExpr btreeDescription = nl->Second(args);
|
||
|
|
ListExpr nameOfKeyAttribute = nl->Third(args);
|
||
|
|
ListExpr nameOfDataAttribute = nl->Fourth(args);
|
||
|
|
ListExpr attrType;
|
||
|
|
|
||
|
|
|
||
|
|
if(!listutils::isTupleStream(streamDescription)){
|
||
|
|
return listutils::typeError("first arguments must be a tuple stream");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr attrList = nl->Second(nl->Second(streamDescription));
|
||
|
|
|
||
|
|
if(!listutils::isBTree2Description(btreeDescription)){
|
||
|
|
return listutils::typeError("second argument is not a valid btree2");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr btreeValue = nl->Third(btreeDescription);
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(nameOfKeyAttribute)){
|
||
|
|
return listutils::typeError("invalid name for key attribute");
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(nameOfDataAttribute)){
|
||
|
|
return listutils::typeError("invalid name for data attribute");
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Check key
|
||
|
|
|
||
|
|
*/
|
||
|
|
string name;
|
||
|
|
nl->WriteToString(name, nameOfKeyAttribute);
|
||
|
|
int keyIndex = listutils::findAttribute(attrList, name, attrType);
|
||
|
|
if(keyIndex <=0 ){
|
||
|
|
return listutils::typeError("Tuples do not contain an attribute named " +
|
||
|
|
name + ".");
|
||
|
|
}
|
||
|
|
ListExpr btreeKey = nl->Second(btreeDescription);
|
||
|
|
if(!nl->Equal(attrType, btreeKey)){
|
||
|
|
return listutils::typeError("Key in tuple is different from btree2 key.");
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
Check value-types
|
||
|
|
|
||
|
|
*/
|
||
|
|
int valueIndex = 0;
|
||
|
|
nl->WriteToString(name, nameOfDataAttribute);
|
||
|
|
|
||
|
|
if (name == "none"){
|
||
|
|
if(!nl->Equal(nameOfDataAttribute, btreeValue)){
|
||
|
|
return listutils::typeError("Argument value type is "
|
||
|
|
"different from btree value type.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
valueIndex = listutils:: findAttribute(attrList, name, attrType);
|
||
|
|
if(valueIndex <= 0){
|
||
|
|
return listutils::typeError("Tuples do not contain"
|
||
|
|
" an attribute named " +
|
||
|
|
name + ".");
|
||
|
|
}
|
||
|
|
if(!nl->Equal(attrType, btreeValue)){
|
||
|
|
return listutils::typeError("Value type in tuple is "
|
||
|
|
"different from btree2 value type.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->IntAtom(keyIndex),
|
||
|
|
nl->IntAtom(valueIndex)), streamDescription);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.2 Value mappings
|
||
|
|
|
||
|
|
*/
|
||
|
|
struct vmInfo{
|
||
|
|
BTree2* btree;
|
||
|
|
int keyIndex;
|
||
|
|
int valueIndex;
|
||
|
|
|
||
|
|
vmInfo(BTree2* b, int k, int v) : btree(b), keyIndex(k), valueIndex(v) {}
|
||
|
|
};
|
||
|
|
|
||
|
|
int
|
||
|
|
updatebtree::ValueMapping1(Word* args, Word& result, int message,
|
||
|
|
Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
vmInfo* info;
|
||
|
|
Tuple* tuple;
|
||
|
|
Word elem;
|
||
|
|
Attribute* key, *keyOld;
|
||
|
|
Attribute* value;
|
||
|
|
|
||
|
|
switch (message)
|
||
|
|
{
|
||
|
|
case OPEN :
|
||
|
|
{
|
||
|
|
BTree2* btree = (BTree2*)args[1].addr;
|
||
|
|
int k = ((CcInt*)args[3].addr)->GetIntval();
|
||
|
|
int v = ((CcInt*)args[4].addr)->GetIntval();
|
||
|
|
info = new vmInfo(btree, k - 1, v - 1);
|
||
|
|
local.addr = info;
|
||
|
|
qp->Open(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
case REQUEST :
|
||
|
|
{
|
||
|
|
qp->Request(args[0].addr, elem);
|
||
|
|
if (qp->Received(args[0].addr))
|
||
|
|
{
|
||
|
|
info = (vmInfo*)local.addr;
|
||
|
|
tuple = (Tuple*)elem.addr;
|
||
|
|
key = tuple->GetAttribute(info->keyIndex);
|
||
|
|
keyOld = tuple->GetAttribute((tuple->GetNoAttributes() - 1) / 2 +
|
||
|
|
info->keyIndex);
|
||
|
|
value = tuple->GetAttribute(info->valueIndex);
|
||
|
|
if ( (key->Compare(keyOld) != 0) )
|
||
|
|
{
|
||
|
|
if (info->btree->DeleteGeneric(keyOld,value))
|
||
|
|
info->btree->AppendGeneric(key,value);
|
||
|
|
}
|
||
|
|
result.setAddr(tuple);
|
||
|
|
return YIELD;
|
||
|
|
}
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
|
||
|
|
case CLOSE :
|
||
|
|
{
|
||
|
|
if (local.addr){
|
||
|
|
info = (vmInfo*)local.addr;
|
||
|
|
delete info;
|
||
|
|
local.setAddr(0);
|
||
|
|
}
|
||
|
|
qp->Close(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
updatebtree::ValueMapping2(Word* args, Word& result, int message,
|
||
|
|
Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
vmInfo* info;
|
||
|
|
Tuple* tuple;
|
||
|
|
Word elem;
|
||
|
|
Attribute* key;
|
||
|
|
Attribute* value;
|
||
|
|
|
||
|
|
switch (message)
|
||
|
|
{
|
||
|
|
case OPEN :
|
||
|
|
{
|
||
|
|
BTree2* btree = (BTree2*)args[1].addr;
|
||
|
|
int k = ((CcInt*)args[4].addr)->GetIntval();
|
||
|
|
int v = ((CcInt*)args[5].addr)->GetIntval();
|
||
|
|
info = new vmInfo(btree, k - 1, v - 1);
|
||
|
|
local.addr = info;
|
||
|
|
qp->Open(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
case REQUEST :
|
||
|
|
{
|
||
|
|
qp->Request(args[0].addr, elem);
|
||
|
|
if (qp->Received(args[0].addr))
|
||
|
|
{
|
||
|
|
info = (vmInfo*)local.addr;
|
||
|
|
tuple = (Tuple*)elem.addr;
|
||
|
|
key = tuple->GetAttribute(info->keyIndex);
|
||
|
|
if (info->valueIndex == -1){
|
||
|
|
info->btree->AppendGeneric(key, 0);
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
value = tuple->GetAttribute(info->valueIndex);
|
||
|
|
info->btree->UpdateGeneric(key, value);
|
||
|
|
}
|
||
|
|
result.setAddr(tuple);
|
||
|
|
return YIELD;
|
||
|
|
}
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
|
||
|
|
case CLOSE :
|
||
|
|
{
|
||
|
|
if (local.addr){
|
||
|
|
info = (vmInfo*)local.addr;
|
||
|
|
delete info;
|
||
|
|
local.setAddr(0);
|
||
|
|
}
|
||
|
|
qp->Close(args[0].addr);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.3 Operator specifications
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
struct getUpdateBTree2Info : OperatorInfo {
|
||
|
|
|
||
|
|
getUpdateBTree2Info() : OperatorInfo()
|
||
|
|
{
|
||
|
|
name = "updatebtree2";
|
||
|
|
signature = "stream(tuple(T)) x (btree2 Tk Td u) x ak x ad ->"
|
||
|
|
" stream(tuple(T))";
|
||
|
|
syntax = "_ _ updatebtree2 [ _, _ ]";
|
||
|
|
meaning = "Updates the first found entry with the argument key, "
|
||
|
|
"if existant,"
|
||
|
|
" or inserts the pairs of values/keys specified by the "
|
||
|
|
"arguments into the BTree2";
|
||
|
|
example = "query Staedte feed extend [Bev_new: .Bev + 1] "
|
||
|
|
"staedte_btree2 updatebtree2 [SName, Bev_new] consume";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
struct getUpdateBTreeInfo : OperatorInfo {
|
||
|
|
|
||
|
|
getUpdateBTreeInfo() : OperatorInfo()
|
||
|
|
{
|
||
|
|
name = "updatebtree";
|
||
|
|
signature = "stream(tuple(X@[(a1 x1)...(ak Tk)...(an xn)(TID tid)]))"
|
||
|
|
" x (btree2 Tk tid multiple) x ak ->"
|
||
|
|
" stream(tuple(X@[(a1 x1)...(ak Tk)...(an xn)(TID tid)]))";
|
||
|
|
syntax = "_ _ updatebtree [ _ ]";
|
||
|
|
meaning = "Updates the key of the old entry";
|
||
|
|
example = " query Staedte feed Staedte updatedirect[Bev: .Bev + 1] "
|
||
|
|
"staedte_btree2_tid updatebtree [SName] count";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
Operator updatebtree::updatebtree1 (getUpdateBTreeInfo(), updatebtree::
|
||
|
|
ValueMapping1, updatebtree::TypeMapping1);
|
||
|
|
|
||
|
|
Operator updatebtree::updatebtree2 (getUpdateBTree2Info(), updatebtree::
|
||
|
|
ValueMapping2, updatebtree::TypeMapping2);
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|