blob: a7255b70654ffbbe77605e8d1fa128cc030d7cd8 [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.
*/
#include "univplan/common/expression.h"
#include <algorithm>
#include "dbcommon/common/tuple-batch.h"
#include "dbcommon/common/vector/fixed-length-vector.h"
#include "dbcommon/common/vector/list-vector.h"
#include "dbcommon/common/vector/struct-vector.h"
#include "dbcommon/common/vector/variable-length-vector.h"
#include "dbcommon/function/func-kind.cg.h"
#include "dbcommon/log/logger.h"
#include "dbcommon/type/array.h"
#include "dbcommon/type/type-util.h"
namespace univplan {
dbcommon::SelectList *ExprState::convertSelectList(const dbcommon::Datum &d,
ExprContext *context) {
dbcommon::Object *obj = dbcommon::DatumGetValue<dbcommon::Object *>(d);
dbcommon::SelectList *sel = nullptr;
dbcommon::BooleanVector *vec = nullptr;
dbcommon::Scalar *val = nullptr;
if ((sel = dynamic_cast<dbcommon::SelectList *>(obj)) == nullptr) {
if (convertedSelectlist == nullptr)
convertedSelectlist.reset(new dbcommon::SelectList);
sel = convertedSelectlist.get();
if ((vec = dynamic_cast<dbcommon::BooleanVector *>(obj)) != nullptr) {
sel->fromVector(vec);
} else if ((val = dynamic_cast<dbcommon::Scalar *>(obj)) != nullptr) {
sel->clear();
if (val->getBoolValue()) {
auto size = context->getNumOfRows();
sel->resize(size);
for (auto i = 0; i < size; i++) (*sel)[i] = i;
}
} else {
LOG_ERROR(ERRCODE_INTERNAL_ERROR,
"Supposed to be SelectList or BooleanVector or Const");
}
}
return sel;
}
ListExprState::ListExprState(const univplan::UnivPlanExprPolyList *exprs) {
for (int i = 0; i < exprs->size(); ++i) {
args.push_back(InitExpr(&exprs->Get(i)));
}
}
dbcommon::Datum ListExprState::calc(ExprContext *context) {
dbcommon::SelectList *result = nullptr;
for (ExprState::uptr &e : args) {
dbcommon::Datum d = e->calc(context);
dbcommon::SelectList *sel = convertSelectList(d, context);
if (result) {
retval.resize(result->size() + sel->size());
auto end =
std::set_intersection(result->begin(), result->end(), sel->begin(),
sel->end(), retval.begin());
retval.resize(end - retval.begin());
result->swap(retval);
} else {
result = sel;
}
}
return dbcommon::CreateDatum(result);
}
dbcommon::Datum VarExprState::calc(ExprContext *context) {
int32_t columnIndex = var->varattno() - 1;
dbcommon::TupleBatch *batch = nullptr;
if (var->varno() == INNER_VAR) {
batch = context->innerBatch;
} else if (var->varno() == OUTER_VAR) {
batch = context->outerBatch;
} else {
batch = context->scanBatch;
}
if (context->tupleIterValid() && !batch->isScalarTupleBatch()) {
batch->getColumn(columnIndex)->readPlainScalar(context->tupleIdx, &scalar);
return dbcommon::CreateDatum<dbcommon::Scalar *>(&scalar);
}
dbcommon::Vector *ret;
if (columnIndex >= 0) {
// Case 1. Relation attribute
ret = batch->getColumn(columnIndex);
} else {
// Case 2. System attribute
LOG_ERROR(
ERRCODE_FEATURE_NOT_SUPPORTED,
"System attribute is not supported in univplan::VarExprState::calc");
}
return CreateDatum(ret);
}
ConstExprState::ConstExprState(const univplan::UnivPlanConst *val)
: scalar(dbcommon::Datum(static_cast<int64_t>(0))) {
retType = univplan::PlanNodeUtil::typeKindMapping(val->type());
retTypeMod = val->typemod();
if (val->isnull()) {
scalar.isnull = true;
} else if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::TIMESTAMPID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::TIMESTAMPTZID) {
scalar.value = dbcommon::CreateDatum(
val->value().c_str(), &ts,
univplan::PlanNodeUtil::typeKindMapping(val->type()));
} else if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::DECIMALID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::DECIMALNEWID) {
dbcommon::DecimalType t;
decimalReg = t.fromString(val->value().c_str());
scalar.value = dbcommon::CreateDatum(&decimalReg);
} else if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::INTERVALID) {
intervalReg = dbcommon::IntervalType::fromString(val->value().c_str());
scalar.value = dbcommon::CreateDatum(&intervalReg);
} else if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::BINARYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::IOBASETYPEID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::STRUCTEXID) {
auto srcStr = val->value().c_str();
auto srcLen = val->value().size();
uint32_t dstLen = 0;
binary.resize(srcLen + sizeof(dstLen));
for (auto i = 0; i < srcLen;) {
if (srcStr[i] != '\\') {
binary[dstLen++] = srcStr[i];
i += 1;
} else if (srcStr[i + 1] == '\\') {
binary[dstLen++] = '\\';
i += 2;
} else {
binary[dstLen++] = (srcStr[i + 1] - '0') * 64 +
(srcStr[i + 2] - '0') * 8 + (srcStr[i + 3] - '0');
i += 4;
}
}
scalar.value = dbcommon::CreateDatum<char *>(&binary[0]);
scalar.length = dstLen;
} else if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::SMALLINTARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::INTARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::BIGINTARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::FLOATARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::DOUBLEARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::STRINGARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::BPCHARARRAYID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::DECIMAL128ARRAYID) {
auto typeEnt = reinterpret_cast<dbcommon::ArrayType *>(
dbcommon::TypeUtil::instance()
->getTypeEntryById(
univplan::PlanNodeUtil::typeKindMapping(val->type()))
->type.get());
array = std::move(typeEnt->getScalarFromString(val->value()));
scalar.value = dbcommon::CreateDatum(array.get());
} else {
scalar.value = dbcommon::CreateDatum(
val->value().c_str(),
univplan::PlanNodeUtil::typeKindMapping(val->type()));
}
if (univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::STRINGID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::VARCHARID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::CHARID ||
univplan::PlanNodeUtil::typeKindMapping(val->type()) ==
dbcommon::TypeKind::DECIMALNEWID) {
scalar.length = val->value().length();
}
}
dbcommon::Datum ConstExprState::calc(ExprContext *context) {
return dbcommon::CreateDatum(&scalar);
}
OpExprState::OpExprState(const univplan::UnivPlanOpExpr *op)
: invoker(univplan::PlanNodeUtil::funcKindMapping(op->funcid())) {
const dbcommon::FuncEntry *entry =
dbcommon::Func::instance()->getFuncEntryById(
univplan::PlanNodeUtil::funcKindMapping(op->funcid()));
retType = entry->retType;
}
OpExprState::OpExprState(dbcommon::FuncKind funcId) : invoker(funcId) {
const dbcommon::FuncEntry *entry =
dbcommon::Func::instance()->getFuncEntryById(
univplan::PlanNodeUtil::funcKindMapping(funcId));
retType = entry->retType;
}
dbcommon::Datum OpExprState::calc(ExprContext *context) {
invoker.resetPrarmeter();
invoker.addParam(dbcommon::CreateDatum(0));
assert(args.size() == 2 || args.size() == 1);
for (ExprState::uptr &arg : args) {
invoker.addParam(arg->calc(context));
}
if (retval) {
retval->clear();
} else {
bool isRetvalVector = true;
if (args.size() == 2) {
dbcommon::Object *paraL =
dbcommon::DatumGetValue<dbcommon::Object *>(invoker.getParam(1));
dbcommon::Vector *vecL = dynamic_cast<dbcommon::Vector *>(paraL);
dbcommon::Object *paraR =
dbcommon::DatumGetValue<dbcommon::Object *>(invoker.getParam(2));
dbcommon::Vector *vecR = dynamic_cast<dbcommon::Vector *>(paraR);
isRetvalVector = vecL || vecR;
} else if (args.size() == 1) {
dbcommon::Object *para =
dbcommon::DatumGetValue<dbcommon::Object *>(invoker.getParam(1));
isRetvalVector = dynamic_cast<dbcommon::Vector *>(para);
}
if (isRetvalVector) {
if (retType == dbcommon::TypeKind::BOOLEANID)
retval = std::unique_ptr<dbcommon::Object>(new dbcommon::SelectList);
else
retval = dbcommon::Vector::BuildVector(retType, true, retTypeMod);
} else {
retval = std::unique_ptr<dbcommon::Object>(new dbcommon::Scalar);
}
}
invoker.setParam(0, dbcommon::CreateDatum<dbcommon::Object *>(retval.get()));
return invoker.invoke();
}
dbcommon::Datum FuncExprState::calc(ExprContext *context) {
invoker.resetPrarmeter();
invoker.addParam(dbcommon::CreateDatum(0));
for (ExprState::uptr &arg : args) {
invoker.addParam(arg->calc(context));
}
if (retval) {
retval->clear();
} else {
bool isVecFunc = false;
for (size_t i = 1; i <= args.size(); i++) {
dbcommon::Object *para =
dbcommon::DatumGetValue<dbcommon::Object *>(invoker.getParam(i));
dbcommon::Vector *vec = dynamic_cast<dbcommon::Vector *>(para);
if (vec) {
isVecFunc = true;
break;
}
}
if (func->funcid() == dbcommon::FuncKind::RANDOMF) isVecFunc = true;
if (!isVecFunc) {
retval = std::unique_ptr<dbcommon::Object>(new dbcommon::Scalar);
} else {
dbcommon::TypeKind rettype =
univplan::PlanNodeUtil::typeKindMapping(func->rettype());
if (rettype == dbcommon::TypeKind::BOOLEANID)
retval = std::unique_ptr<dbcommon::Object>(new dbcommon::SelectList);
else
retval = dbcommon::Vector::BuildVector(rettype, true);
}
}
invoker.setParam(0, dbcommon::CreateDatum<dbcommon::Object *>(retval.get()));
if (func->funcid() == dbcommon::FuncKind::RANDOMF) {
invoker.addParam(dbcommon::CreateDatum(context->outerBatch != nullptr
? context->outerBatch
: context->scanBatch));
}
return invoker.invoke();
}
dbcommon::Datum NullTestState::calc(ExprContext *context) {
assert(args.size() == 1);
auto obj =
dbcommon::DatumGetValue<dbcommon::Object *>(args[0]->calc(context));
if (auto scalar = dynamic_cast<dbcommon::Scalar *>(obj)) {
scalarResult_.value = dbcommon::CreateDatum<bool>(scalar->isnull == isNull);
return dbcommon::CreateDatum(&scalarResult_);
} else {
auto vec = reinterpret_cast<dbcommon::Vector *>(obj);
size_t size = vec->getNumOfRows();
result.resize(0);
for (size_t i = 0; i < size; ++i) {
bool null = vec->isNull(i);
if (null == isNull) {
result.push_back(vec->getPlainIndex(i));
}
}
}
return dbcommon::CreateDatum(&result);
}
dbcommon::Datum BooleanTestState::calc(ExprContext *context) {
assert(args.size() == 1);
for (ExprState::uptr &arg : args) {
dbcommon::Vector *vec =
dbcommon::DatumGetValue<dbcommon::Vector *>(arg->calc(context));
size_t size = vec->getNumOfRows();
result.reset(new dbcommon::SelectList);
result->reserve(size);
const bool *val = reinterpret_cast<const bool *>(vec->getValue());
for (size_t i = 0; i < size; ++i) {
uint64_t index = vec->getPlainIndex(i);
bool null = vec->isNullPlain(index);
if (op->type() == univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_TRUE) {
if (!null && val[index]) result->push_back(index);
} else if (op->type() ==
univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_NOT_TRUE) {
if (null || !val[index]) result->push_back(index);
} else if (op->type() == univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_FALSE) {
if (!null && !val[index]) result->push_back(index);
} else if (op->type() ==
univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_NOT_FALSE) {
if (null || val[index]) result->push_back(index);
} else if (op->type() ==
univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_UNKNOWN) {
if (null) result->push_back(index);
} else {
assert(op->type() ==
univplan::BOOLTESTTYPE::BOOLTESTTYPE_IS_NOT_UNKNOWN);
if (!null) result->push_back(index);
}
}
}
return dbcommon::CreateDatum(result.get());
}
dbcommon::Datum BoolExprState::calc(ExprContext *context) {
if (op == univplan::BOOLEXPRTYPE::BOOLEXPRTYPE_OR_EXPR) {
return calcOr(context);
} else if (op == univplan::BOOLEXPRTYPE::BOOLEXPRTYPE_NOT_EXPR) {
return calcNot(context);
} else {
assert(op == univplan::BOOLEXPRTYPE::BOOLEXPRTYPE_AND_EXPR);
return calcAnd(context);
}
}
dbcommon::Datum BoolExprState::calcAnd(ExprContext *context) {
assert(args.size() >= 2);
backupSel_ = context->releaseSelected();
dbcommon::SelectList *backupSel = context->getSelectList();
dbcommon::Object *para0 = args[0]->calc(context);
if (dynamic_cast<dbcommon::Scalar *>(para0))
LOG_ERROR(ERRCODE_FEATURE_NOT_SUPPORTED, "Feature not supported");
if (dynamic_cast<dbcommon::SelectList *>(para0)) {
if (retval == nullptr)
retval =
dbcommon::Vector::BuildVector(dbcommon::TypeKind::BOOLEANID, true);
reinterpret_cast<dbcommon::SelectList *>(para0)->toVector(
reinterpret_cast<dbcommon::Vector *>(retval.get()));
} else {
retval =
reinterpret_cast<dbcommon::Vector *>(para0)->cloneSelected(nullptr);
}
dbcommon::Vector *retVector =
reinterpret_cast<dbcommon::Vector *>(retval.get());
std::unique_ptr<dbcommon::Vector> tmpVectorBackup;
for (auto i = 1; i < args.size(); i++) {
auto &it = args[i];
dbcommon::Object *para = it->calc(context);
auto lhsVector = retVector->cloneSelected(nullptr);
dbcommon::Vector *rhsVector = reinterpret_cast<dbcommon::Vector *>(para);
if (dynamic_cast<dbcommon::Scalar *>(para))
LOG_ERROR(ERRCODE_FEATURE_NOT_SUPPORTED, "Feature not supported");
if (auto sel = dynamic_cast<dbcommon::SelectList *>(para)) {
if (tmpVectorBackup == nullptr)
tmpVectorBackup =
dbcommon::Vector::BuildVector(dbcommon::TypeKind::BOOLEANID, true);
rhsVector = tmpVectorBackup.get();
sel->toVector(rhsVector);
}
dbcommon::FixedSizeTypeVectorRawData<bool> lhs(lhsVector.get());
dbcommon::FixedSizeTypeVectorRawData<bool> rhs(rhsVector);
retVector->resize(context->getNumOfRowsPlain(), nullptr, lhs.nulls,
rhs.nulls);
dbcommon::FixedSizeTypeVectorRawData<bool> ret(retVector);
auto setBoolean = [&](uint64_t plainIdx) {
ret.values[plainIdx] = lhs.values[plainIdx] & rhs.values[plainIdx];
};
dbcommon::transformVector(ret.plainSize, nullptr, nullptr, setBoolean);
if (ret.nulls) {
auto setNullFromLhs = [&](uint64_t plainIdx) {
if (lhs.values[plainIdx] == false)
const_cast<bool *>(ret.nulls)[plainIdx] = false;
};
dbcommon::transformVector(ret.plainSize, nullptr, lhs.nulls,
setNullFromLhs);
auto setNullFromRhs = [&](uint64_t plainIdx) {
if (rhs.values[plainIdx] == false)
const_cast<bool *>(ret.nulls)[plainIdx] = false;
};
dbcommon::transformVector(ret.plainSize, nullptr, rhs.nulls,
setNullFromRhs);
}
}
context->setSelected(backupSel);
auto retsel = convertSelectList(dbcommon::CreateDatum(retVector), context);
return dbcommon::CreateDatum(retsel);
}
dbcommon::Datum BoolExprState::calcOr(ExprContext *context) {
assert(args.size() >= 2);
backupSel_ = context->releaseSelected();
dbcommon::SelectList *backupSel = context->getSelectList();
if (retval == nullptr) retval.reset(new dbcommon::SelectList);
retval->clear();
dbcommon::SelectList *retsel =
static_cast<dbcommon::SelectList *>(retval.get());
retsel->setPlainSize(0);
dbcommon::Datum d = args[0]->calc(context);
dbcommon::SelectList *sel = convertSelectList(d, context);
*retsel = *sel;
for (auto i = 1; i < args.size(); i++) {
auto &it = args[i];
dbcommon::Datum d = it->calc(context);
dbcommon::SelectList *sel = convertSelectList(d, context);
dbcommon::SelectList tmp = *retsel;
retsel->resize(tmp.size() + sel->size());
auto end = std::set_union(tmp.begin(), tmp.end(), sel->begin(), sel->end(),
retsel->begin());
retsel->resize(end - retsel->begin());
retsel->setNulls(context->getNumOfRowsPlain(), nullptr, tmp.getNulls(),
sel->getNulls());
}
retsel->setNulls(context->getNumOfRowsPlain(), retsel, false);
context->setSelected(backupSel);
return dbcommon::CreateDatum(retval.get());
}
dbcommon::Datum BoolExprState::calcNot(ExprContext *context) {
assert(args.size() == 1);
backupSel_ = context->releaseSelected();
dbcommon::SelectList *backupSel = context->getSelectList();
dbcommon::Datum d = args.front()->calc(context);
if (auto sel = dynamic_cast<dbcommon::SelectList *>(
dbcommon::DatumGetValue<dbcommon::Object *>(d))) {
if (retval == nullptr) retval.reset(new dbcommon::SelectList);
auto retsel = reinterpret_cast<dbcommon::SelectList *>(retval.get());
*retsel = sel->getComplement(context->getNumOfRowsPlain());
retsel->setNulls(context->getNumOfRowsPlain(), nullptr, sel->getNulls());
if (backupSel) {
auto end = std::set_intersection(retsel->begin(), retsel->end(),
backupSel->begin(), backupSel->end(),
retsel->begin());
retsel->resize(end - retsel->begin());
}
} else if (dbcommon::BooleanVector *vec =
dynamic_cast<dbcommon::BooleanVector *>(
dbcommon::DatumGetValue<dbcommon::Object *>(d))) {
if (retval == nullptr) retval.reset(new dbcommon::SelectList);
auto retsel = reinterpret_cast<dbcommon::SelectList *>(retval.get());
dbcommon::SelectList tmp;
tmp.fromVector(vec);
*retsel = tmp.getComplement(context->getNumOfRowsPlain());
retsel->setNulls(context->getNumOfRowsPlain(), nullptr, tmp.getNulls());
if (backupSel) {
auto end = std::set_intersection(retsel->begin(), retsel->end(),
backupSel->begin(), backupSel->end(),
retsel->begin());
retsel->resize(end - retsel->begin());
}
} else {
dbcommon::Scalar *scalar = static_cast<dbcommon::Scalar *>(
dbcommon::DatumGetValue<dbcommon::Object *>(d));
if (scalar->value.value.i8)
scalar->value.value.i8 = 0;
else
scalar->value.value.i8 = 1;
retval.reset(new dbcommon::Scalar(*scalar));
}
context->setSelected(backupSel);
return dbcommon::CreateDatum(retval.get());
}
ExprState::uptr InitExpr(const univplan::UnivPlanExprPolyList *exprs) {
return ExprState::uptr(new ListExprState(exprs));
}
ExprState::uptr InitExpr(const univplan::UnivPlanExprPoly *expr) {
switch (expr->type()) {
case univplan::UNIVPLAN_EXPR_VAR:
return ExprState::uptr(new VarExprState(&expr->var()));
case univplan::UNIVPLAN_EXPR_CONST:
return ExprState::uptr(new ConstExprState(&expr->val()));
case univplan::UNIVPLAN_EXPR_TARGETENTRY:
return InitExpr(&expr->targetentry().expression());
case univplan::UNIVPLAN_EXPR_OPEXPR: {
const univplan::UnivPlanOpExpr &op = expr->opexpr();
bool predictable =
dbcommon::Func::instance()
->getFuncEntryById(static_cast<dbcommon::FuncKind>(op.funcid()))
->predictable;
if (!predictable)
LOG_ERROR(ERRCODE_INTERNAL_ERROR, "FuncExpr %d is not predictable",
op.funcid());
OpExprState::uptr retval(new OpExprState(&op));
for (int i = 0; i < op.args_size(); ++i)
retval->addArg(InitExpr(&op.args(i)));
return std::move(retval);
}
case univplan::UNIVPLAN_EXPR_FUNCEXPR: {
const univplan::UnivPlanFuncExpr &func = expr->funcexpr();
bool predictable =
dbcommon::Func::instance()
->getFuncEntryById(static_cast<dbcommon::FuncKind>(func.funcid()))
->predictable;
if (!predictable)
LOG_ERROR(ERRCODE_INTERNAL_ERROR, "FuncExpr %d is not predictable",
func.funcid());
FuncExprState::uptr retval(new FuncExprState(&func));
for (int i = 0; i < func.args_size(); ++i)
retval->addArg(InitExpr(&func.args(i)));
return std::move(retval);
}
case univplan::UNIVPLAN_EXPR_NULLTEST: {
const univplan::UnivPlanNullTest &op = expr->nulltest();
NullTestState::uptr retval(new NullTestState(&op));
retval->addArg(InitExpr(&op.arg()));
return std::move(retval);
}
case univplan::UNIVPLAN_EXPR_BOOLEANTEST: {
const univplan::UnivPlanBooleanTest &op = expr->booltest();
BooleanTestState::uptr retval(new BooleanTestState(&op));
retval->addArg(InitExpr(&op.arg()));
return std::move(retval);
}
case univplan::UNIVPLAN_EXPR_BOOLEXPR: {
const univplan::UnivPlanBoolExpr &op = expr->boolexpr();
BoolExprState::uptr retval(new BoolExprState(&op));
for (int i = 0; i < op.args_size(); ++i)
retval->addArg(InitExpr(&op.args(i)));
return std::move(retval);
}
default:
LOG_ERROR(ERRCODE_INTERNAL_ERROR, "expr type %d is not predictable",
expr->type());
}
return nullptr;
}
bool do_opexpr2(int col, const univplan::UnivPlanOpExpr &op,
std::vector<std::unique_ptr<IndexExpr> > &allExpr, // NOLINT
std::vector<std::unique_ptr<IndexExpr> > &equalExpr, // NOLINT
int *equal) {
std::unique_ptr<IndexExpr> idx(new IndexExpr());
const univplan::UnivPlanVar &var = op.args(0).var();
int att = var.varattno();
int typeId = var.typeid_();
if (typeId == dbcommon::TypeKind::DECIMALID ||
typeId == dbcommon::TypeKind::BOOLEANID) {
return false;
}
int modify = var.typemod();
std::string funcName =
dbcommon::Func::instance()
->getFuncEntryById(static_cast<dbcommon::FuncKind>(op.funcid()))
->funcName;
if (att - 1 == col &&
(!(dbcommon::StringUtil::countReplicates(funcName, "not_equal") == 1))) {
const univplan::UnivPlanConst &con = op.args(1).val();
idx->colidx = att;
idx->typeId = typeId;
idx->oper = funcName;
idx->constVal = con.value();
idx->typeModify = modify;
if (!(dbcommon::StringUtil::countReplicates(funcName, "equal") == 1)) {
allExpr.push_back(std::move(idx));
*equal = 0;
} else {
equalExpr.push_back(std::move(idx));
*equal = 1;
}
return true;
}
return false;
}
bool do_boolexpr2(
int pk, const univplan::UnivPlanBoolExpr &expr,
std::vector<std::unique_ptr<IndexExpr> > &allExpr, // NOLINT
std::vector<std::unique_ptr<IndexExpr> > &equalExpr, // NOLINT
int *equal) {
int args_size = expr.args_size();
bool hasExpr = false;
for (int i = 0; i < args_size; ++i) {
const univplan::UnivPlanExprPoly &op = expr.args(i);
switch (op.type()) {
case univplan::UNIVPLAN_EXPR_OPEXPR: {
const univplan::UnivPlanOpExpr &opex = op.opexpr();
bool has = do_opexpr2(pk, opex, allExpr, equalExpr, equal);
if (*equal == 1) return true;
if (has) hasExpr = true;
break;
}
case univplan::UNIVPLAN_EXPR_BOOLEXPR: {
const univplan::UnivPlanBoolExpr &opex = op.boolexpr();
bool has = do_boolexpr2(pk, opex, allExpr, equalExpr, equal);
if (*equal == 1) return true;
if (has) hasExpr = true;
break;
}
default:
break;
}
}
return hasExpr;
}
bool loopContinue(
int pkCol, const univplan::UnivPlanExprPolyList *filterExprs,
std::vector<std::unique_ptr<IndexExpr> > &allExpr, // NOLINT
std::vector<std::unique_ptr<IndexExpr> > &equalExpr) { // NOLINT
int filterSize = filterExprs->size();
assert(filterSize > 0);
bool hasExpr = false;
for (int i = 0; i < filterSize; ++i) {
const univplan::UnivPlanExprPoly &ep = filterExprs->Get(i);
switch (ep.type()) {
case univplan::UNIVPLAN_EXPR_OPEXPR: {
const univplan::UnivPlanOpExpr &op = ep.opexpr();
int equal = 0;
bool has = do_opexpr2(pkCol, op, allExpr, equalExpr, &equal);
if (equal == 1) return true;
if (has) hasExpr = true;
break;
}
case univplan::UNIVPLAN_EXPR_BOOLEXPR: {
const univplan::UnivPlanBoolExpr &op = ep.boolexpr();
if (op.type() == univplan::BOOLEXPRTYPE::BOOLEXPRTYPE_AND_EXPR) {
int equal = 0;
bool has = do_boolexpr2(pkCol, op, allExpr, equalExpr, &equal);
if (equal == 1) return true;
if (has) hasExpr = true;
}
break;
}
default:
break;
}
}
return hasExpr;
}
std::vector<std::vector<std::unique_ptr<IndexExpr> > > getIndexExpr2(
const std::vector<int> &index,
const univplan::UnivPlanExprPolyList *filterExprs) {
std::vector<std::vector<std::unique_ptr<IndexExpr> > > indexExprVec;
int indexSize = index.size();
assert(indexSize > 0);
for (int i = 0; i < indexSize; ++i) {
int col = index[i];
std::vector<std::unique_ptr<IndexExpr> > allExpr;
std::vector<std::unique_ptr<IndexExpr> > equalExpr;
bool loop = loopContinue(col, filterExprs, allExpr, equalExpr);
if (!loop) return indexExprVec;
int equalSize = equalExpr.size();
int allSize = allExpr.size();
if (equalSize > 0) {
indexExprVec.push_back(std::move(equalExpr));
continue;
} else {
if (allSize > 0) {
indexExprVec.push_back(std::move(allExpr));
return indexExprVec;
}
}
}
return indexExprVec;
}
} // namespace univplan