Files
secondo/Algebras/Temporal2/OpAppendPositions.cpp

441 lines
14 KiB
C++
Raw Normal View History

2026-01-23 17:03:45 +08:00
/*
implementation of operator appendpositions
*/
#include "OpAppendPositions.h"
#include "Operator.h"
#include "NestedList.h"
#include "QueryProcessor.h"
#include "StandardTypes.h"
#include "Algebras/Temporal/TemporalAlgebra.h"
#include "Stream.h"
#include "TypeMapUtils.h"
#include "Symbols.h"
#include "ListUtils.h"
#include "MPoint2.h"
#include "Algebras/FText/FTextAlgebra.h"
#include "Stream.h"
#include "Algebras/TupleIdentifier/TupleIdentifier.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "Algebras/OrderedRelation/OrderedRelationAlgebra.h"
#include "MovingCalculations.h"
#include <sstream>
extern NestedList* nl;
extern QueryProcessor *qp;
using namespace std;
using namespace temporalalgebra;
namespace temporal2algebra{
struct AppendPositionsInfo : OperatorInfo {
AppendPositionsInfo() : OperatorInfo() {
name = "appendpositions";
signature = "stream(tuple1) x relation(tuple2)"
"x text x text x text (x int)"
" -> stream(tuple)";
syntax = "<stream(tuple1)> x <relation(tuple2)> appendpositions"
" ['<tid-src-attr>', '<pos-src-attr>', '<pos-dst-attr>',"
" <transaction_mode>]";
meaning = "Appends the positions from tuple1.pos-src-attr to"
" tuple2.pos-dst-attr where tuple2.tid = tuple1.tid-src-attr\n"
"Choose transaction mode 1 for subcommits. ATTENTION: this will"
" crash secondo when using the feed operator.";
}
};
ListExpr AppendPositions_tm( ListExpr args ) {
int numArgs = nl->ListLength(args);
if (numArgs < 5 || numArgs > 6 ) {
stringstream s;
s << "expected 5 or 6 arguments, but got " << numArgs;
return listutils::typeError(s.str());
}
ListExpr arg_tuplestreamType = nl->First(nl->First(args));
ListExpr arg_relationName = nl->Second(args);
ListExpr arg_srcTidAttr = nl->Third(args);
ListExpr arg_srcElemAttr = nl->Fourth(args);
ListExpr arg_dstM2Attr = nl->Fifth(args);
if(!listutils::isTupleStream(arg_tuplestreamType)){
return listutils::typeError("first argument must be a tuple stream"
", but got " + nl->ToString(arg_tuplestreamType));
}
ListExpr tupAttributes = nl->Second(nl->Second(arg_tuplestreamType));
if(!FText::checkType(nl->First(arg_relationName))) {
return listutils::typeError("second argument must be of type "
+ FText::BasicType()
+ ", but got " + nl->ToString(nl->First(arg_srcElemAttr)));
}
std::string relationName = nl->Text2String(nl->Second(arg_relationName));
SecondoCatalog* catalog = SecondoSystem::GetCatalog();
if (!catalog->IsObjectName(relationName)) {
return listutils::typeError("No secondo object found with name '"
+ relationName + "'");
}
ListExpr relationType = catalog->GetObjectTypeExpr(relationName);
if(!listutils::isRelDescription(relationType) &&
!listutils::isOrelDescription(relationType)){
return listutils::typeError("second argument must be of type "
+ Relation::BasicType() + " or "
+ OrderedRelation::BasicType()
+ ", but got " + nl->ToString(relationType));
}
ListExpr relAttributes = nl->Second(nl->Second(relationType));
if(!FText::checkType(nl->First(arg_srcTidAttr))) {
return listutils::typeError("third argument must be of type "
+ FText::BasicType()
+ ", but got " + nl->ToString(nl->First(arg_srcTidAttr)));
}
std::string tupTidAttrToFindName =
nl->Text2String(nl->Second(arg_srcTidAttr));
if(!FText::checkType(nl->First(arg_srcElemAttr))) {
return listutils::typeError("fourth argument must be of type "
+ FText::BasicType()
+ ", but got " + nl->ToString(nl->First(arg_srcElemAttr)));
}
std::string tupAttrToFindName =
nl->Text2String(nl->Second(arg_srcElemAttr));
if(!FText::checkType(nl->First(arg_dstM2Attr))) {
return listutils::typeError("fifth argument must be of type "
+ FText::BasicType()
+ ", but got " + nl->ToString(nl->First(arg_dstM2Attr)));
}
std::string relAttrToFindName = nl->Text2String(nl->Second(arg_dstM2Attr));
// find tid attr in incoming stream
ListExpr tupTidAttrType;
int tupTidAttrPos = listutils::findAttribute(
tupAttributes , tupTidAttrToFindName , tupTidAttrType);
if (tupTidAttrPos == 0) {
return listutils::typeError("incoming stream does not "
"contain attribute with name '" + tupTidAttrToFindName +"'");
}
if (TupleIdentifier::checkType(tupTidAttrType)) {
cout << "this is what we really need\n";
} else if (CcInt::checkType(tupTidAttrType)) {
cout << "only temporarily accept int\n";
} else {
return listutils::typeError("expected attribute's '"
+ tupTidAttrToFindName
+ "' type in incoming stream to be "
+ TupleIdentifier::BasicType()
+ ", but was " + nl->ToString(tupTidAttrType));
}
// find unit/intime attr in incoming stream
ListExpr tupAttrType;
int tupAttrPos = listutils::findAttribute(
tupAttributes , tupAttrToFindName , tupAttrType);
if (tupAttrPos == 0) {
return listutils::typeError("incoming stream does not "
"contain attribute with name '" + tupAttrToFindName +"'");
}
std::string expectedDestAttrType;
if (IPoint::checkType(tupAttrType)) {
expectedDestAttrType = MPoint2::BasicType();
} else if (CcInt::checkType(tupAttrType)) {
expectedDestAttrType = CcInt::BasicType();
} else {
return listutils::typeError("expected attribute's '"
+ tupAttrToFindName
+ "' type in incoming stream to be any of "
+ IPoint::BasicType()
+ ", " + CcInt::BasicType()
+ ", but was " + nl->ToString(tupAttrType));
}
// find moving2 attr in relation
ListExpr relAttrType;
int relAttrPos = listutils::findAttribute(
relAttributes , relAttrToFindName , relAttrType);
if (relAttrPos == 0) {
return listutils::typeError("target relation does not "
"contain attribute with name '" + relAttrToFindName +"'");
}
if (nl->ToString(relAttrType) != expectedDestAttrType){
return listutils::typeError("attribute '"
+ tupAttrToFindName + "' of type "
+ nl->ToString(tupAttrType)
+ " in stream requires attribute of type "
+ expectedDestAttrType + " in target relation, but '"
+ relAttrToFindName + "' is of type "
+ nl->ToString(relAttrType));
}
if (numArgs == 5) {
return nl->ThreeElemList (
nl->SymbolAtom ( Symbols::APPEND ()) ,
nl->FourElemList (
nl->IntAtom(0), // dummy
nl->IntAtom(tupTidAttrPos),
nl->IntAtom(tupAttrPos),
nl->IntAtom(relAttrPos)) ,
arg_tuplestreamType);
}
// numArgs == 6
if(!CcInt::checkType(nl->First(nl->Sixth(args)))) {
return listutils::typeError("(optional) sixth argument must be of type "
+ CcInt::BasicType()
+ ", but got " + nl->ToString(nl->First(nl->Sixth(args))));
}
return nl->ThreeElemList (
nl->SymbolAtom ( Symbols::APPEND ()) ,
nl->ThreeElemList (
nl->IntAtom(tupTidAttrPos),
nl->IntAtom(tupAttrPos),
nl->IntAtom(relAttrPos)) ,
arg_tuplestreamType);
}
int AppendPositions_sf( ListExpr args ) {
// TODO: is there a way to pass information from the type mapping?
// How to select the correct version
cout << "AppendPositions_sf: " << nl->ToString(args) << endl;
return 0;
}
void sleepMode(int mode, int mode2, std::string message) {
if (mode == mode2) {
cout << "sleeping: '" << message << "'\n";
sleep (10);
cout << "sleeping done\n";
}
}
void handleIpoint(const BackReference& backRef,
Relation* relation,
const IPoint* ipoint,
const int transactionMode) {
Word word;
MemStorageId destMemId = MPoint2::findMemStorageId(backRef);
// TODO: refactor to:
// MemStorageId MPoint2::bringToMemory(backRef, commit_mode)
if (destMemId <= 0) { // no such Moving im Memory, check relation
Tuple* destTuple = relation->GetTuple(backRef.tupleId, true);
if (destTuple != 0) {
cout << "found tuple in relation: " << *destTuple << endl;
MPoint2* moving = static_cast<MPoint2*>(
destTuple->GetAttribute(backRef.attrPos));
cout << "also found MPoint2: " << *moving << endl;
MPoint2* moving_for_update = moving->Clone();
moving_for_update->SetBackReference(backRef);
vector<int> changedIndices(1);
changedIndices[0] = backRef.attrPos;
vector<Attribute*> newAttrs(1);
newAttrs[0] = moving_for_update;
// it seems that UpdateTuple does not incr ref count
// for newAttrs -> so do not delete(IfAllowed) moving_for_update.
relation->UpdateTuple(destTuple,
changedIndices,
newAttrs);
destTuple->DeleteIfAllowed();
if(transactionMode == 1) {
cout << "commiting....\n";
SmiEnvironment::CommitTransaction();
SmiEnvironment::BeginTransaction();
cout << "...done\n";
}
}
}
if (destMemId <= 0) {
cout << "no tuple found for '"
<< backRef << "'\n";
return;
}
Unit finalUnit = MPoint2::getFinalUnit(destMemId);
UPoint newUnit(0);
CreateExtensionUnit<IPoint, UPoint>(
&finalUnit,
ipoint,
&newUnit);
if (newUnit.IsDefined()) {
MPoint2::appendUnit(destMemId, newUnit);
} else {
cout << "couldn't create valid extension unit\n";
}
}
// return copy of original tuple
int AppendPositionsStreamRegular_vm
( Word* args, Word& result, int message, Word& local, Supplier s )
{
// 0:srcStream(tuple1) x 1:dstRelation(tuple2) x
// 2:srcTidName x 3:srcUnitName x 4:dstMovingName x
// 5:srcTidPos x 6:srcUnitPos x 7:dstMovingPos
cout << "int AppendPositionsStreamRegular_vm\n";
struct AppendPositions_LocalInfo{
AppendPositions_LocalInfo():
mode(0),
srcTidPos(0),
srcUnitPos(0),
dstMovingPos(0),
relationName(),
relation(0) {};
int mode;
int srcTidPos;
int srcUnitPos;
int dstMovingPos;
std::string relationName;
Relation* relation;
};
Word elem;
AppendPositions_LocalInfo *localInfo =
static_cast<AppendPositions_LocalInfo*>(local.addr);
Word t;
bool defined; // only needed in OPEN
Word word; // only needed in OPEN
SecondoCatalog* catalog; // only needed in OPEN
switch (message)
{
case OPEN :
localInfo = new AppendPositions_LocalInfo();
// we get indexes 1 based, but need them 0 based
localInfo->mode =
(static_cast<CcInt*>(args[5].addr))->GetIntval();
localInfo->srcTidPos =
(static_cast<CcInt*>(args[6].addr))->GetIntval() -1;
localInfo->srcUnitPos =
(static_cast<CcInt*>(args[7].addr))->GetIntval() -1;
localInfo->dstMovingPos =
(static_cast<CcInt*>(args[8].addr))->GetIntval() -1;
// we checked the presence of the relation during TypeMapping
// TODO: check if there is a way to ensure the Relation* stays valid
localInfo->relationName =
static_cast<FText*>(args[1].addr)->GetValue();
catalog = SecondoSystem::GetCatalog();
catalog->GetObject(localInfo->relationName, word, defined);
localInfo->relation = static_cast<Relation*>(word.addr);
local.setAddr(localInfo);
qp->Open(args[0].addr);
return 0;
case REQUEST :
if(!localInfo){ return CANCEL; }
qp->Request(args[0].addr,t);
if (qp->Received(args[0].addr))
{
Tuple* src_tuple = static_cast<Tuple*>(t.addr);
cout << "src_tuple: " << src_tuple
<< ", *src_tuple: " << *src_tuple << endl;
TupleIdentifier* srcTid_ptr =
static_cast<TupleIdentifier*>(
src_tuple->GetAttribute(localInfo->srcTidPos));
cout << "got Tuple identifier: " << srcTid_ptr->GetTid() << endl;
IPoint* srcIPoint_ptr =
static_cast<IPoint*>(
src_tuple->GetAttribute(localInfo->srcUnitPos));
cout << "got Unit identifier: " << *srcIPoint_ptr << endl;
BackReference backRef = BackReference(
localInfo->relationName,
srcTid_ptr->GetTid(),
localInfo->dstMovingPos
);
cout << "backRef: " << backRef << endl;
handleIpoint(backRef,
localInfo->relation,
srcIPoint_ptr,
localInfo->mode);
//TODO: maybe it makes more sense to pass on the updated tuple
// or even the original extended with the changes
// (as in UpdateRelationAlgebra)
// src_tup->DeleteIfAllowed(); // don't delete but - we pass it on
result.setAddr(src_tuple);
return YIELD;
}
else
return CANCEL;
case CLOSE :
qp->Close(args[0].addr);
if(localInfo)
{
delete localInfo;
local.setAddr(0);
}
return 0;
}
cout << "unhandled message: " << message << endl;
assert(false);
return -1;
}
ValueMapping AppendPositions_vms[] =
{
AppendPositionsStreamRegular_vm
// AppendPositions_vm<MBool, IBool>,
// AppendPositions_vm<MString, IString>,
// AppendPositions_vm<MInt, IInt>
// AppendPositions_vm<MReal, IReal>,
};
Operator* getAppendPositionsOpPtr() {
Operator* op = new Operator(
AppendPositionsInfo(),
AppendPositions_vms,
AppendPositions_sf,
AppendPositions_tm
);
op->SetUsesArgsInTypeMapping();
return op;
}
} // end of namespace temporal2algebra