/* ---- This file is part of SECONDO. Copyright (C) 2004-2009, University in Hagen, 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 ---- //paragraph [10] title: [{\Large \bf ] [}] //paragraph [21] table1column: [\begin{quote}\begin{tabular}{l}] [\end{tabular}\end{quote}] //paragraph [22] table2columns: [\begin{quote}\begin{tabular}{ll}] [\end{tabular}\end{quote}] //paragraph [23] table3columns: [\begin{quote}\begin{tabular}{lll}] [\end{tabular}\end{quote}] //paragraph [24] table4columns: [\begin{quote}\begin{tabular}{llll}] [\end{tabular}\end{quote}] //[TOC] [\tableofcontents] //[--------] [\hline] //characters [1] verbatim: [$] [$] //characters [2] formula: [$] [$] //characters [3] capital: [\textsc{] [}] //characters [4] teletype: [\texttt{] [}] //[ae] [\"a] //[oe] [\"o] //[ue] [\"u] //[ss] [{\ss}] //[<=] [\leq] //[#] [\neq] //[tilde] [\verb|~|] //[<] [$<$] //[>] [$>$] [10] Implementation file of the CompiledExpression Algebra 2016/2017 H.Brieschke created the new CompiledExpression Algebra [TOC] 1 Overview The ~Compiled Expression Algebra~ basically implements three operators, Namely ~filter~, ~extend~, and ~executeQuery~. However, these can not be used directly in a query, but are exchanged by the algebra against the original operators during the query processing. The ~filter~-operator corresponds to the ~filter~-operator from the ~relation algebra~, the ~extend~-operator is the ~extend~-operator from the ~ExtRelation algebra~, and the ~excecuteQuery-~operator is used if the complete query could be compiled by this algebra. 2 Defines, includes, and constants */ #include #include "Operator.h" #include "NestedList.h" #include "ListUtils.h" #include "Symbols.h" #include "Trace.h" #include "StandardTypes.h" #include "QueryProcessor.h" #include "Progress.h" #include "Algebras/Relation-C++/RelationAlgebra.h" #include "./CompiledExpressionsAlgebra.h" #include "./CECompiler.h" #include "./CECodeGenerator.h" extern NestedList* nl; extern QueryProcessor* qp; extern AlgebraManager* am; using namespace CompiledExpressions; namespace CompiledExpressions { /* 3 Class ~CEARuntimeError~ This class implements ~ERROR~-objects, which are required for the error treatment. */ CEARuntimeError::CEARuntimeError(std::string s) { errMsg = s; } const char* CEARuntimeError::what() const throw() { return errMsg.c_str(); } /* 4 The Operators of the ~Compiled Expressions Algebra~. 4.1 Operator ~filter~ This operator corrosponded to the ~filter-~operator in the ~Realation-Algebra~. Only tuples, fulfilling a certain condition are passed on to the output stream. 4.1.1 Type mapping function of operator ~filter~ Result type of filter operation. ---- ((stream (tuple x)) (map (tuple x) bool)) -> (stream (tuple x)) ---- Type mapping function modified to show the possibility of getting not only types but also arguments in the type mapping. This happens when an operator registers "UsesArgsinTypeMapping". Type list now has the form ---- ( (type1 arg1) (type2 arg2) ) ---- that is ---- ( ( (stream (tuple x)) arg1 ) ( (map (tuple x) bool) arg2 ) ) ---- */ ListExpr ceaFilterTypeMap( ListExpr args ) { if(!nl->HasLength(args,2)) { return listutils::typeError("two arguments expected"); } if(!nl->HasLength(nl->First(args),2)) { ErrorReporter::ReportError("the first argument " " should be a (type, expression) pair"); return nl->TypeError(); } if(!listutils::isTupleStream(nl->First(nl->First(args)))){ ErrorReporter::ReportError("first argument must be a stream of tuples"); return nl->TypeError(); } if(!nl->HasLength(nl->Second(args),2)){ ErrorReporter::ReportError("the second argument " " should be a (type, expression) pair"); return nl->TypeError(); } ListExpr map = nl->First(nl->Second(args)); if(!listutils::isMap<1>(map)){ // checking for a single arg ErrorReporter::ReportError("map: tuple -> bool expected as the" " second argument"); return nl->TypeError(); } ListExpr mapres = nl->Third(map); if(!CcBool::checkType(mapres)){ ErrorReporter::ReportError("map is not a predicate"); return nl->TypeError(); } if(!nl->Equal(nl->Second(nl->First(nl->First(args))), nl->Second(map))){ ErrorReporter::ReportError("map and tuple type are not consistent"); return nl->TypeError(); } return nl->First(nl->First(args)); } /* 4.1.2 Value mapping function of operator ~filter~ */ #ifndef USE_PROGRESS // standard version int ceaFilterValueMap( Word* args, Word& result, int message, Word& local, Supplier s ) { switch ( message ) { case OPEN: qp->Open (args[0].addr); return 0; case REQUEST: { bool found = false; Word elem; Tuple* tuple = 0; filterOp_t filterOp = (filterOp_t) args[1].addr; qp->Request(args[0].addr, elem); while (qp->Received(args[0].addr) && !found) { tuple = (Tuple*)elem.addr; found = filterOp(tuple); if (!found) { tuple->DeleteIfAllowed(); qp->Request(args[0].addr, elem); } } if (found) { result.setAddr(tuple); return YIELD; } else return CANCEL; } case CLOSE: qp->Close(args[0].addr); return 0; } return 0; } #else //progress version int ceaFilterValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { CEAFilterLocalInfo* ptrCEAFLI; switch ( message ) { case OPEN: { ptrCEAFLI = (CEAFilterLocalInfo*) local.addr; if(ptrCEAFLI) delete ptrCEAFLI; ptrCEAFLI = new CEAFilterLocalInfo(); local.setAddr(ptrCEAFLI); qp->Open(args[0].addr); return 0; } case REQUEST: { ptrCEAFLI = (CEAFilterLocalInfo*) local.addr; bool found = false; Word elem; Tuple* tuple = 0; filterOp_t filterOp = (filterOp_t) args[1].addr; qp->Request(args[0].addr, elem); while (qp->Received(args[0].addr) && !found) { tuple = (Tuple*)elem.addr; found = filterOp(tuple); if (!found) { tuple->DeleteIfAllowed(); qp->Request(args[0].addr, elem); } } if (found) { result.setAddr(tuple); ptrCEAFLI->addReturned(); return YIELD; } else { ptrCEAFLI->setDone(); return CANCEL; } } case CLOSE: { qp->Close(args[0].addr); return 0; } case CLOSEPROGRESS: { ptrCEAFLI = (CEAFilterLocalInfo*) local.addr; if (ptrCEAFLI) { delete ptrCEAFLI; local.setAddr(0); } return 0; } case REQUESTPROGRESS: { ProgressInfo p1; ProgressInfo* pRes; const double uFilter = 0.01; pRes = (ProgressInfo*) result.addr; ptrCEAFLI = (CEAFilterLocalInfo*) local.addr; if ( qp->RequestProgress(args[0].addr, &p1) ) { pRes->CopySizes(p1); if ( ptrCEAFLI ) { //filter was started if ( ptrCEAFLI->getDone() ) { //arg stream exhausted, all known pRes->Card = (double) ptrCEAFLI->getReturned(); pRes->Time = p1.Time + (double) ptrCEAFLI->getCurrent() * qp->GetPredCost(s) * uFilter; pRes->Progress = 1.0; pRes->CopyBlocking(p1); return YIELD; } if ( ptrCEAFLI->getReturned() >= enoughSuccessesSelection ) { //stable state assumed now pRes->Card = p1.Card * ( (double) ptrCEAFLI->getReturned() / (double) (ptrCEAFLI->getCurrent())); pRes->Time = p1.Time + p1.Card * qp->GetPredCost(s) * uFilter; if ( p1.BTime < 0.1 && pipelinedProgress ) //non-blocking, //use pipelining pRes->Progress = p1.Progress; else pRes->Progress = (p1.Progress * p1.Time + ptrCEAFLI->getCurrent() * qp->GetPredCost(s) * uFilter) / pRes->Time; pRes->CopyBlocking(p1); return YIELD; } } //filter not yet started or not enough seen pRes->Card = p1.Card * qp->GetSelectivity(s); pRes->Time = p1.Time + p1.Card * qp->GetPredCost(s) * uFilter; if ( p1.BTime < 0.1 && pipelinedProgress ) //non-blocking, //use pipelining pRes->Progress = p1.Progress; else pRes->Progress = (p1.Progress * p1.Time) / pRes->Time; pRes->CopyBlocking(p1); return YIELD; } else return CANCEL; } } return 0; } /* 4.1.3 Class ~CEAFilterLocalInfo~ In the ~Progress~-Version used this class objects as data structure for the progress informations. The Constructor. */ CEAFilterLocalInfo::CEAFilterLocalInfo() : current(0), returned(0), done(false) {} /* The Destructor. */ CEAFilterLocalInfo::~CEAFilterLocalInfo() {} /* The following methods are the ~get~er- and ~set~er-methods for these private variables. */ void CEAFilterLocalInfo::addCurrent() { current++; } void CEAFilterLocalInfo::addReturned() { returned++; } void CEAFilterLocalInfo::setDone() { done = true; } int CEAFilterLocalInfo::getCurrent() { return current; } int CEAFilterLocalInfo::getReturned() { return returned; } bool CEAFilterLocalInfo::getDone() { return done; } #endif /* 4.1.4 Specification of operator ~filter~ */ const std::string ceaFilterSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "( ((stream x) (map x bool)) -> " "(stream x)" "_ filter [ fun ]" "Only tuples, fulfilling a certain " "condition are passed on to the output " "stream." "query cities feed filter " "[.population > 500000] consume" ") )"; /* 4.1.5 Definition of operator ~filter~ */ Operator ceaOperatorFilter ( "filter", // name ceaFilterSpec, // specification ceaFilterValueMap, // value mapping Operator::SimpleSelect, // trivial selection function ceaFilterTypeMap // type mapping ); /* 4.2 Operator ~extend~ This operator corrosponded to the ~extend-~operator in the ~ExtRealation-Algebra~. Extends each input tuple by new attributes as specified in the parameter list. 4.2.1 Type mapping function of operator ~extend~ Type mapping for ~extend~ is ---- ((stream X) ((b1 (map x y1)) ... (bm (map x ym)))) -> (stream (tuple ((a1 x1) ... (an xn) (b1 y1) ... (bm ym))))) where X = (tuple ((a1 x1) ... (an xn))) ---- */ ListExpr ceaExtendTypeMap( ListExpr args ) { ListExpr errorInfo = nl->OneElemList(nl->SymbolAtom("ERROR")); if(nl->ListLength(args)!=2){ ErrorReporter::ReportError("two elements expected"); return nl->TypeError(); } ListExpr stream = nl->First(args); if(!IsStreamDescription(stream)){ ErrorReporter::ReportError("first argument is not a tuple stream"); return nl->TypeError(); } ListExpr tuple = nl->Second(stream); ListExpr functions = nl->Second(args); if(nl->ListLength(functions)<1){ ErrorReporter::ReportError("at least one function expected"); return nl->TypeError(); } // copy attrlist to newattrlist ListExpr attrList = nl->Second(nl->Second(stream)); ListExpr newAttrList = nl->OneElemList(nl->First(attrList)); ListExpr lastlistn = newAttrList; attrList = nl->Rest(attrList); while (!(nl->IsEmpty(attrList))) { lastlistn = nl->Append(lastlistn,nl->First(attrList)); attrList = nl->Rest(attrList); } // reset attrList attrList = nl->Second(nl->Second(stream)); ListExpr typeList; // check functions std::set usedNames; while (!(nl->IsEmpty(functions))) { ListExpr function = nl->First(functions); functions = nl->Rest(functions); if(nl->ListLength(function)!=2){ ErrorReporter::ReportError("invalid extension found"); return nl->TypeError(); } ListExpr name = nl->First(function); ListExpr map = nl->Second(function); std::string errormsg; if(!listutils::isValidAttributeName(name, errormsg)){ return listutils::typeError(errormsg); } std::string namestr = nl->SymbolValue(name); int pos = FindAttribute(attrList,namestr,typeList); if(pos!=0){ ErrorReporter::ReportError("Attribute "+ namestr + " already member of the tuple"); return nl->TypeError(); } if(nl->ListLength(map)!=3){ ErrorReporter::ReportError("invalid function"); return nl->TypeError(); } if(!nl->IsEqual(nl->First(map),Symbol::MAP())){ ErrorReporter::ReportError("invalid function"); return nl->TypeError(); } ListExpr funResType = nl->Third(map); if(!am->CheckKind(Kind::DATA(),funResType, errorInfo)){ ErrorReporter::ReportError("requested attribute " + namestr + "not in kind DATA"); return nl->TypeError(); } ListExpr funArgType = nl->Second(map); if(!nl->Equal(funArgType, tuple)){ ErrorReporter::ReportError ("function type different to the tuple type"); return nl->TypeError(); } if(usedNames.find(namestr)!=usedNames.end()){ ErrorReporter::ReportError("Name "+ namestr + "occurs twice"); return nl->TypeError(); } usedNames.insert(namestr); // append attribute lastlistn = nl->Append(lastlistn, (nl->TwoElemList(name, funResType ))); } return nl->TwoElemList(nl->SymbolAtom(Symbol::STREAM()), nl->TwoElemList(nl->SymbolAtom(Tuple::BasicType()), newAttrList)); } /* 4.2.2 Value mapping function of operator ~extend~ */ #ifndef USE_PROGRESS // standard version int ceaExtendValueMap(Word* args, Word& result, int message, Word& local, Supplier s ) { TupleType* resultTupleType; switch (message) { case OPEN: { ListExpr resultType; qp->Open(args[0].addr); resultType = GetTupleResultType( s ); resultTupleType = new TupleType( nl->Second( resultType ) ); local.setAddr( resultTupleType ); return 0; } case REQUEST: { Supplier supplier1, supplier2, supplier3; Tuple* tuple; Word elem, value, tmpArgs; ArgVectorPointer funargs; int nooffun; resultTupleType = (TupleType*)local.addr; qp->Request(args[0].addr, elem); if (qp->Received(args[0].addr)) { tuple = (Tuple*)elem.addr; Tuple* newTuple = new Tuple( resultTupleType ); for( int i = 0; i < tuple->GetNoAttributes(); i++ ) { //cout << (void*) tuple << endl; newTuple->CopyAttribute( i, tuple, i ); } supplier1 = args[1].addr; nooffun = qp->GetNoSons(supplier1); for (int i=0; i < nooffun; i++) { supplier2 = qp->GetSupplier(supplier1, i); supplier3 = qp->GetSupplier(supplier2, 1); if ((qp->getPtrCEQueryProcessor())->IsPointerNode( supplier3 )) { //cout << "son [" << i << "] is a pointer." << endl; qp->Request(supplier3, tmpArgs); extendOp_t extendOp = (extendOp_t) tmpArgs.addr; newTuple->PutAttribute( tuple->GetNoAttributes()+i, (extendOp(tuple))->Clone()); } else { //cout << "son [" << i << "] is a map function." << endl; funargs = qp->Argument(supplier3); ((*funargs)[0]).setAddr(tuple); qp->Request(supplier3,value); newTuple->PutAttribute( tuple->GetNoAttributes()+i, ((Attribute*)value.addr)->Clone() ); } } tuple->DeleteIfAllowed(); result.setAddr(newTuple); return YIELD; } else return CANCEL; } case CLOSE: if(local.addr) { ((TupleType*)local.addr)->DeleteIfAllowed(); local.setAddr(0); } qp->Close(args[0].addr); return 0; } return 0; } # else // progress version int ceaExtendValueMap(Word* args, Word& result, int message, Word& local, Supplier s) { Word t, value, tmpArgs; Tuple* tuple; Supplier supplier1, supplier2, supplier3; int nooffun; ArgVectorPointer funargs; CEAExtendLocalInfo* ptrCEAELI; switch (message) { case OPEN : { ptrCEAELI = (CEAExtendLocalInfo*) local.addr; if ( ptrCEAELI ) { delete ptrCEAELI; } ptrCEAELI = new CEAExtendLocalInfo (new TupleType(nl->Second(GetTupleResultType(s))), 50, false, qp->GetNoSons(args[1].addr)); local.setAddr(ptrCEAELI); qp->Open(args[0].addr); return 0; } case REQUEST : { ptrCEAELI = (CEAExtendLocalInfo*) local.addr; if(!ptrCEAELI){ return CANCEL; } qp->Request(args[0].addr,t); if (qp->Received(args[0].addr)) { tuple = (Tuple*)t.addr; Tuple* newTuple = new Tuple( ptrCEAELI->getResultTupleType() ); ptrCEAELI->read++; for( int i = 0; i < tuple->GetNoAttributes(); i++ ) { //cout << (void*) tuple << endl; newTuple->CopyAttribute( i, tuple, i ); } supplier1 = args[1].addr; nooffun = qp->GetNoSons(supplier1); for (int i=0; i < nooffun;i++) { supplier2 = qp->GetSupplier(supplier1, i); supplier3 = qp->GetSupplier(supplier2, 1); if ((qp->getPtrCEQueryProcessor())->IsPointerNode( supplier3 )) { //cout << "son [" << i << "] is a pointer." << endl; qp->Request(supplier3, tmpArgs); extendOp_t extendOp = (extendOp_t) tmpArgs.addr; newTuple->PutAttribute( tuple->GetNoAttributes()+i, (extendOp(tuple))->Clone()); } else { //cout << "son [" << i << "] is a map function." << endl; funargs = qp->Argument(supplier3); ((*funargs)[0]).setAddr(tuple); qp->Request(supplier3,value); newTuple->PutAttribute( tuple->GetNoAttributes()+i, ((Attribute*)value.addr)->Clone() ); } if (ptrCEAELI->read <= ptrCEAELI->getStableValue()) { ptrCEAELI->addAttrSizeTmp (newTuple->GetSize(tuple->GetNoAttributes()+i), i); ptrCEAELI->addAttrSizeExtTmp (newTuple->GetExtSize(tuple->GetNoAttributes()+i), i); } } tuple->DeleteIfAllowed(); result.setAddr(newTuple); return YIELD; } else return CANCEL; } case CLOSE : { qp->Close(args[0].addr); return 0; } case CLOSEPROGRESS : { ptrCEAELI = (CEAExtendLocalInfo*) local.addr; if ( ptrCEAELI ){ delete ptrCEAELI; local.setAddr(0); } return 0; } case REQUESTPROGRESS : { ptrCEAELI = (CEAExtendLocalInfo*) local.addr; ProgressInfo p1; ProgressInfo *pRes; const double uExtend = 0.0034; //millisecs per tuple const double vExtend = 0.0067; //millisecs per tuple and attribute // see determination of constants in file ConstantsExtendStream pRes = (ProgressInfo*) result.addr; if ( !ptrCEAELI ) { return CANCEL; } if ( qp->RequestProgress(args[0].addr, &p1) ) { ptrCEAELI->sizesChanged = false; if ( !ptrCEAELI->sizesInitialized ) { ptrCEAELI->setNoOldAttrs(p1.noAttrs); ptrCEAELI->noAttrs = ptrCEAELI->getNoOldAttrs() + ptrCEAELI->getNoNewAttrs(); ptrCEAELI->attrSize = new double[ptrCEAELI->noAttrs]; ptrCEAELI->attrSizeExt = new double[ptrCEAELI->noAttrs]; } if ( !ptrCEAELI->sizesInitialized || p1.sizesChanged || ( ptrCEAELI->read >= ptrCEAELI->getStableValue() && !ptrCEAELI->getSizesFinal() ) ) { ptrCEAELI->Size = 0.0; ptrCEAELI->SizeExt = 0.0; //old attrs for (int i = 0; i < ptrCEAELI->getNoOldAttrs(); i++) { ptrCEAELI->attrSize[i] = p1.attrSize[i]; ptrCEAELI->attrSizeExt[i] = p1.attrSizeExt[i]; ptrCEAELI->Size += ptrCEAELI->attrSize[i]; ptrCEAELI->SizeExt += ptrCEAELI->attrSizeExt[i]; } //new attrs if ( ptrCEAELI->read < ptrCEAELI->getStableValue() ) { for (int j = 0; j < ptrCEAELI->getNoNewAttrs(); j++) { ptrCEAELI->attrSize[j + ptrCEAELI->getNoOldAttrs()] = 12; ptrCEAELI->attrSizeExt[j + ptrCEAELI->getNoOldAttrs()] = 12; ptrCEAELI->Size += ptrCEAELI ->attrSize[j + ptrCEAELI->getNoOldAttrs()]; ptrCEAELI->SizeExt += ptrCEAELI ->attrSizeExt[j + ptrCEAELI ->getNoOldAttrs()]; } } else { for (int j = 0; j < ptrCEAELI->getNoNewAttrs(); j++) { ptrCEAELI->attrSize[j + ptrCEAELI->getNoOldAttrs()] = ptrCEAELI->getAttrSizeTmp(j) / ptrCEAELI->getStableValue(); ptrCEAELI->attrSizeExt[j + ptrCEAELI->getNoOldAttrs()] = ptrCEAELI->getAttrSizeExtTmp(j) / ptrCEAELI->getStableValue(); ptrCEAELI->Size += ptrCEAELI ->attrSize[j + ptrCEAELI ->getNoOldAttrs()]; ptrCEAELI->SizeExt += ptrCEAELI ->attrSizeExt[j + ptrCEAELI ->getNoOldAttrs()]; } } ptrCEAELI->sizesInitialized = true; ptrCEAELI->sizesChanged = true; } //ensure sizes are updated only once for passing the threshold if ( ptrCEAELI->read >= ptrCEAELI->getStableValue() ) ptrCEAELI->setSizesFinal(true); pRes->Card = p1.Card; pRes->CopySizes(ptrCEAELI); pRes->Time = p1.Time + p1.Card * (uExtend + ptrCEAELI->getNoNewAttrs() * vExtend); if ( p1.BTime < 0.1 && pipelinedProgress ) //non-blocking, //use pipelining pRes->Progress = p1.Progress; else pRes->Progress = (p1.Progress * p1.Time + ptrCEAELI->read * (uExtend + ptrCEAELI->getNoNewAttrs() * vExtend)) / pRes->Time; pRes->CopyBlocking(p1); //non-blocking operator return YIELD; } else { return CANCEL; } } } return 0; } /* 4.2.3 Class ~CEAExtendLocalInfo~ In the ~Progress~-Version used this class objects as data structure for the progress informations. The Constructor. */ CEAExtendLocalInfo::CEAExtendLocalInfo( TupleType* ptrTupleType, int sv, bool sf, int nna) : resultTupleType(ptrTupleType), stableValue(sv), sizesFinal(sf), noOldAttrs(0), noNewAttrs(nna) { attrSizeTmp = new double[nna]; attrSizeExtTmp = new double[nna]; for (int i = 0; i < nna; i++) { attrSizeTmp[i] = 0.0; attrSizeExtTmp[i] = 0.0; } }; /* The Destructor. */ CEAExtendLocalInfo::~CEAExtendLocalInfo() { if(resultTupleType){ resultTupleType->DeleteIfAllowed(); } if(attrSizeTmp){ delete [] attrSizeTmp; } if(attrSizeExtTmp){ delete [] attrSizeExtTmp; } } /* The following methods are the ~get~er- and ~set~er-methods for these private variables. */ void CEAExtendLocalInfo::setResultTupleType(TupleType* ptrTupleType) { resultTupleType = ptrTupleType; } TupleType* CEAExtendLocalInfo::getResultTupleType() { return resultTupleType; } void CEAExtendLocalInfo::setStableValue(int val) { stableValue = val; } int CEAExtendLocalInfo::getStableValue() { return stableValue; } void CEAExtendLocalInfo::setSizesFinal(bool sf) { sizesFinal = sf; } bool CEAExtendLocalInfo::getSizesFinal() { return sizesFinal; } void CEAExtendLocalInfo::setNoOldAttrs(int noa) { noOldAttrs = noa; } int CEAExtendLocalInfo::getNoOldAttrs() { return noOldAttrs; } void CEAExtendLocalInfo::setNoNewAttrs(int noa) { noNewAttrs = noa; } int CEAExtendLocalInfo::getNoNewAttrs() { return noNewAttrs; } void CEAExtendLocalInfo::setAttrSizeTmp(double asp, int idx) { attrSizeTmp[idx] = asp; } void CEAExtendLocalInfo::addAttrSizeTmp(double asp, int idx) { attrSizeTmp[idx] += asp; } double CEAExtendLocalInfo::getAttrSizeTmp(int idx) { return attrSizeTmp[idx]; } void CEAExtendLocalInfo::setAttrSizeExtTmp(double asep, int idx) { attrSizeExtTmp[idx] = asep; } void CEAExtendLocalInfo::addAttrSizeExtTmp(double asep, int idx) { attrSizeExtTmp[idx] += asep; } double CEAExtendLocalInfo::getAttrSizeExtTmp(int idx) { return attrSizeExtTmp[idx]; } #endif /* 4.2.4 Specification of operator ~extend~ */ const std::string ceaExtendSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "( (stream(tuple(x)) x [(a1, (tuple(x)" " -> d1)) ... (an, (tuple(x) -> dn))] -> " "stream(tuple(x@[a1:d1, ... , an:dn])))" "" "_ extend [funlist]" "Extends each input tuple by new " "attributes as specified in the parameter" " list." "query ten feed extend [mult5 : " ".nr * 5, mod2 : .nr mod 2] consume" "" ") )"; /* 4.2.5 Definition of operator ~extend~ */ Operator ceaOperatorExtend ( "extend", // name ceaExtendSpec, // specification ceaExtendValueMap, // value mapping Operator::SimpleSelect, // trivial selection function ceaExtendTypeMap // type mapping ); /* 4.3 Operator ~executeQuery~ This operator is used, if the complete query could be compiled by this algebra. 4.3.1 Type mapping function of operator ~executeQuery~ Since this operator can not be used directly in queries, there is no valid type mappings. A type mapping error is always generated. */ ListExpr ceaExecuteQueryTypeMap( ListExpr args ) { ErrorReporter::ReportError("this operator is not to be used in queries"); return nl->TypeError(); } /* 4.3.2 Value mapping function of operator ~executeQuery~ */ int ceaExecuteQueryValueMap(Word* args, Word& result, int message, Word& local, Supplier s ) { executeQueryOp_t executeQueryOp = (executeQueryOp_t) args[0].addr; executeQueryOp(result, s); return 0; } /* 4.3.3 Specification of operator ~executeQuery~ */ const std::string ceaExecuteQuerySpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" " "\"Example\" ) " "( ()" "executeQuery" "This Operator called only from Secondo-" "System. Is not to use in querys." "No Exapmle exist.) )"; /* 4.3.4 Definition of operator ~executeQuery~ */ Operator ceaOperatorExecuteQuery ( "executeQuery", // name ceaExecuteQuerySpec, // specification ceaExecuteQueryValueMap, // value mapping Operator::SimpleSelect, // trivial selection function ceaExecuteQueryTypeMap // type mapping ); /* 5 Class ~CompiledExpressionsAlgebra~ A new subclass ~CompiledExpressionsAlgebra~ of class ~Algebra~ is declared. The only specialization with respect to class ~Algebra~ takes place within the constructor: all type constructors and operators are registered at the actual algebra. After declaring the new class, its only instance ~CompiledExpressionsAlgebra~ is defined. Definition the static variables of the ~CompiledExpressionsAlgebra~-class. */ bool CompiledExpressionsAlgebra::ceaActiv = false; CompiledExpressionsAlgebra* CompiledExpressionsAlgebra::instance = 0; /* This function gives a pointer to the ~CompiledExpressionsAlgebra~-Instance. */ CompiledExpressionsAlgebra* CompiledExpressionsAlgebra::getInstance() { if (!instance) instance = new CompiledExpressions::CompiledExpressionsAlgebra(); return instance; } /* This function delete the ~CompiledExpressionsAlgebra~-Instance. */ void CompiledExpressionsAlgebra::deleteInstance() { if (instance) delete instance; instance = 0; } /* This function returned, if one instance of the ~CompiledExpressionsAlgebra~ are created. */ bool CompiledExpressionsAlgebra::isActiv() { return CompiledExpressionsAlgebra::ceaActiv; } /* The Constructor. */ CompiledExpressionsAlgebra::CompiledExpressionsAlgebra() : Algebra(), thisAlgID(-1) { AddOperator(&ceaOperatorFilter); ceaOperatorFilter.SetUsesArgsInTypeMapping(); AddOperator(&ceaOperatorExtend); AddOperator(&ceaOperatorExecuteQuery); /* Register operators which are able to handle progress messages */ #ifdef USE_PROGRESS ceaOperatorFilter.EnableProgress(); ceaOperatorExtend.EnableProgress(); #endif CompiledExpressionsAlgebra::ceaActiv = true; } /* The Destructor. */ CompiledExpressionsAlgebra::~CompiledExpressionsAlgebra() { instance = 0; CECodeGenerator::deleteInstance(); CECompiler::deleteInstance(); } /* This function returned the algebra-ID from the algebramanager or 0, if the algera is not loaded. */ int CompiledExpressionsAlgebra::getThisAlgebraID() /*throw (CEARuntimeError)*/{ if (thisAlgID == -1) thisAlgID = am->GetAlgebraId("CompiledExpressionsAlgebra"); if (thisAlgID == 0) throw CEARuntimeError("The CompiledExpressionsAlgebra is not loaded."); return thisAlgID; } /* This function returned the operator-ID of the spezified operator name. If the operator is not found, the function throws an error. */ int CompiledExpressionsAlgebra::getOperatorID(std::string name) /*throw (CEARuntimeError)*/ { int idx = 0; bool found = false; while ( !found && idx < GetNumOps() ) { if ( GetOperator(idx)->GetName() == name ) found = true; else idx++; } if (!found) throw CEARuntimeError("Operator " + name + " not insert in this algebra."); return idx; } } /* 7 Initialization Each algebra module needs an initialization function. The algebra manager has a reference to this function if this algebra is included in the list of required algebras, thus forcing the linker to include this module. The algebra manager invokes this function to get a reference to the instance of the algebra class and to provide references to the global nested list container (used to store constructor, type, operator and object information) and to the query processor. The function has a C interface to make it possible to load the algebra dynamically at runtime. */ #ifdef __cplusplus extern "C"{ #endif Algebra* InitializeCompiledExpressionsAlgebra(NestedList* nlRef, QueryProcessor* qpRef) { nl = nlRef; qp = qpRef; return CompiledExpressions::CompiledExpressionsAlgebra::getInstance(); } #ifdef __cplusplus } #endif