Files
secondo/Algebras/BTree2/op_updatebtree.cpp

447 lines
12 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
----
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);
}
}