Files
secondo/Algebras/Relation-C++/OperatorFeedProject.cpp
2026-01-23 17:03:45 +08:00

217 lines
5.0 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2016,
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 "OperatorFeedProject.h"
#include "Algebra.h"
#include "Symbols.h"
#include "Progress.h"
#include "RelationAlgebra.h"
#include "Stream.h"
#ifdef USE_PROGRESS
#include "../CostEstimation/RelationAlgebraCostEstimation.h"
#endif
using namespace std;
#ifdef USE_PROGRESS
ListExpr OperatorFeedProject::feedproject_tm(ListExpr args)
{
if(!nl->HasLength(args,2)){
return listutils::typeError("rel(tuple(X)) x attrlist expected");
}
ListExpr rel = nl->First(args);
ListExpr attrList = nl->Second(args);
if(!Relation::checkType(rel)){
return listutils::typeError("first argument is not a relation");
}
if((nl->AtomType(attrList)!=NoAtom) || nl->IsEmpty(attrList)){
return listutils::typeError("invalid list of attribute names");
}
NList l(args);
const string opName = "feedproject";
const string arg1 = "rel(tuple(...)";
const string arg2 = "list of unique symbols (a_1 ... a_k)";
string err1("");
if ( !l.checkLength(2, err1) )
return l.typeError( err1 );
NList attrs;
if ( !l.first().checkRel( attrs ) )
return l.typeError(1, arg1);
//cerr << "a1 " << attrs << endl;
NList atoms = l.second();
if ( !l.checkSymbolList( atoms ) )
return l.typeError(2, arg2);
if ( !l.checkUniqueMembers( atoms ) )
return l.typeError(2, arg2);
NList indices;
NList oldAttrs(attrs);
NList newAttrs;
int noAtoms = atoms.length();
while ( !atoms.isEmpty() )
{
string attrname = atoms.first().str();
ListExpr attrtype = nl->Empty();
//cerr << "a2 " << attrs << endl;
int newIndex = FindAttribute( oldAttrs.listExpr(), attrname, attrtype );
if (newIndex > 0)
{
indices.append( NList(newIndex) );
newAttrs.append( oldAttrs.elem(newIndex) );
}
else
{
ErrorReporter::ReportError(
"Attributename '" + attrname +
"' is not a known attributename in the tuple stream.");
return nl->SymbolAtom(Symbol::TYPEERROR());
}
atoms.rest();
}
NList outlist = NList( NList(Symbol::APPEND()),
NList( NList( noAtoms ), indices ),
NList().tupleStreamOf( newAttrs ) );
return outlist.listExpr();
}
CostEstimation*
OperatorFeedProject::FeedProjectCostEstimationFunc() {
return new FeedProjectCostEstimation();
}
int
OperatorFeedProject::feedproject_vm(Word* args,
Word& result,
int message,
Word& local,
Supplier s)
{
GenericRelation* r=0;
FeedProjLocalInfo* fli=0;
Word elem(Address(0));
int noOfAttrs= 0;
int index= 0;
Supplier son;
TupleType* tt = (TupleType*) qp->GetLocal2(s).addr;
switch (message)
{
case INIT : {
tt = new TupleType(nl->Second(GetTupleResultType(s)));
qp->GetLocal2(s).addr = tt;
return 0;
}
case FINISH : {
if(tt){
tt->DeleteIfAllowed();
qp->GetLocal2(s).addr=0;
}
return 0;
}
case OPEN :{
r = (GenericRelation*)args[0].addr;
fli = (FeedProjLocalInfo*) local.addr;
if ( fli ) delete fli;
tt->IncReference();
fli = new FeedProjLocalInfo(tt);
fli->total = r->GetNoTuples();
fli->rit = r->MakeScan(tt);
local.setAddr(fli);
return 0;
}
case REQUEST :{
fli = (FeedProjLocalInfo*) local.addr;
Tuple *t;
noOfAttrs = ((CcInt*)args[2].addr)->GetIntval();
list<int> usedAttrs;
for( int i = 0; i < noOfAttrs; i++)
{
son = qp->GetSupplier(args[3].addr, i);
qp->Request(son, elem);
index = ((CcInt*)elem.addr)->GetIntval();
//cerr << "ind = " << index << endl;
usedAttrs.push_back(index-1);
}
if ((t = fli->rit->GetNextTuple(usedAttrs)) != 0)
{
fli->returned++;
result.setAddr(t);
return YIELD;
}
else
{
return CANCEL;
}
}
case CLOSE :{
fli = static_cast<FeedProjLocalInfo*>(local.addr);
if(fli){
if(fli->rit){
delete fli->rit;
fli->rit=0;
}
delete fli;
fli = 0;
local.setAddr(0);
}
return 0;
} // end case
} // end switch
return 0;
}
#endif