blob: 976b9c6a8469e22a4ff6ac074ff9dd92b5dc94e7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef UNIVPLAN_SRC_UNIVPLAN_MINMAX_MINMAX_PREDICATES_H_
#define UNIVPLAN_SRC_UNIVPLAN_MINMAX_MINMAX_PREDICATES_H_
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "dbcommon/common/tuple-batch.h"
#include "dbcommon/common/tuple-desc.h"
#include "dbcommon/nodes/datum.h"
#include "univplan/common/expression.h"
#include "univplan/common/statistics.h"
#include "univplan/common/univplan-type.h"
#include "univplan/common/var-util.h"
namespace univplan {
class PredicateStats {
public:
PredicateStats() {}
virtual ~PredicateStats() {}
typedef std::unique_ptr<PredicateStats> uptr;
dbcommon::Scalar maxValue;
dbcommon::Scalar minValue;
bool hasAllNull = false;
bool hasMinMax = false;
};
class MinMaxPredicatesAbstract;
class MinMaxPredicatesPage;
class MinMaxPredicatesCO;
#define PREDPAGE(pred) (dynamic_cast<const MinMaxPredicatesPage*>(pred))
#define PREDCO(pred) (dynamic_cast<const MinMaxPredicatesCO*>(pred))
class PredicateOper {
public:
explicit PredicateOper(const MinMaxPredicatesAbstract* pred) : pred(pred) {}
virtual ~PredicateOper() {}
typedef std::unique_ptr<PredicateOper> uptr;
virtual bool canDrop() { return false; }
protected:
const MinMaxPredicatesAbstract* pred = nullptr;
};
class ListPredicate : public PredicateOper {
public:
ListPredicate(const univplan::UnivPlanExprPolyList* exprs,
const MinMaxPredicatesAbstract* pred);
~ListPredicate() {}
typedef std::unique_ptr<ListPredicate> uptr;
bool canDrop() override;
private:
std::vector<PredicateOper::uptr> children;
};
class BooleanPredicate : public PredicateOper {
public:
BooleanPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBoolExpr* op);
~BooleanPredicate() {}
typedef std::unique_ptr<BooleanPredicate> uptr;
protected:
std::vector<PredicateOper::uptr> children;
};
class VarPredicate : public PredicateOper {
public:
VarPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanVar* var)
: PredicateOper(pred), var(var) {}
~VarPredicate() {}
typedef std::unique_ptr<VarPredicate> uptr;
bool canDrop() override;
private:
const univplan::UnivPlanVar* var;
};
class BooleanTestPredicate : public PredicateOper {
public:
BooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: PredicateOper(pred), var(&op->arg().var()) {}
~BooleanTestPredicate() {}
typedef std::unique_ptr<BooleanTestPredicate> uptr;
protected:
const univplan::UnivPlanVar* var;
};
class IsTrueBooleanTestPredicate : public BooleanTestPredicate {
public:
IsTrueBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsTrueBooleanTestPredicate() {}
typedef std::unique_ptr<IsTrueBooleanTestPredicate> uptr;
bool canDrop() override;
};
class IsNotTrueBooleanTestPredicate : public BooleanTestPredicate {
public:
IsNotTrueBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsNotTrueBooleanTestPredicate() {}
typedef std::unique_ptr<IsNotTrueBooleanTestPredicate> uptr;
bool canDrop() override;
};
class IsFalseBooleanTestPredicate : public BooleanTestPredicate {
public:
IsFalseBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsFalseBooleanTestPredicate() {}
typedef std::unique_ptr<IsFalseBooleanTestPredicate> uptr;
bool canDrop() override;
};
class IsNotFalseBooleanTestPredicate : public BooleanTestPredicate {
public:
IsNotFalseBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsNotFalseBooleanTestPredicate() {}
typedef std::unique_ptr<IsNotFalseBooleanTestPredicate> uptr;
bool canDrop() override;
};
class IsUnknownBooleanTestPredicate : public BooleanTestPredicate {
public:
IsUnknownBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsUnknownBooleanTestPredicate() {}
typedef std::unique_ptr<IsUnknownBooleanTestPredicate> uptr;
bool canDrop() override;
};
class IsNotUnknownBooleanTestPredicate : public BooleanTestPredicate {
public:
IsNotUnknownBooleanTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBooleanTest* op)
: BooleanTestPredicate(pred, op) {}
~IsNotUnknownBooleanTestPredicate() {}
typedef std::unique_ptr<IsNotUnknownBooleanTestPredicate> uptr;
bool canDrop() override;
};
class AndPredicate : public BooleanPredicate {
public:
AndPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBoolExpr* op)
: BooleanPredicate(pred, op) {}
~AndPredicate() {}
typedef std::unique_ptr<AndPredicate> uptr;
bool canDrop() override;
};
class OrPredicate : public BooleanPredicate {
public:
OrPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanBoolExpr* op)
: BooleanPredicate(pred, op) {}
~OrPredicate() {}
typedef std::unique_ptr<OrPredicate> uptr;
bool canDrop() override;
};
class NullTestPredicate : public PredicateOper {
public:
NullTestPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanNullTest* op)
: PredicateOper(pred) {
if (!op->arg().has_var())
LOG_ERROR(ERRCODE_FEATURE_NOT_SUPPORTED,
"NullTestPredicate only work for simple expression");
univplan::VarUtil varUtil;
varAttrNo = varUtil.collectVarAttNo(
const_cast<univplan::UnivPlanExprPoly*>(&op->arg()));
}
~NullTestPredicate() {}
typedef std::unique_ptr<NullTestPredicate> uptr;
protected:
std::vector<int32_t> varAttrNo;
};
class IsNullPredicate : public NullTestPredicate {
public:
IsNullPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanNullTest* op)
: NullTestPredicate(pred, op) {}
~IsNullPredicate() {}
typedef std::unique_ptr<IsNullPredicate> uptr;
bool canDrop() override;
};
class IsNotNullPredicate : public NullTestPredicate {
public:
IsNotNullPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanNullTest* op)
: NullTestPredicate(pred, op) {}
~IsNotNullPredicate() {}
typedef std::unique_ptr<IsNotNullPredicate> uptr;
bool canDrop() override;
};
class CompPredicate : public PredicateOper {
public:
CompPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: PredicateOper(pred), expr(op) {
assert(op->args_size() == 2);
typeKinds.push_back(univplan::PlanNodeUtil::exprType(op->args(0)));
typeKinds.push_back(univplan::PlanNodeUtil::exprType(op->args(1)));
univplan::VarUtil varUtil;
varAttNo.push_back(varUtil.collectVarAttNo(
const_cast<univplan::UnivPlanExprPoly*>(&op->args(0))));
varAttNo.push_back(varUtil.collectVarAttNo(
const_cast<univplan::UnivPlanExprPoly*>(&op->args(1))));
}
~CompPredicate() {}
typedef std::unique_ptr<CompPredicate> uptr;
void addArg(ExprState::uptr arg) { args.push_back(std::move(arg)); }
bool isValidToPredicate() const;
protected:
PredicateStats::uptr calcLeft();
PredicateStats::uptr calcRight();
int32_t compareTo(const dbcommon::Scalar& s1, dbcommon::TypeKind t1,
const dbcommon::Scalar& s2, dbcommon::TypeKind t2);
private:
dbcommon::TupleBatch::uptr buildTupleBatch(int32_t argIndex);
PredicateStats::uptr doCalc(int32_t argIndex);
std::string covertPredicateTypeStr(std::string typeName);
protected:
std::vector<dbcommon::TypeKind> typeKinds;
const univplan::UnivPlanOpExpr* expr;
private:
std::vector<ExprState::uptr> args;
std::vector<std::vector<int32_t>> varAttNo;
dbcommon::Timestamp minTimestamp;
dbcommon::Timestamp maxTimestamp;
std::vector<dbcommon::TupleBatch::uptr> tbVec_;
};
class EqualPredicate : public CompPredicate {
public:
EqualPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~EqualPredicate() {}
typedef std::unique_ptr<EqualPredicate> uptr;
bool canDrop() override;
};
class NEPredicate : public CompPredicate {
public:
NEPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~NEPredicate() {}
typedef std::unique_ptr<NEPredicate> uptr;
bool canDrop() override;
};
class GTPredicate : public CompPredicate {
public:
GTPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~GTPredicate() {}
typedef std::unique_ptr<GTPredicate> uptr;
bool canDrop() override;
};
class GEPredicate : public CompPredicate {
public:
GEPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~GEPredicate() {}
typedef std::unique_ptr<GEPredicate> uptr;
bool canDrop() override;
};
class LTPredicate : public CompPredicate {
public:
LTPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~LTPredicate() {}
typedef std::unique_ptr<LTPredicate> uptr;
bool canDrop() override;
};
class LEPredicate : public CompPredicate {
public:
LEPredicate(const MinMaxPredicatesAbstract* pred,
const univplan::UnivPlanOpExpr* op)
: CompPredicate(pred, op) {}
~LEPredicate() {}
typedef std::unique_ptr<LEPredicate> uptr;
bool canDrop() override;
};
class MinMaxPredicatesAbstract {
public:
MinMaxPredicatesAbstract(const univplan::UnivPlanExprPolyList* predicateExprs,
const dbcommon::TupleDesc* tupleDesc)
: exprs(predicateExprs), td(tupleDesc) {}
virtual ~MinMaxPredicatesAbstract() {}
// facility for building general purpose predicate tree
static PredicateOper::uptr buildPredicateOper(
const univplan::UnivPlanExprPolyList* exprs,
const MinMaxPredicatesAbstract* owner);
static PredicateOper::uptr buildPredicateOper(
const univplan::UnivPlanExprPoly* expr,
const MinMaxPredicatesAbstract* owner);
const dbcommon::TupleDesc* getTupleDesc() const { return td; }
protected:
const univplan::UnivPlanExprPolyList* exprs; // original pushed filter
const dbcommon::TupleDesc* td; // full tuple desc
PredicateOper::uptr predicate; // generated predicate
};
class MinMaxPredicatesPage : public MinMaxPredicatesAbstract {
public:
MinMaxPredicatesPage(const Statistics* s,
const univplan::UnivPlanExprPolyList* predicateExprs,
const dbcommon::TupleDesc* tupleDesc)
: MinMaxPredicatesAbstract(predicateExprs, tupleDesc), stripeStats(s) {}
virtual ~MinMaxPredicatesPage() {}
typedef std::unique_ptr<MinMaxPredicatesPage> uptr;
virtual bool canDrop(); // page level min-max calculation interface
public:
virtual bool hasNull(int32_t colId) const = 0;
virtual bool hasAllNull(int32_t colId) const = 0;
virtual bool canDropByBloomFilter(int32_t colId, PredicateStats* stat,
dbcommon::TypeKind type) const = 0;
virtual PredicateStats getMinMax(int32_t colId) const = 0;
virtual PredicateStats getMinMax(int32_t colId,
dbcommon::Timestamp* minTimestamp,
dbcommon::Timestamp* maxTimestamp) const = 0;
protected:
const Statistics* stripeStats;
};
class COBlockTask {
public:
COBlockTask(uint64_t offset, uint64_t beginRowId, uint64_t rowCount)
: offset(offset),
beginRowId(beginRowId),
rowCount(rowCount),
taskBeginRowId(beginRowId),
taskRowCount(rowCount),
lastTaskBeginRowId(0),
lastTaskRowCount(0),
intersected(false) {}
COBlockTask(uint64_t offset, uint64_t beginRowId, uint64_t rowCount,
uint64_t taskBeginRowId, uint64_t taskRowCount)
: offset(offset),
beginRowId(beginRowId),
rowCount(rowCount),
taskBeginRowId(taskBeginRowId),
taskRowCount(taskRowCount),
lastTaskBeginRowId(0),
lastTaskRowCount(0),
intersected(false) {
LOG_DEBUG("CO block task %llu %llu %llu %llu %llu", offset, beginRowId,
rowCount, taskBeginRowId, taskRowCount);
}
typedef std::unique_ptr<COBlockTask> uptr;
public:
inline uint64_t getEndRowId() const { return beginRowId + rowCount - 1; }
inline uint64_t getTaskEndRowId() const {
return taskBeginRowId + taskRowCount - 1;
}
inline uint64_t getLastTaskEndRowId() const {
return lastTaskBeginRowId + lastTaskRowCount - 1;
}
inline void resetIntersection() {
intersected = false;
lastTaskBeginRowId = taskBeginRowId;
lastTaskRowCount = taskRowCount;
taskRowCount = 0;
}
inline void resetUnionAll() {
lastTaskBeginRowId = taskBeginRowId;
lastTaskRowCount = taskRowCount;
}
inline void intersect(const COBlockTask& srcTask) {
if (srcTask.getTaskEndRowId() < lastTaskBeginRowId ||
srcTask.taskBeginRowId > this->getLastTaskEndRowId()) {
if (!intersected) {
if (srcTask.getEndRowId() < this->lastTaskBeginRowId) {
// does not touch existing job, so restore original version
taskBeginRowId = lastTaskBeginRowId;
taskRowCount = lastTaskRowCount;
intersected = true;
} else if (srcTask.getEndRowId() <= this->getLastTaskEndRowId()) {
// restore partial job
taskBeginRowId = srcTask.getEndRowId() + 1;
taskRowCount = this->getLastTaskEndRowId() - taskBeginRowId + 1;
intersected = true;
}
return;
}
}
if (!intersected) {
// fix task begin row id, the source task may have smaller task begin row
// id, thus check to make sure this task has valid task begin row id. end
// row id has the same problem as well.
taskBeginRowId = srcTask.taskBeginRowId < taskBeginRowId
? taskBeginRowId
: srcTask.taskBeginRowId;
uint64_t tmpTaskEndRowId = srcTask.getTaskEndRowId();
tmpTaskEndRowId = tmpTaskEndRowId > this->getLastTaskEndRowId()
? this->getLastTaskEndRowId()
: tmpTaskEndRowId;
taskRowCount = tmpTaskEndRowId - taskBeginRowId + 1;
intersected = true;
} else {
// dont check begin row id again, as we expect srce tasks are processed
// in ascending order, and we use last task row id range to perform
// intersection
uint64_t tmpTaskEndRowId = srcTask.getTaskEndRowId();
tmpTaskEndRowId = tmpTaskEndRowId > this->getLastTaskEndRowId()
? this->getLastTaskEndRowId()
: tmpTaskEndRowId;
taskRowCount = tmpTaskEndRowId - taskBeginRowId + 1;
}
}
inline void unionAll(const COBlockTask& srcTask) {
if (srcTask.getTaskEndRowId() < beginRowId ||
srcTask.taskBeginRowId > this->getEndRowId()) {
// skip this part, as no overlap in row id range
return;
}
// we always check its possible new begin rowid and it should not go out of
// current task range
taskBeginRowId = taskBeginRowId > srcTask.taskBeginRowId
? srcTask.taskBeginRowId
: taskBeginRowId;
taskBeginRowId = taskBeginRowId < beginRowId ? beginRowId : taskBeginRowId;
// then is its end rowid
uint64_t tmpTaskEndRowId = srcTask.getTaskEndRowId();
tmpTaskEndRowId = tmpTaskEndRowId > this->getTaskEndRowId()
? tmpTaskEndRowId
: this->getTaskEndRowId();
tmpTaskEndRowId = tmpTaskEndRowId > this->getEndRowId()
? this->getEndRowId()
: tmpTaskEndRowId;
taskRowCount = tmpTaskEndRowId - taskBeginRowId + 1;
}
public:
uint64_t offset;
uint64_t beginRowId;
uint64_t rowCount;
uint64_t taskBeginRowId;
uint64_t taskRowCount;
uint64_t lastTaskBeginRowId;
uint64_t lastTaskRowCount;
private:
bool intersected;
};
class COBlockTaskList {
public:
COBlockTaskList();
void add(COBlockTask::uptr task) {
uint64_t taskBeginRowId = task->taskBeginRowId;
taskList[taskBeginRowId] = std::move(task);
}
void intersect(const COBlockTaskList& source);
void unionAll(const COBlockTaskList& source);
typedef std::unique_ptr<COBlockTaskList> uptr;
public:
std::map<uint64_t, COBlockTask::uptr> taskList;
};
class MinMaxPredicatesCO : public MinMaxPredicatesAbstract {
public:
MinMaxPredicatesCO(const univplan::UnivPlanExprPolyList* predicateExprs,
const dbcommon::TupleDesc* tupleDesc)
: MinMaxPredicatesAbstract(predicateExprs, tupleDesc) {}
virtual ~MinMaxPredicatesCO() {}
// methods implemented by sub-class to provide customized data preparation
virtual void preparePredicatesForStrip() = 0;
virtual COBlockTask::uptr buildCOTaskFromCurrentStrip(int colId) = 0;
// methods of whole calculation framework
virtual void preparePredicates();
virtual void calculate(std::unordered_map<int, COBlockTaskList::uptr>* res);
protected:
// holding one strip's statistics
std::unique_ptr<univplan::Statistics> stripStatistics;
// holding one page level predicates to do actual calculation
std::unique_ptr<MinMaxPredicatesPage> predicatesForPages;
};
} // namespace univplan
#endif // UNIVPLAN_SRC_UNIVPLAN_MINMAX_MINMAX_PREDICATES_H_