Files
secondo/Algebras/CRel/Operators/ApplyPredicate.cpp
2026-01-23 17:03:45 +08:00

221 lines
5.8 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
SECONDO is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#include "ApplyPredicate.h"
#include "Attribute.h"
#include "AttrArray.h"
#include <cstdint>
#include <exception>
#include "Ints.h"
#include "../TypeConstructors/LongIntsTC.h"
#include "LogMsg.h"
#include "OperatorUtils.h"
#include "QueryProcessor.h"
#include "Algebras/Relation-C++/RelationAlgebra.h"
#include "SecondoSystem.h"
#include "StandardTypes.h"
#include <string>
#include "Symbols.h"
#include "TypeUtils.h"
#include <vector>
using namespace CRelAlgebra;
using namespace CRelAlgebra::Operators;
using std::exception;
using std::string;
using std::vector;
extern NestedList *nl;
extern QueryProcessor *qp;
//ApplyPredicate----------------------------------------------------------------
ApplyPredicate::ApplyPredicate() :
Operator(info, valueMappings, SelectValueMapping, TypeMapping)
{
}
ValueMapping ApplyPredicate::valueMappings[] =
{
AttrArrayValueMapping,
TBlockValueMapping,
nullptr
};
const OperatorInfo ApplyPredicate::info = OperatorInfo(
"apply", "(ATTRARRAY | tblock) x (map BLOCKENTRY bool) -> longints",
"_ apply[ fun ]",
"Determines the indices of those entries in the array / tblock whose "
"attribute / tuple representations fullfill the predicate function.\n"
"The returned indices are in ascending order.",
"query [const longints value (1 2 3)] apply[. >= 2] consume");
ListExpr ApplyPredicate::TypeMapping(ListExpr args)
{
//Expect two arguments
if(!nl->HasLength(args,2))
{
return GetTypeError("Two arguments expected.");
}
//Check the first argument for attrarray or tblock
const ListExpr firstArg = nl->First(args);
ListExpr expectedMapArg;
if (TBlockTI::Check(firstArg))
{
expectedMapArg = TBlockTI(firstArg, false).GetTupleTypeExpr();
}
else
{
AttrArrayTypeConstructor *constructor =
AttrArray::GetTypeConstructor(firstArg);
if (constructor == nullptr)
{
return GetTypeError(0, "Isn't tblock or ATTRARRAY.");
}
expectedMapArg = constructor->GetAttributeType(firstArg, false);
}
//Check the second argument for function type
//Compare the arrays Attribute-Type with the functions parameter type
//Check the functions result type
const ListExpr mapType = nl->Second(args);
if(!nl->HasLength(mapType, 3) ||
!nl->IsEqual(nl->First(mapType), Symbols::MAP()) ||
!nl->Equal(nl->Second(mapType), expectedMapArg) ||
!CcBool::checkType(nl->Third(mapType)))
{
const ListExpr expectedMapType =
nl->ThreeElemList(nl->SymbolAtom(Symbols::MAP()), expectedMapArg,
nl->SymbolAtom(CcBool::BasicType()));
return GetTypeError(1, "map", "Expected " + nl->ToString(expectedMapType) +
".");
}
//Result type is 'indices'
return LongIntsTI(false).GetTypeExpr();
}
int ApplyPredicate::SelectValueMapping(ListExpr args)
{
return TBlockTI::Check(nl->First(args)) ? 1 : 0;
}
int ApplyPredicate::AttrArrayValueMapping(ArgVector args, Word &result, int,
Word&, Supplier s)
{
try
{
//The function
const Supplier predicate = args[1].addr;
//The function's parameter
Address &predicateArg = (*qp->Argument(predicate))[0].addr;
//The indices which satisfy the predicate
LongInts &indices = qp->ResultStorage<LongInts>(result, s);
indices.Clear();
for (const AttrArrayEntry &entry : ((AttrArray*)args[0].addr)->GetFilter())
{
Attribute *attribute = entry.GetAttribute();
predicateArg = attribute;
CcBool &predicateResult = *(CcBool*)qp->Request(predicate).addr;
attribute->DeleteIfAllowed();
if (predicateResult.IsDefined() && predicateResult.GetValue())
{
indices.Append(entry.GetRow());
}
}
return 0;
}
catch (const exception &e)
{
ErrorReporter::ReportError(e.what());
}
return FAILURE;
}
int ApplyPredicate::TBlockValueMapping(ArgVector args, Word &result, int,
Word&, Supplier s)
{
try
{
//The function
const Supplier predicate = args[1].addr;
//The indices which satisfy the predicate
LongInts &indices = qp->ResultStorage<LongInts>(result, s);
indices.Clear();
const TBlock &block = *(TBlock*)args[0].addr;
const uint64_t columnCount = block.GetColumnCount();
const ListExpr tupleType =
TBlockTI(qp->GetType(qp->GetSon(s, 0)), false).GetTupleTypeExpr();
Tuple tuple(SecondoSystem::GetCatalog()->NumericType(tupleType));
//The function's parameter
(*qp->Argument(predicate))[0].addr = &tuple;
for (const TBlockEntry &entry : block.GetFilter())
{
for (uint64_t i = 0; i < columnCount; ++i)
{
tuple.PutAttribute(i, entry[i].GetAttribute());
}
CcBool &predicateResult = *(CcBool*)qp->Request(predicate).addr;
if (predicateResult.IsDefined() && predicateResult.GetValue())
{
indices.Append(entry.GetRow());
}
}
return 0;
}
catch (const exception &e)
{
ErrorReporter::ReportError(e.what());
}
return FAILURE;
}