/* ---- This file is part of SECONDO. Copyright (C) 2015, Faculty of Mathematics and 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 ---- //[$][\$] */ #include "NestedList.h" #include "ListUtils.h" #include "QueryProcessor.h" #include "StandardTypes.h" #include "SecParser.h" #include "Stream.h" #include "Algebras/DRel/DRel.h" #include "Algebras/DRel/DRelHelpers.h" #include "Algebras/Distributed2/DArray.h" #include "Algebras/FText/FTextAlgebra.h" #include "Algebras/Relation-C++/OperatorFilter.h" #include #include extern NestedList* nl; extern QueryProcessor* qp; template ListExpr insertDeleteRelTypeMap(ListExpr args); ListExpr insertTupleTypeMap(ListExpr args); ListExpr updateSearchRelTypeMap(ListExpr args); ListExpr updateDirectRelTypeMap(ListExpr args); ListExpr appendIdentifierTypeMap (ListExpr args); ListExpr allUpdatesRTreeTypeMap(ListExpr& args, std::string opName); ListExpr allUpdatesBTreeTypeMap( const ListExpr& args, std::string opName); template ListExpr IndexQuerySTypeMap(ListExpr args); ListExpr WindowIntersectsSTypeMap(ListExpr args); ListExpr deletebyid4TM(ListExpr args); ListExpr updatebyid2TM(ListExpr args); using namespace drel; using namespace distributed2; namespace drelupdate{ extern Operator drelspatialjoinOp; /* 1. Operator ~drelinsert~ 1.1 Type Mapping ~drelinsert~ */ ListExpr drelinsertTM( ListExpr args ){ std::string err = "stream(tuple(X)) x drel(rel(tuple(X))) x int " "expected"; if(!nl->HasLength(args,3)){ return listutils::typeError("wrong number of arguments"); } // check for correct types ListExpr streamType = nl->First( args ); if(!Stream::checkType(streamType)){ return listutils::typeError(err + ": first argument is not a stream"); } ListExpr drelType = nl->Second( args ); distributionType type; int attr, key; if(!DRel::checkType( drelType, type, attr, key ) ){ return listutils::typeError(err + ": second argument is not a drel"); } ListExpr port = nl->Third( args ); if(!CcInt::checkType( port ) ){ return listutils::typeError(err + ": last argument not of type int"); } //streamType != relType (spatial2d, 3d, replicated) ListExpr attrList = nl->Second(nl->Second( streamType ) ); if( type == replicated ){ attrList = ConcatLists( attrList, nl->OneElemList(nl->TwoElemList( nl->SymbolAtom("Original"), listutils::basicSymbol() ) ) ); } else if ( type == spatial2d || type == spatial3d ) { attrList = DRelHelpers::addPartitionAttributes( attrList ); } streamType = nl->TwoElemList( listutils::basicSymbol >(), nl->TwoElemList( listutils::basicSymbol(), attrList) ); ListExpr result = insertDeleteRelTypeMap<0>( nl->TwoElemList( streamType, nl->Second(drelType) ) ); if(!listutils::isTupleStream( result ) ){ return result; } ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second(result) ), nl->Third(drelType) ); //distType return resType; } /* ~distributeSimilarToDRel~ Distributes a relation in the same manner as a given drel. */ bool distributeSimilarToDRel( Relation* rel, ListExpr relType, DRel* drel, ListExpr drelType, DFRel*& dfrel_tmp ){ std::string relPtr = nl->ToString( DRelHelpers::createPointerList( relType, rel) ); std::string drelPtr = nl->ToString( DRelHelpers::createdrel2darray( drelType, drel) ); distributionType type = drel->getDistType()->getDistType(); std::string dtype = getName(type); std::string query; if(type == replicated){ query = "(drelfdistribute " + relPtr + "\"TMP_DATA\" " + dtype + " (consume (getWorkers " + drelPtr + ")))"; } else if(type == drel::random){ query = "(drelfdistribute " + relPtr + "\"TMP_DATA\" " + dtype + " (size " + drelPtr + ") " + "(consume (getWorkers " + drelPtr + ")))"; } else if( type == drel::hash || type == range || type == spatial2d || type == spatial3d){ //get attribute name for distribution ListExpr attrList = nl->Second( nl->Second(nl->Second(drelType) ) ); int attrPos = nl->IntValue(nl->Second(nl->Third(drelType) ) ); for(int i = 0; i < attrPos; i++){ attrList = nl->Rest(attrList); } std::string attr = nl->ToString( nl->First(nl->First(attrList) ) ); query = "(drelfdistribute " + relPtr + "\"TMP_DATA\" " + dtype + " " + attr + " (size " + drelPtr + ") " + "(consume (getWorkers " + drelPtr + ")))"; } Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { cout << "distribution of a stream to d[f]rel failed" << endl; return false; } else { dfrel_tmp = (DFRel*) qRes.addr; } if( !dfrel_tmp || !dfrel_tmp->IsDefined() ){ return false; } return true; } /* ~removeTempObjects~ Removes temporary objects from a given dfrel. */ bool removeTempObjects(DFRel* dfrel_tmp, ListExpr drelType){ std::string dfrelPtr = nl->ToString(DRelHelpers::createPointerList( nl->TwoElemList( listutils::basicSymbol(), nl->Second(drelType) ), dfrel_tmp ) ) ; std::string query = "(deleteRemoteObjects " + dfrelPtr + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { return false; } else { int deletedObjects = ((CcInt*) qRes.addr)->GetValue(); return deletedObjects > 0 ? true : false; } } /* 1.2 Value Mapping ~drelinsert~ */ int drelinsertVM(Word* args, Word& result, int message, Word& local, Supplier s ){ Stream stream(args[0].addr); DRel* drel = (DRel*) args[1].addr; CcInt* port = (CcInt*) args[2].addr; result = qp->ResultStorage(s); DFRel* resultDFRel = (DFRel*)result.addr; //collect all tuples from stream into relation stream.open(); Tuple* tup = stream.request(); Relation* rel = new Relation(tup->GetTupleType()); rel->AppendTuple(tup); tup->DeleteIfAllowed(); while((tup = stream.request()) != 0){ rel->AppendTuple(tup); tup->DeleteIfAllowed(); } stream.close(); //distribute relation similar to drel ListExpr relType = nl->TwoElemList( listutils::basicSymbol (), nl->Second( qp->GetType( qp->GetSon(s,0) ) ) ); ListExpr drelType = qp->GetType( qp->GetSon(s,1) ); DFRel* dfrel_tmp = 0; if( ! distributeSimilarToDRel(rel, relType, drel, drelType, dfrel_tmp) ){ resultDFRel->makeUndefined(); delete dfrel_tmp; delete rel; return 0; } ListExpr arg1ptr = DRelHelpers::createPointerList( nl->TwoElemList( listutils::basicSymbol(), nl->Second(drelType) ), dfrel_tmp ); ListExpr arg2ptr = DRelHelpers::createPointerList( nl->TwoElemList( listutils::basicSymbol(), nl->Second(drelType) ), drel ); std::string query = "(dmap2 " + nl->ToString(arg1ptr) + nl->ToString(arg2ptr) + "\"\" " "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(insert (feed elem1) elem2)) " + boost::to_string( port->GetValue() ) + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFRel->makeUndefined(); } else { DFArray* dfarray = (DFArray*) qRes.addr; if( !dfarray || !dfarray->IsDefined()){ resultDFRel->makeUndefined(); } else { resultDFRel->copyFrom( *dfarray ); resultDFRel->setDistType( drel->getDistType()->copy() ); } delete dfarray; } //delete temporary objects from remote server if( !removeTempObjects(dfrel_tmp, drelType) ){ cout<<"temporary objects not deleted" << endl; } //check pointers delete dfrel_tmp; delete rel; return 0; } /* 1.3 Specification of ~drelinsert~ */ OperatorSpec drelinsertSpec( " stream(tuple(X)) x drel(rel(tuple(X))) x int " "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ drelinsert [_]", "Inserts tuples of the stream into the distributed relation. " "The tuples to insert should not contain the partition " "attributes (Cell, Original). The third argument specifies " "a port number.", "query rel1 feed drel1 drelinsert [1238]" ); /* 1.4 Definition of ~drelinsert~ */ Operator drelinsertOp ( "drelinsert", drelinsertSpec.getStr( ), drelinsertVM, Operator::SimpleSelect, drelinsertTM ); /* 2. Operator ~drelinserttuple~ 2.1 Type Mapping ~drelinserttuple~ */ ListExpr drelinserttupleTM( ListExpr args ){ if(!nl->HasLength(args, 3) ){ return listutils::typeError("wrong number of arguments"); } ListExpr drelType = nl->First( args ); ListExpr attrList = nl->Second( args ); // check for correct types distributionType type; int attr, key; if(!DRel::checkType( drelType, type, attr, key ) ){ return listutils::typeError( "first argument is not a drel"); } if(nl->AtomType( attrList ) != NoAtom){ return listutils::typeError( "second argument must be a list of attributes"); } if(!CcInt::checkType( nl->Third( args ) ) ){ return listutils::typeError( "last argument not of type int"); } // attrList != relType (spatial2d, 3d, replicated) if( type == replicated ) { attrList = ConcatLists( attrList, nl->OneElemList( listutils::basicSymbol() ) ); } else if ( type == spatial2d || type == spatial3d ) { attrList = ConcatLists( attrList, nl->TwoElemList( listutils::basicSymbol(), listutils::basicSymbol() ) ); } ListExpr result = insertTupleTypeMap( nl->TwoElemList( nl->Second( drelType ), attrList ) ); if(!listutils::isTupleStream( result ) ){ return result; } ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ), nl->Third( drelType ) ); //distType return resType; } /* 2.2 Value Mapping ~drelinserttuple~ */ int drelinserttupleVM(Word* args, Word& result, int message, Word& local, Supplier s ){ DRel* drel = (DRel*) args[0].addr; CcInt* port = (CcInt*) args[2].addr; result = qp->ResultStorage(s); DFRel* resultDFRel = (DFRel*)result.addr; ListExpr resTupleType = nl->Second( nl->Second( GetTupleResultType( s ) ) ); ListExpr rest, last, insertType; rest = nl->Second( resTupleType ); insertType = nl->OneElemList(nl->First( rest ) ); last = insertType; rest = nl->Rest( rest ); int i = 1; distributionType type = drel->getDistType()->getDistType(); if(type == replicated) i = 2; else if( type == spatial2d || type == spatial3d ) i = 3; while(nl->ListLength( rest ) > i){ last = nl->Append(last, nl->First( rest ) ); rest = nl->Rest( rest ); } insertType = nl->TwoElemList(nl->First( resTupleType ), insertType); //create a new tuple from the attribute list Tuple* insertTuple = new Tuple( new TupleType( insertType ) ); Supplier supplier = args[1].addr; Supplier supplier_i; Word attrValue; Attribute* attr; for(int i = 0; i < insertTuple->GetNoAttributes(); i++){ supplier_i = qp->GetSupplier(supplier, i); qp->Request(supplier_i, attrValue); attr = (Attribute*) attrValue.addr; insertTuple->PutAttribute(i, attr->Clone() ); } Relation* rel = new Relation( insertTuple->GetTupleType() ); rel->AppendTuple( insertTuple ); insertTuple->DeleteIfAllowed(); //distribute relation similar to drel ListExpr drelType = qp->GetType( qp->GetSon(s,0) ); ListExpr attrs = DRelHelpers::removePartitionAttributes( nl->Second( nl->Second( nl->Second( drelType ) ) ), type ); ListExpr relType = nl->TwoElemList( listutils::basicSymbol (), nl->TwoElemList( listutils::basicSymbol(), attrs ) ); DFRel* dfrel_tmp = 0; if( ! distributeSimilarToDRel(rel, relType, drel, drelType, dfrel_tmp) ){ resultDFRel->makeUndefined(); delete dfrel_tmp; delete rel; return 0; } ListExpr arg1ptr = DRelHelpers::createPointerList( nl->TwoElemList( listutils::basicSymbol(), nl->Second(drelType) ), dfrel_tmp ); ListExpr arg2ptr = DRelHelpers::createPointerList( nl->TwoElemList( listutils::basicSymbol(), nl->Second(drelType) ), drel ); std::string query = "(dmap2 " + nl->ToString(arg1ptr) + nl->ToString(arg2ptr) + "\"\" " "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(insert (feed elem1) elem2)) " + boost::to_string( port->GetValue() ) + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFRel->makeUndefined(); } else { DFArray* dfarray = (DFArray*) qRes.addr; if( !dfarray || !dfarray->IsDefined()){ resultDFRel->makeUndefined(); } else { resultDFRel->copyFrom( *dfarray ); resultDFRel->setDistType( drel->getDistType()->copy() ); } delete dfarray; } //delete temporary objects from remote server if( !removeTempObjects(dfrel_tmp, drelType) ){ cout<<"temporary objects not deleted" << endl; } //check pointers delete dfrel_tmp; delete rel; return 0; } /* 2.3 Specification of ~drelinserttuple~ */ OperatorSpec drelinserttupleSpec( " drel(rel(tuple(X))) x [t1 ... tn] x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ drelinserttuple [_; _]", "Inserts a new tuple with the values from " "the second argument list into the distributed relation. " "The third argument specifies a port number. ", "query drel1 drelinserttuple [\"Z\", 10 ; 1238]" ); /* 2.4 Definition of ~drelinserttuple~ */ Operator drelinserttupleOp ( "drelinserttuple", drelinserttupleSpec.getStr( ), drelinserttupleVM, Operator::SimpleSelect, drelinserttupleTM ); /* 3. Operators ~dreldelete~, ~drelupdate~, ~dreldeletebyid~, ~drelupdatebyid~ 3.1 Type Mapping functions 3.1.1 Type Mapping of ~dreldelete~ */ ListExpr dreldeleteTM ( ListExpr args ){ if(!nl->HasLength(args, 3)){ return listutils::typeError("wrong number of arguments"); } //check for correct types ListExpr drelType1 = nl->First(args); if( !DRel::checkType( drelType1 ) && !DFRel::checkType( drelType1 ) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr drelType2 = nl->Second(args); if( !DRel::checkType( drelType2 ) ){ return listutils::typeError( "second argument is not a drel"); } ListExpr port = nl->Third(args); if( !CcInt::checkType( port ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr result = insertDeleteRelTypeMap<0>( nl->TwoElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second(nl->Second( drelType1 ) ) ), nl->Second( drelType2 ) ) ); if(!listutils::isTupleStream( result ) ){ return result; } // create function type for dmap2 operator std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(deletesearch (feed elem1) elem2)) "; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ), nl->Third( drelType2 ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 3.1.2 Type Mapping of ~drelupdate~ */ ListExpr drelupdateTM ( ListExpr args ){ if(!nl->HasLength(args, 4)){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists(args) ){ return listutils::typeError("internal Error"); } // check for correct types ListExpr drelType1 = nl->First( nl->First(args) ); if( !DRel::checkType( drelType1 ) && !DFRel::checkType( drelType1 ) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr drelType2 = nl->First( nl->Second(args) ); if( !DRel::checkType( drelType2 ) ){ return listutils::typeError( "second argument is not a drel"); } ListExpr mapList = nl->First( nl->Third(args) ); ListExpr funList = nl->Second( nl->Third(args) ); ListExpr tempfun; ListExpr funList_new = nl->TheEmptyList( ); while( !nl->IsEmpty( funList ) ){ if( !nl->HasLength( nl->First( funList ), 2 ) ){ return listutils::typeError( "internal error" ); } if( !DRelHelpers::replaceDRELFUNARG( nl->Second (nl->First( funList ) ), "TUPLE", tempfun ) ) { return listutils::typeError( "error in the function format" ); } if( nl->IsEmpty( funList_new ) ){ funList_new = nl->OneElemList( nl->TwoElemList( nl->First(nl->First( funList ) ), tempfun ) ); } else { funList_new = listutils::concat( funList_new, nl->OneElemList( nl->TwoElemList( nl->First(nl->First( funList ) ), tempfun ) ) ); } funList = nl->Rest( funList ); } ListExpr port = nl->Fourth(args); if( !CcInt::checkType(nl->First( port ) ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr result = updateSearchRelTypeMap( nl->ThreeElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( drelType1 ) ) ), nl->Second( drelType2 ), mapList ) ); if( !nl->HasLength(result, 3) ){ return result; } // create function for dmap2 operator std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(updatesearch (feed elem1) elem2 " + nl->ToString(funList_new) + ")) "; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third( result ) ) ), nl->Third( drelType2 ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 3.1.3 Type Mapping of ~dreldeletebyid~ */ ListExpr dreldeletebyidTM ( ListExpr args ){ if(!nl->HasLength(args, 4)){ return listutils::typeError("wrong number of arguments"); } // check for correct types ListExpr arg1Type = nl->First(args); if( !DRel::checkType( arg1Type ) && !DFRel::checkType( arg1Type ) && !DArray::checkType( arg1Type ) && !DFArray::checkType( arg1Type ) ){ return listutils::typeError( "first argument is not a d[f]rel or a d[f]array"); } if( !Relation::checkType( nl->Second( arg1Type ) ) ){ return listutils::typeError( "wrong subtype of the first argument"); } ListExpr drelType2 = nl->Second(args); if( !DRel::checkType( drelType2 ) ){ return listutils::typeError( "second argument is not a drel"); } ListExpr attrName = nl->Third(args); if(!listutils::isSymbol( attrName ) ){ return listutils::typeError( "third argument must be an attribute name" ); } ListExpr port = nl->Fourth( args ); if(!CcInt::checkType( port ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr result = deletebyid4TM( nl->ThreeElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( arg1Type ) ) ), nl->Second( drelType2 ), attrName ) ); if( !nl->HasLength(result, 3) ){ return result; } // create function for dmap2 operator std::string attr = nl->ToString(attrName); std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(deletebyid4 (feed elem1) elem2 " + attr + ")) "; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third( result) ) ), nl->Third( drelType2 ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 3.1.4 Type Mapping of ~drelupdatebyid~ */ ListExpr drelupdatebyidTM ( ListExpr args ){ if(!nl->HasLength(args, 5)){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists(args) ){ return listutils::typeError("internal Error"); } // check for correct types ListExpr arg1Type = nl->First( nl->First(args) ); if( !DRel::checkType( arg1Type ) && !DFRel::checkType( arg1Type ) && !DArray::checkType( arg1Type ) && !DFArray::checkType( arg1Type ) ){ return listutils::typeError( "first argument is not a d[f]rel or a d[f]array"); } if( !Relation::checkType( nl->Second( arg1Type ) ) ){ return listutils::typeError( "wrong subtype of the first argument"); } ListExpr drelType2 = nl->First( nl->Second(args) ); if( !DRel::checkType( drelType2 ) ){ return listutils::typeError( "second argument is not a drel"); } ListExpr attrName = nl->Second ( nl->Third( args ) ); if(!listutils::isSymbol( attrName ) ){ return listutils::typeError( "third argument must be an attribute name" ); } ListExpr mapList = nl->First( nl->Fourth(args) ); ListExpr funList = nl->Second( nl->Fourth(args) ); ListExpr tempfun; ListExpr fundef; ListExpr funList_new = nl->TheEmptyList( ); while( !nl->IsEmpty( funList ) ){ if( !nl->HasLength( nl->First( funList ), 2 ) ){ return listutils::typeError( "internal error" ); } fundef = nl->Second( nl->First( funList ) ); if( !nl->HasLength( fundef, 4 ) || !nl->HasLength( nl->Second( fundef ), 2 ) || !nl->HasLength( nl->Third( fundef ), 2 ) || !listutils::isSymbol( nl->Second ( nl->Second( fundef ) ) ) || !listutils::isSymbol( nl->Second ( nl->Third( fundef ) ) ) ) { return listutils::typeError( "error in the function format" ); } tempfun = nl->FourElemList( nl->First( fundef ), nl->TwoElemList( nl->First ( nl->Second( fundef ) ), nl->SymbolAtom( "TUPLE" ) ), nl->TwoElemList( nl->First ( nl->Third( fundef ) ), nl->SymbolAtom( "TUPLE2" ) ), nl->Fourth( fundef ) ); if( nl->IsEmpty( funList_new ) ){ funList_new = nl->OneElemList( nl->TwoElemList( nl->First(nl->First( funList ) ), tempfun ) ); } else { funList_new = listutils::concat( funList_new, nl->OneElemList( nl->TwoElemList( nl->First(nl->First( funList ) ), tempfun ) ) ); } funList = nl->Rest( funList ); } ListExpr port = nl->Fifth( args ); if(!CcInt::checkType( nl->First(port) ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr result = updatebyid2TM( nl->FourElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( arg1Type ) ) ), nl->Second( drelType2 ), attrName, mapList ) ); if( !nl->HasLength(result, 3) ){ return result; } // create function for dmap2 operator std::string attr = nl->ToString(attrName); std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(updatebyid2 (feed elem1) elem2 " + attr + " " + nl->ToString(funList_new) + "))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third(result) ) ), nl->Third( drelType2 ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 3.2 Value Mapping function used by ~dreldelete~, ~drelupdate~, ~dreldeletebyid~, ~drelupdatebyid~ operators */ template int dreldmap2VMT(Word* args, Word& result, int message, Word& local, Supplier s ){ int argsNum = qp->GetNoSons( s ); R* arg1 = (R*) args[0].addr; DRel* drel2 = (DRel*) args[1].addr; CcInt* port = (CcInt*) args[argsNum - 2].addr; FText* funText = (FText*) args[argsNum - 1].addr; result = qp->ResultStorage(s); DFRel* resultDFRel = (DFRel*)result.addr; ListExpr arg1ptr; if( DRel::checkType( qp->GetType( qp->GetSon(s,0) ) ) || DFRel::checkType( qp->GetType( qp->GetSon(s,0) ) ) ) { arg1ptr = DRelHelpers::createdrel2darray( qp->GetType( qp->GetSon(s,0) ), arg1 ); } else { arg1ptr = DRelHelpers::createPointerList( qp->GetType( qp->GetSon(s,0) ), arg1 ); } ListExpr arg2ptr = DRelHelpers::createdrel2darray( qp->GetType( qp->GetSon(s,1) ), drel2 ); std::string query = "(dmap2 " + nl->ToString(arg1ptr) + nl->ToString(arg2ptr) + "\"\" " + funText->GetValue() + boost::to_string( port->GetValue() ) + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFRel->makeUndefined(); return 0; } else { DFArray* dfarray = (DFArray*) qRes.addr; if( !dfarray || !dfarray->IsDefined()){ resultDFRel->makeUndefined(); delete dfarray; return 0; } resultDFRel->copyFrom( *dfarray ); resultDFRel->setDistType( drel2->getDistType()->copy() ); delete dfarray; } return 0; } ValueMapping dreldmap2VM[] = { dreldmap2VMT, dreldmap2VMT }; int dreldmap2UpdSelect( ListExpr args ){ return DRel::checkType( nl->First( args ) ) || DArray::checkType( nl->First( args ) ) ? 0 : 1; } /* 3.3 Specifications 3.3.1 Specification of ~dreldelete~ */ OperatorSpec dreldeleteSpec( " d[f]rel(rel(tuple(X))) x drel(rel(tuple(X))) x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ dreldelete [_]", "Deletes tuples from the distributed relation given " "as a second argument. The first distributed relation " "contains tuples to delete. The third argument " "is a port number.", "query drel1 drelfilter[.No > 5] drel1 dreldelete [1238]" ); /* 3.3.2 Specification of ~drelupdate~ */ OperatorSpec drelupdateSpec( " d[f]rel(rel(tuple(X))) x drel(rel(tuple(X))) x funlist x int" "-> dfrel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid])))", " _ _ drelupdate [_ ; _]", "Updates tuples in the distributed relation given " "as a second argument by replacing attributes as " "specified in the funlist. The first distributed " "relation contains tuples to update. The fourth argument " "is a port number.", "query drel1 drelfilter[.No > 5] drel1 drelupdate [No: .No + 1; 1238]" ); /* 3.3.3 Specification of ~dreldeletebyid~ */ OperatorSpec dreldeletebyidSpec( " d[f]rel(rel(tuple(X))) x drel(rel(tuple(Y))) x attr x int" "-> dfrel(rel(tuple(Y@[TID:tid]))), " " d[f]array(rel(tuple(X))) x drel(rel(tuple(Y))) x attr x int" "-> dfrel(rel(tuple(Y@[TID:tid]))) ", " _ _ dreldeletebyid [_, _]", "Deletes tuples from the distributed relation given " "as a second argument. The first argument contains " "tuples to delete and specifies tupleids by the attr " "argument. It can be of types d[f]array or d[f]rel. " "The last argument is a port number.", "query drel1 drelfilteraddid[.No > 5] drel1 dreldeletebyid[TID, 1238]" ); /* 3.3.4 Specification of ~drelupdatebyid~ */ OperatorSpec drelupdatebyidSpec( " d[f]rel(rel(tuple(X))) x drel(rel(tuple(Y))) x attr x funlist x int" "-> dfrel(rel(tuple(X))), " " d[f]array(rel(tuple(X))) x drel(rel(tuple(Y))) x attr x funlist x int" "-> dfrel(rel(tuple(X)))", " _ _ drelupdatebyid [_ ; _; _]", "Updates tuples in the distributed relation given " "as a second argument. The first argument contains " "tuples to update and specifies tupleid by the attr " "argument. It can be of types d[f]array or d[f]rel. " "The functions may use parts from the first argument " "(dot notation) or from the second drel (double dot notation).", "query drel1 dreladdid drel1 drelupdatebyid [TID; No: ..No + 1; 1238]" ); /* 3.4 Definitions 3.4.1 Definition of ~dreldelete~ */ Operator dreldeleteOp ( "dreldelete", dreldeleteSpec.getStr( ), 2, dreldmap2VM, dreldmap2UpdSelect, dreldeleteTM ); /* 3.4.2 Definition of ~drelupdate~ */ Operator drelupdateOp ( "drelupdate", drelupdateSpec.getStr( ), 2, dreldmap2VM, dreldmap2UpdSelect, drelupdateTM ); /* 3.4.3 Definition of ~dreldeletebyid~ */ Operator dreldeletebyidOp ( "dreldeletebyid", dreldeletebyidSpec.getStr( ), 2, dreldmap2VM, dreldmap2UpdSelect, dreldeletebyidTM ); /* 3.4.4 Definition of ~drelupdatebyid~ */ Operator drelupdatebyidOp ( "drelupdatebyid", drelupdatebyidSpec.getStr( ), 2, dreldmap2VM, dreldmap2UpdSelect, drelupdatebyidTM ); /* 4. Operators ~drelinsertrtree~, ~dreldeletertree~, ~drelupdatertree~, ~drelinsertbtree~, ~dreldeletebtree~, ~drelupdatebtree~ 4.1 Type Mapping function for update distributed rtree */ ListExpr drelAllUpdatesRTreeTM (ListExpr& args, std::string opName ){ if(!nl->HasLength(args, 4) ){ return listutils::typeError("wrong number of arguments"); } ListExpr drelType = nl->First(args); if( !DRel::checkType( drelType ) && !DFRel::checkType( drelType ) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr darrayRTreeType = nl->Second(args); if( !DArray::checkType( darrayRTreeType ) ){ return listutils::typeError( "second argument is not a darray"); } ListExpr attrName = nl->Third(args); if(!listutils::isSymbol( attrName ) ){ return listutils::typeError( "third argument must be an attribute name" ); } ListExpr port = nl->Fourth(args); if(!CcInt::checkType( port ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr args2 = nl->ThreeElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second(nl->Second( drelType ) ) ), nl->Second( darrayRTreeType ), attrName ); ListExpr result = allUpdatesRTreeTypeMap(args2, opName); if( !nl->HasLength(result, 3) ){ return result; } //create function for dmap2 operator std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(" + opName + " (feed elem1) elem2 " + nl->ToString(attrName) + "))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third( result ) ) ), nl->Third( drelType ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 4.1.1 Type Mapping of ~drelinsertrtree~ */ ListExpr drelinsertrtreeTM(ListExpr args){ return drelAllUpdatesRTreeTM(args, "insertrtree"); } /* 4.1.2 Type Mapping of ~dreldeletertree~ */ ListExpr dreldeletertreeTM(ListExpr args){ return drelAllUpdatesRTreeTM(args, "deletertree"); } /* 4.1.3 Type Mapping of ~drelupdatertree~ */ ListExpr drelupdatertreeTM(ListExpr args){ return drelAllUpdatesRTreeTM(args, "updatertree"); } /* 4.2 Type Mapping function for update distributed btree */ ListExpr drelAllUpdatesBTreeTM (ListExpr& args, std::string opName ){ if(!nl->HasLength(args, 4) ){ return listutils::typeError("wrong number of arguments"); } // check for correct types ListExpr drelType = nl->First(args); if( !DRel::checkType( drelType ) && !DFRel::checkType( drelType ) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr darrayBTreeType = nl->Second( args ); if( !DArray::checkType( darrayBTreeType ) ){ return listutils::typeError( "second argument is not a darray"); } ListExpr attrName = nl->Third( args ); if( !listutils::isSymbol( attrName ) ){ return listutils::typeError( "third argument must be an attribute name" ); } ListExpr port = nl->Fourth(args); if(!CcInt::checkType( port ) ){ return listutils::typeError( "last argument not of type int"); } ListExpr args2 = nl->ThreeElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second(nl->Second( drelType ) ) ), nl->Second( darrayBTreeType ), attrName ); ListExpr result = allUpdatesBTreeTypeMap(args2, opName); if( !nl->HasLength(result, 3) ){ return result; } //create function for dmap2 operator std::string fun = "(fun (elem1 ARRAYFUNARG1) (elem2 ARRAYFUNARG2) " "(" + opName + " (feed elem1) elem2 " + nl->ToString(attrName) + "))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third( result ) ) ), nl->Third( drelType ) ); ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 4.2.1 Type Mapping of ~drelinsertbtree~ */ ListExpr drelinsertbtreeTM(ListExpr args){ return drelAllUpdatesBTreeTM(args, "insertbtree"); } /* 4.2.2 Type Mapping of ~dreldeletebtree~ */ ListExpr dreldeletebtreeTM(ListExpr args){ return drelAllUpdatesBTreeTM(args, "deletebtree"); } /* 4.2.3 Type Mapping of ~drelupdatebtree~ */ ListExpr drelupdatebtreeTM(ListExpr args){ return drelAllUpdatesBTreeTM(args, "updatebtree"); } /* 4.3 Value Mapping function used by ~drelinsertrtree~, ~dreldeletertree~, ~drelupdatertree~, ~drelinsertbtree~, ~dreldeletebtree~, ~drelupdatebtree~ operators */ template int dreldmap2IVMT(Word* args, Word& result, int message, Word& local, Supplier s ){ int argsNum = qp->GetNoSons( s ); R* drel = (R*) args[0].addr; DArray* da = (DArray*) args[1].addr; CcInt* port = (CcInt*) args[argsNum - 2].addr; FText* funText = (FText*) args[argsNum - 1].addr; result = qp->ResultStorage(s); DFRel* resultDFRel = (DFRel*)result.addr; ListExpr arg1ptr = DRelHelpers::createdrel2darray( qp->GetType( qp->GetSon(s,0) ), drel ); ListExpr arg2ptr = DRelHelpers::createPointerList( qp->GetType( qp->GetSon(s,1) ), da ); std::string query = "(dmap2 " + nl->ToString(arg1ptr) + nl->ToString(arg2ptr) + "\"\" " + funText->GetValue() + boost::to_string( port->GetValue() ) + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFRel->makeUndefined(); return 0; } else { DFArray* dfarray = (DFArray*) qRes.addr; if( !dfarray || !dfarray->IsDefined()){ resultDFRel->makeUndefined(); delete dfarray; return 0; } resultDFRel->copyFrom( *dfarray ); resultDFRel->setDistType( drel->getDistType()->copy() ); delete dfarray; } return 0; } ValueMapping dreldmap2IVM[] = { dreldmap2IVMT, dreldmap2IVMT }; int dreldmap2IUpdSelect( ListExpr args ){ return DRel::checkType( nl->First( args ) ) ? 0 : 1; } /* 4.4 Specifications 4.4.1 Specification of ~drelinsertrtree~ */ OperatorSpec drelinsertrtreeSpec( " d[f]rel(rel(tuple(X@[TID:tid]))) x da(rtree(tuple(X))) x attr x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ drelinsertrtree [_, _]", "Inserts references of tuples with tupleids into the " "distributed rtree. ", "query drel da_rtree drelinsertrtree [GeoData, 1238]" ); /* 4.4.2 Specification of ~dreldeletertree~ */ OperatorSpec dreldeletertreeSpec( " d[f]rel(rel(tuple(X@[TID:tid]))) x da(rtree(tuple(X))) x attr x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ dreldeletertree [_, _]", "Deletes references of tuples with tupleids from the " "distributed rtree. ", "query drel da_rtree dreldeletertree [GeoData, 1238]" ); /* 4.4.3 Specification of ~drelupdatertree~ */ OperatorSpec drelupdatertreeSpec( " d[f]rel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid]))) x" " da(rtree(tuple(X))) x attr x int " "-> dfrel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid])))", " _ _ drelupdatertree [_, _]", "Updates references of tuples with tupleids in the " "distributed rtree.", "query drel da_rtree drelupdatertree [GeoData, 1238]" ); /* 4.4.4 Specification of ~drelinsertbtree~ */ OperatorSpec drelinsertbtreeSpec( " d[f]rel(rel(tuple(X@[TID:tid]))) x da(btree(tuple(X))) x attr x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ drelinsertbtree [_, _]", "Inserts references of tuples with tupleids into the " "distributed btree. ", "query drel da_btree drelinsertbtree [BevT, 1238]" ); /* 4.4.5 Specification of ~dreldeletebtree~ */ OperatorSpec dreldeletebtreeSpec( " d[f]rel(rel(tuple(X@[TID:tid]))) x da(btree(tuple(X))) x attr x int" "-> dfrel(rel(tuple(X@[TID:tid])))", " _ _ dreldeletebtree [_, _]", "Deletes references of tuples with tupleids from the " "distributed btree. ", "query drel da_btree dreldeletebtree [BevT, 1238]" ); /* 4.4.6 Specification of ~drelupdatebtree~ */ OperatorSpec drelupdatebtreeSpec( " d[f]rel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid]))) x" " da(btree(tuple(X))) x attr x int " "-> dfrel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid])))", " _ _ drelupdatebtree [_, _]", "Updates references of tuples with tupleids in the " "distributed btree.", "query drel da_btree drelupdatebtree [BevT, 1238]" ); /* 4.5 Definitions 4.5.1 Definition of ~drelinsertrtree~ */ Operator drelinsertrtreeOp ( "drelinsertrtree", drelinsertrtreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, drelinsertrtreeTM ); /* 4.5.2 Definition of ~dreldeletertree~ */ Operator dreldeletertreeOp ( "dreldeletertree", dreldeletertreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, dreldeletertreeTM ); /* 4.5.3 Definition of ~drelupdatertree~ */ Operator drelupdatertreeOp ( "drelupdatertree", drelupdatertreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, drelupdatertreeTM ); /* 4.5.4 Definition of ~drelinsertbtree~ */ Operator drelinsertbtreeOp ( "drelinsertbtree", drelinsertbtreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, drelinsertbtreeTM ); /* 4.5.5 Definition of ~dreldeletebtree~ */ Operator dreldeletebtreeOp ( "dreldeletebtree", dreldeletebtreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, dreldeletebtreeTM ); /* 4.5.6 Definition of ~drelupdatebtree~ */ Operator drelupdatebtreeOp ( "drelupdatebtree", drelupdatebtreeSpec.getStr( ), 2, dreldmap2IVM, dreldmap2IUpdSelect, drelupdatebtreeTM ); /* 5. Operators ~dreladdid~, ~drelfilteraddid~, ~drelfilterdelete~, ~drelfilterupdate~ 5.1 Type Mapping functions 5.1.1 Type Mapping of ~dreladdid~ */ ListExpr dreladdidTM ( ListExpr args ){ if(!nl->HasLength(args, 1) ){ return listutils::typeError("wrong number of arguments"); } ListExpr drelType = nl->First(args); if( !DRel::checkType( drelType ) && !DFRel::checkType( drelType ) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr result = appendIdentifierTypeMap( nl->OneElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( drelType ) ) ) ) ); if(!listutils::isTupleStream( result ) ){ return result; } // create function for dmap operator std::string fun ="(fun (elem1 ARRAYFUNARG1) (addid (feed elem1)))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ), nl->Third( drelType ) ); //distType ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 5.1.2 Type Mapping of ~drelfilteraddid~ */ ListExpr drelfilteraddidTM( ListExpr args ){ if(!nl->HasLength(args,2)){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists(args) ){ return listutils::typeError("internal error"); } // check for correct types ListExpr drelType, relType, distType, drelValue; if(!DRelHelpers::isDRelDescr(nl->First(args), drelType, relType, distType, drelValue) ){ return listutils::typeError( "first argument is not a d[f]rel"); } ListExpr fun, map; if( !DRelHelpers::replaceDRELFUNARG( nl->Second( args ), "STREAMELEM", fun, map) ){ return listutils::typeError( "error in the function format"); } ListExpr filterRes = OperatorFilter::FilterTypeMap( nl->TwoElemList( nl->TwoElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( relType ) ), nl->TwoElemList( nl->SymbolAtom("feed"), //dummy drelValue ) ), nl->TwoElemList( map, fun ) ) ); if(!listutils::isTupleStream( filterRes ) ){ return filterRes; } ListExpr result = appendIdentifierTypeMap( nl->OneElemList( filterRes ) ); if(!listutils::isTupleStream( result ) ){ return result; } // create function for dmap operator std::string funText = "(fun (elem1 ARRAYFUNARG1) (addid (filter " "(feed elem1) " + nl->ToString(fun) + ")))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ), distType); ListExpr append = nl->OneElemList( nl->TextAtom( funText ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 5.1.3 Type Mapping of ~drelfilterdelete~ */ ListExpr drelfilterdeleteTM( ListExpr args ){ if(!nl->HasLength(args,2)){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists(args) ){ return listutils::typeError("internal error"); } // check for correct types ListExpr drelType = nl->First( nl->First( args ) ); ListExpr drelValue = nl->Second( nl->First( args ) ); if( !DRel::checkType( drelType ) ){ return listutils::typeError( "first argument is not a drel"); // ONLY DREL } ListExpr fun, map; if( !DRelHelpers::replaceDRELFUNARG( nl->Second( args ), "STREAMELEM", fun, map) ){ return listutils::typeError( "error in the function format"); } ListExpr filterRes = OperatorFilter::FilterTypeMap( nl->TwoElemList( nl->TwoElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( drelType ) ) ), nl->TwoElemList( nl->SymbolAtom("feed"), //dummy drelValue ) ), nl->TwoElemList( map, fun ) ) ); if(!listutils::isTupleStream( filterRes ) ){ return filterRes; } ListExpr result = insertDeleteRelTypeMap<0>( nl->TwoElemList( filterRes, nl->Second( drelType ) ) ); if(!listutils::isTupleStream( result ) ){ return result; } // create function for dmap operator std::string funText = "(fun (elem1 ARRAYFUNARG1) (deletedirect " "(filter (feed elem1) " + nl->ToString(fun) + ") elem1))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ), nl->Third( drelType ) ); // distType ListExpr append = nl->OneElemList( nl->TextAtom( funText ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 5.1.4 Type Mapping of ~drelfilterupdate~ */ ListExpr drelfilterupdateTM( ListExpr args ){ if(!nl->HasLength(args,3)){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists(args) ){ return listutils::typeError("internal error"); } // check for correct types ListExpr drelType = nl->First( nl->First( args ) ); ListExpr drelValue = nl->Second( nl->First( args ) ); if( !DRel::checkType( drelType ) ){ return listutils::typeError( "first argument is not a drel"); // ONLY DREL } ListExpr filter_fun, filter_map; if( !DRelHelpers::replaceDRELFUNARG( nl->Second( args ), "STREAMELEM", filter_fun, filter_map) ){ return listutils::typeError( "error in the function format"); } ListExpr filterRes = OperatorFilter::FilterTypeMap( nl->TwoElemList( nl->TwoElemList( nl->TwoElemList( listutils::basicSymbol >(), nl->Second( nl->Second( drelType ) ) ), nl->TwoElemList( nl->SymbolAtom("feed"), //dummy drelValue ) ), nl->TwoElemList( filter_map, filter_fun ) ) ); if(!listutils::isTupleStream( filterRes ) ){ return filterRes; } ListExpr update_mapList = nl->First( nl->Third(args) ); ListExpr update_funList = nl->Second( nl->Third(args) ); ListExpr tempfun; ListExpr funList_new = nl->TheEmptyList( ); while( !nl->IsEmpty( update_funList ) ){ if( !nl->HasLength( nl->First( update_funList ), 2 ) ){ return listutils::typeError( "internal error" ); } if( !DRelHelpers::replaceDRELFUNARG( nl->Second (nl->First( update_funList ) ), "TUPLE", tempfun ) ) { return listutils::typeError( "error in the function format" ); } if( nl->IsEmpty( funList_new ) ){ funList_new = nl->OneElemList( nl->TwoElemList( nl->First(nl->First( update_funList ) ), tempfun ) ); } else { funList_new = listutils::concat( funList_new, nl->OneElemList( nl->TwoElemList( nl->First(nl->First( update_funList ) ), tempfun ) ) ); } update_funList = nl->Rest( update_funList ); } ListExpr result = updateDirectRelTypeMap( nl->ThreeElemList( filterRes, nl->Second( drelType ), // relType update_mapList ) ); if( !nl->HasLength(result, 3) ){ return result; } // create function for dmap operator std::string funText = "(fun (elem1 ARRAYFUNARG1) (updatedirect " "(filter (feed elem1) " + nl->ToString(filter_fun) + ") elem1 " + nl->ToString(funList_new) + "))"; ListExpr resType = nl->ThreeElemList( listutils::basicSymbol(), nl->TwoElemList( listutils::basicSymbol(), nl->Second( nl->Third( result ) ) ), nl->Third( drelType ) ); //distType ListExpr append = nl->OneElemList( nl->TextAtom( funText ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 5.2 Value Mapping function used by ~dreladdid~, ~drelfilteraddid~, ~drelfilterdelete~, ~drelfilterupdate~ operators */ template int dreldmapVMT(Word* args, Word& result, int message, Word& local, Supplier s ){ int argsNum = qp->GetNoSons( s ); R* drel = (R*) args[0].addr; FText* funText = (FText*) args[argsNum - 1].addr; result = qp->ResultStorage(s); DFRel* resultDFRel = (DFRel*)result.addr; ListExpr drelptr = DRelHelpers::createdrel2darray (qp->GetType( qp->GetSon(s, 0) ), drel); std::string query = "(dmap " + nl->ToString(drelptr) + "\"\" " + funText->GetValue() + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFRel->makeUndefined(); return 0; } else { DFArray* dfarray = (DFArray*) qRes.addr; if( !dfarray || !dfarray->IsDefined()){ resultDFRel->makeUndefined(); delete dfarray; return 0; } resultDFRel->copyFrom( *dfarray ); resultDFRel->setDistType( drel->getDistType()->copy() ); delete dfarray; } return 0; } ValueMapping dreldmapVM[] = { dreldmapVMT, dreldmapVMT }; int dreldmapUpdSelect( ListExpr args ){ return DRel::checkType( nl->First( args ) ) ? 0 : 1; } /* 5.3 Specifications 5.3.1 Specification of ~dreladdid~ */ OperatorSpec dreladdidSpec( " d[f]rel(rel(tuple(X))) -> dfrel(rel(tuple(X@[TID:tid])))", " _ dreladdid", "Appends tupleid attribute to each tuple of the " "distributed relation. Must be applied directly " "to the distributed relation, because other " "operators may corrupt tupleids.", "query drel1 dreladdid head[5] drel1 dreldeletebyid[TID, 1238]" ); /* 5.3.2 Specification of ~drelfilteraddid~ */ OperatorSpec drelfilteraddidSpec( " d[f]rel(rel(tuple(X))) x fun -> dfrel(rel(tuple(X@[TID:tid])))", " _ drelfilteraddid [_]", "Only tuples, fulfilling a certain condition are selected, " "extended with the TID attribute and passed to the output " "distributed relation.", "query drel1 drelfilteraddid [.No > 5] dreldeletebyid[TID, 1238]" ); /* 5.3.3 Specification of ~drelfilterdelete~ */ OperatorSpec drelfilterdeleteSpec( "drel(rel(tuple(X))) x fun -> dfrel(rel(tuple(X@[TID:tid])))", " _ drelfilterdelete [_]", "Only tuples, fulfilling a certain condition are selected " "and deleted from the distributed relation. The output " "distributed relation contains deleted tuples extended " "with the TID attribute. ", "query drel1 drelfilterdelete[.No > 5]" ); /* 5.3.4 Specification of ~drelfilterupdate~ */ OperatorSpec drelfilterupdateSpec( " drel(rel(tuple(X))) x fun x funlist -> " " dfrel(rel(tuple(X@[X1_old t1]@...[Xn_old tn]@[TID:tid])))", " _ drelfilterupdate [filter_fun; update_funlist]", "Only tuples, fulfilling a certain condition (second argument) " "are selected and updated by replacing attributes as specified " "in the funlist (third argument). The output " "distributed relation contains updated tuples extended " "with old attribute values and TID attribute. ", "query drel1 drelfilterupdate[.No > 5; No: .No + 1]" ); /* 5.4 Definitions 5.4.1 Definition of ~dreladdid~ */ Operator dreladdidOp ( "dreladdid", dreladdidSpec.getStr( ), 2, dreldmapVM, dreldmapUpdSelect, dreladdidTM ); /* 5.4.2 Definition of ~drelfilteraddid~ */ Operator drelfilteraddidOp ( "drelfilteraddid", drelfilteraddidSpec.getStr( ), 2, dreldmapVM, dreldmapUpdSelect, drelfilteraddidTM ); /* 5.4.3 Definition of ~drelfilterdelete~ */ Operator drelfilterdeleteOp ( "drelfilterdelete", drelfilterdeleteSpec.getStr( ), 2, dreldmapVM, dreldmapUpdSelect, drelfilterdeleteTM ); /* 5.4.4 Definition of ~drelfilterupdate~ */ Operator drelfilterupdateOp ( "drelfilterupdate", drelfilterupdateSpec.getStr( ), 2, dreldmapVM, dreldmapUpdSelect, drelfilterupdateTM ); /* 6. Operators ~drelexactmatchS~, ~drelrangeS~, ~drelwindowintersectsS~ 6.1 Type Mapping functions 6.1.1 Type Mapping of ~drelexactmatchS~, ~drelrangeS~ */ //RANGE 2, EXACTMATCH 3 template ListExpr drelindexquerySTM (ListExpr args){ //check number of arguments 2/3 if( !nl->HasLength( args, 2 ) && !nl->HasLength( args, 3 ) ){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists( args ) ){ return listutils::typeError("internal error"); } ListExpr darrayBTreeType = nl->First( nl->First( args ) ); if( !DArray::checkType( darrayBTreeType ) ){ return listutils::typeError( "first argument is not a darray"); } ListExpr args2; if( operatorId == 2 ){ args2 = nl->ThreeElemList( nl->Second( darrayBTreeType ), nl->First( nl->Second( args ) ), nl->First( nl->Third( args ) ) ); } else { args2 = nl->TwoElemList( nl->Second( darrayBTreeType ), nl->First( nl->Second( args ) ) ); } ListExpr result = IndexQuerySTypeMap( args2 ); if(!listutils::isTupleStream( result ) ){ return result; } ListExpr resType = nl->TwoElemList( listutils::basicSymbol( ), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ) ); std::string funText; if( operatorId == 2 ){ funText = "(fun (elem1 ARRAYFUNARG1) (rangeS elem1 " + nl->ToString( nl->Second( nl->Second( args ) ) ) + " " + nl->ToString( nl->Second( nl->Third( args ) ) ) + ")) "; } else { funText = "(fun (elem1 ARRAYFUNARG1) (exactmatchS elem1 " + nl->ToString( nl->Second( nl->Second( args ) ) ) + ")) "; } ListExpr append = nl->OneElemList( nl->TextAtom( funText ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 6.1.2 Type Mapping of ~drelwindowintersectsS~ */ ListExpr drelwindowintersectsSTM (ListExpr args){ if( !nl->HasLength( args, 2 ) ){ return listutils::typeError("wrong number of arguments"); } if(!DRelHelpers::isListOfTwoElemLists( args ) ){ return listutils::typeError("internal error"); } ListExpr darrayRTreeType = nl->First( nl->First( args ) ); if( !DArray::checkType( darrayRTreeType ) ){ return listutils::typeError( "first argument is not a darray"); } ListExpr result = WindowIntersectsSTypeMap( nl->TwoElemList( nl->Second( darrayRTreeType ), nl->First( nl->Second( args ) ) ) ); if(!listutils::isTupleStream( result ) ){ return result; } ListExpr resType = nl->TwoElemList( listutils::basicSymbol( ), nl->TwoElemList( listutils::basicSymbol(), nl->Second( result ) ) ); std::string fun = "(fun (elem1 ARRAYFUNARG1) (windowintersectsS elem1 " + nl->ToString( nl->Second( nl->Second( args ) ) ) + ")) "; ListExpr append = nl->OneElemList( nl->TextAtom( fun ) ); return nl->ThreeElemList( nl->SymbolAtom(Symbols::APPEND()), append, resType); } /* 6.2 Value Mapping function used by ~drelexactmatchS~, ~drelrangeS~, ~drelwindowintersectsS~ operators */ template int dreldmapSVMT(Word* args, Word& result, int message, Word& local, Supplier s ){ int argsNum = qp->GetNoSons( s ); A* darray = (A*) args[0].addr; FText* funText = (FText*) args[argsNum - 1].addr; result = qp->ResultStorage(s); DFArray* resultDFArray = (DFArray*)result.addr; ListExpr arg1ptr = DRelHelpers::createPointerList (qp->GetType( qp->GetSon(s, 0) ), darray); std::string query = "(dmap " + nl->ToString( arg1ptr ) + "\"\" " + funText->GetValue() + ")"; Word qRes; if( !QueryProcessor::ExecuteQuery( query, qRes ) ) { resultDFArray->makeUndefined(); return 0; } else { resultDFArray = (DFArray*) qRes.addr; result.setAddr(resultDFArray); } return 0; } ValueMapping dreldmapSVM[] = { dreldmapSVMT, dreldmapSVMT }; int dreldmapSUpdSelect( ListExpr args ){ return DArray::checkType( nl->First( args ) ) ? 0 : 1; } /* 6.3 Specifications 6.3.1 Specification of ~drelexactmatchS~ */ OperatorSpec drelexactmatchSSpec( " da(btree(tuple(X))) x ti -> dfarray(rel(tuple(Id tid)))", " _ drelexactmatchS [_]", "Uses the given distributed btree to find all tuple " "identifiers where the key matches argument value ti. ", "query da_btree drelexactmatchS [10]" ); /* 6.3.2 Specification of ~drelrangeS~ */ OperatorSpec drelrangeSSpec( " da(btree(tuple(X))) x ti x ti-> dfarray(rel(tuple(Id tid)))", " _ drelrangeS [_, _]", "Uses the given distributed btree to find all tuple " "identifiers where the key is between argument values ti. ", "query da_btree drelrangeS [5, 10]" ); /* 6.3.3 Specification of ~drelwindowintersectsS~ */ OperatorSpec drelwindowintersectsSSpec( " da(rtree(tuple(X))) x ti -> dfarray(rel(tuple(Id tid)))", " _ drelwindowintersectsS [_]", "Uses the given distributed rtree to find all tuple " "identifiers whose bounding box intersects with " "ti bounding box. The argument value ti can be in " "{rect} or SPATIALD, where d in {2, 3, 4, 8}.", "query da_rtree drelwindowintersectsS [ bbox(thecenter) ]" ); /* 6.4 Definitions 6.4.1 Definition of ~drelexactmatchS~ */ Operator drelexactmatchSOp ( "drelexactmatchS", drelexactmatchSSpec.getStr( ), 2, dreldmapSVM, dreldmapSUpdSelect, drelindexquerySTM<3> ); /* 6.4.2 Definition of ~drelrangeS~ */ Operator drelrangeSOp ( "drelrangeS", drelrangeSSpec.getStr( ), 2, dreldmapSVM, dreldmapSUpdSelect, drelindexquerySTM<2> ); /* 6.4.3 Definition of ~drelwindowintersectsS~ */ Operator drelwindowintersectsSOp ( "drelwindowintersectsS", drelwindowintersectsSSpec.getStr( ), 2, dreldmapSVM, dreldmapSUpdSelect, drelwindowintersectsSTM ); class DistributedUpdateAlgebra : public Algebra{ public: DistributedUpdateAlgebra() : Algebra(){ AddOperator(&drelinsertOp); AddOperator(&drelinserttupleOp); AddOperator(&dreldeleteOp); AddOperator(&drelupdateOp); drelupdateOp.SetUsesArgsInTypeMapping( ); AddOperator(&dreldeletebyidOp); AddOperator(&drelupdatebyidOp); drelupdatebyidOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelinsertrtreeOp); AddOperator(&dreldeletertreeOp); AddOperator(&drelupdatertreeOp); AddOperator(&drelinsertbtreeOp); AddOperator(&dreldeletebtreeOp); AddOperator(&drelupdatebtreeOp); AddOperator(&dreladdidOp); AddOperator(&drelfilteraddidOp); drelfilteraddidOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelfilterdeleteOp); drelfilterdeleteOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelfilterupdateOp); drelfilterupdateOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelexactmatchSOp); drelexactmatchSOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelrangeSOp); drelrangeSOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelwindowintersectsSOp); drelwindowintersectsSOp.SetUsesArgsInTypeMapping( ); AddOperator(&drelspatialjoinOp); drelspatialjoinOp.SetUsesArgsInTypeMapping( ); } }; } //end of namespace drelupdate extern "C" Algebra* InitializeDistributedUpdateAlgebra( NestedList* nlRef, QueryProcessor* qpRef ) { return new drelupdate::DistributedUpdateAlgebra (); }