392 lines
10 KiB
C++
392 lines
10 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 insertbtree and insertbtree2 Operators
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
0 Overview
|
||
|
|
|
||
|
|
1 Defines and Includes
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "op_insertbtree.h"
|
||
|
|
|
||
|
|
#include "ListUtils.h"
|
||
|
|
#include "QueryProcessor.h"
|
||
|
|
#include "Algebras/Relation-C++/RelationAlgebra.h"
|
||
|
|
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
|
||
|
|
#include "Symbols.h"
|
||
|
|
|
||
|
|
#include "BTree2.h"
|
||
|
|
|
||
|
|
extern NestedList* nl;
|
||
|
|
extern QueryProcessor *qp;
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
|
||
|
|
namespace BTree2Algebra {
|
||
|
|
namespace Operators {
|
||
|
|
|
||
|
|
/*
|
||
|
|
2 Operators ~insertbtree~ and ~insertbtree2~
|
||
|
|
|
||
|
|
Inserts the entries from the stream into the btree2.
|
||
|
|
|
||
|
|
Signatures are
|
||
|
|
|
||
|
|
----
|
||
|
|
insertbtree: stream(tuple(T)) x (btree2 Tk Td u) x ak x ad -->
|
||
|
|
stream(tuple(T))
|
||
|
|
|
||
|
|
insertbtree2: stream(tuple(X@[TID tid])) x (btree2 Tk tid multiple)
|
||
|
|
x ak --> stream(tuple(X@[TID tid]))
|
||
|
|
----
|
||
|
|
|
||
|
|
2.1 TypeMapping
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr insertbtree::TypeMappingAll(ListExpr args, bool wrapper)
|
||
|
|
{
|
||
|
|
if (wrapper){
|
||
|
|
if(nl->ListLength(args) != 3){
|
||
|
|
return listutils::typeError("Operator insertbtree expects 3 arguments.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
if(nl->ListLength(args) != 4){
|
||
|
|
return listutils::typeError("Operator insertbtree2 expects"
|
||
|
|
" 4 arguments.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Split argument in four parts */
|
||
|
|
ListExpr streamDescription = nl->First(args);
|
||
|
|
ListExpr btreeDescription = nl->Second(args);
|
||
|
|
ListExpr nameOfKeyAttribute = nl->Third(args);
|
||
|
|
ListExpr attrType;
|
||
|
|
|
||
|
|
|
||
|
|
if(!listutils::isTupleStream(streamDescription)){
|
||
|
|
return listutils::typeError("first arguments must be a tuple stream");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr attrList = nl->Second(nl->Second(streamDescription)); // get attrlist
|
||
|
|
|
||
|
|
if (wrapper){
|
||
|
|
if(nl->ListLength(attrList)<=1){
|
||
|
|
return listutils::typeError("stream must contain at least 2 attributes");
|
||
|
|
}
|
||
|
|
ListExpr rest = nl->Second(nl->Second(streamDescription));
|
||
|
|
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 attribute must be of type tid");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!listutils::isBTree2Description(btreeDescription)){
|
||
|
|
return listutils::typeError("second argument is not a valid btree2");
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr btreeValue = nl->Third(btreeDescription);
|
||
|
|
|
||
|
|
if (wrapper){
|
||
|
|
if(!listutils::isSymbol(btreeValue, TupleIdentifier::BasicType())){
|
||
|
|
return listutils::typeError("Value type of btree has to b tid");
|
||
|
|
}
|
||
|
|
if(!listutils::isSymbol(nl->Fourth(btreeDescription), "multiple")){
|
||
|
|
return listutils::typeError("Keys have to be multiple");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(!listutils::isSymbol(nameOfKeyAttribute)){
|
||
|
|
return listutils::typeError("invalid name for key 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;
|
||
|
|
if (!wrapper){
|
||
|
|
ListExpr nameOfDataAttribute = nl->Fourth(args);
|
||
|
|
if(!listutils::isSymbol(nameOfDataAttribute)){
|
||
|
|
return listutils::typeError("invalid name for data attribute");
|
||
|
|
}
|
||
|
|
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.");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (wrapper){
|
||
|
|
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->IntAtom(keyIndex), nl->
|
||
|
|
IntAtom(nl->ListLength(attrList))), streamDescription);
|
||
|
|
}
|
||
|
|
else{
|
||
|
|
return nl->ThreeElemList(nl->SymbolAtom(Symbol::APPEND()),
|
||
|
|
nl->TwoElemList(nl->IntAtom(keyIndex),
|
||
|
|
nl->IntAtom(valueIndex)), streamDescription);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.1.1 Type map for insertbtree
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr insertbtree::TypeMapping1(ListExpr args){
|
||
|
|
return insertbtree::TypeMappingAll(args);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.1.2 Type map for insertbtree2
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr insertbtree::TypeMapping2(ListExpr args){
|
||
|
|
return insertbtree::TypeMappingAll(args, false);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.2 Value mapping for insertbtree
|
||
|
|
|
||
|
|
*/
|
||
|
|
struct vmInfo{
|
||
|
|
BTree2* btree;
|
||
|
|
int keyIndex;
|
||
|
|
int valueIndex;
|
||
|
|
|
||
|
|
vmInfo(BTree2* b, int k, int v) : btree(b), keyIndex(k), valueIndex(v) {}
|
||
|
|
};
|
||
|
|
|
||
|
|
int
|
||
|
|
insertbtree::ValueMapping1(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[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);
|
||
|
|
value = tuple->GetAttribute(info->valueIndex);
|
||
|
|
if (((TupleIdentifier*)value)->GetTid() == 0){
|
||
|
|
tuple->DeleteIfAllowed();
|
||
|
|
return CANCEL;
|
||
|
|
}
|
||
|
|
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.3 Valuemapping for insertbtree2
|
||
|
|
|
||
|
|
*/
|
||
|
|
int
|
||
|
|
insertbtree::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->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;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
2.4 Operator specifications
|
||
|
|
|
||
|
|
*/
|
||
|
|
struct getInsertBTree2Info : OperatorInfo {
|
||
|
|
|
||
|
|
getInsertBTree2Info() : OperatorInfo()
|
||
|
|
{
|
||
|
|
name = "insertbtree2";
|
||
|
|
signature = "stream(tuple(T)) x (btree2 Tk Td u) x ak x ad ->"
|
||
|
|
" stream(tuple(T))";
|
||
|
|
syntax = "_ _ insertbtree2 [ _, _ ]";
|
||
|
|
meaning = "Inserts the pairs of values/keys specified by the "
|
||
|
|
"arguments into the BTree2";
|
||
|
|
example = "query Staedte feed staedte_btree2 insertbtree2 "
|
||
|
|
"[SName, Bev] count;";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
struct getInsertBTreeInfo : OperatorInfo {
|
||
|
|
|
||
|
|
getInsertBTreeInfo() : OperatorInfo()
|
||
|
|
{
|
||
|
|
name = "insertbtree";
|
||
|
|
signature = "stream(tuple(X@[TID tid])) x (btree2 Tk tid multiple) x ak"
|
||
|
|
" -> stream(tuple(X@[TID tid]))";
|
||
|
|
syntax = "_ _ insertbtree [ _ ]";
|
||
|
|
meaning = "Inserts the pairs of values/keys specified by the "
|
||
|
|
"arguments into the BTree2";
|
||
|
|
example = "query Staedte feed addid staedte_btree2_tid "
|
||
|
|
"insertbtree [SName] count";
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
Operator insertbtree::insertbtree1 (getInsertBTreeInfo(), insertbtree::
|
||
|
|
ValueMapping1, insertbtree::TypeMapping1);
|
||
|
|
|
||
|
|
Operator insertbtree::insertbtree2 (getInsertBTree2Info(), insertbtree::
|
||
|
|
ValueMapping2, insertbtree::TypeMapping2);
|
||
|
|
|
||
|
|
} // end namespace operators
|
||
|
|
} // end namespace btree2algebra
|
||
|
|
|