planTestUtil.cpp 7.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program 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.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "planTestUtil.h"

#include <algorithm>
X
Xiaoyu Wang 已提交
19
#include <array>
20 21 22 23 24 25 26 27

#include "cmdnodes.h"
#include "parser.h"
#include "planInt.h"

using namespace std;
using namespace testing;

X
Xiaoyu Wang 已提交
28 29 30 31 32 33 34 35
#define DO_WITH_THROW(func, ...)                                                                                   \
  do {                                                                                                             \
    int32_t code__ = func(__VA_ARGS__);                                                                            \
    if (TSDB_CODE_SUCCESS != code__) {                                                                             \
      throw runtime_error("sql:[" + stmtEnv_.sql_ + "] " #func " code:" + to_string(code__) +                      \
                          ", strerror:" + string(tstrerror(code__)) + ", msg:" + string(stmtEnv_.msgBuf_.data())); \
    }                                                                                                              \
  } while (0);
36

X
Xiaoyu Wang 已提交
37 38
bool g_isDump = false;

39
class PlannerTestBaseImpl {
X
Xiaoyu Wang 已提交
40
 public:
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
  void useDb(const string& acctId, const string& db) {
    caseEnv_.acctId_ = acctId;
    caseEnv_.db_ = db;
  }

  void run(const string& sql) {
    reset();
    try {
      SQuery* pQuery = nullptr;
      doParseSql(sql, &pQuery);

      SPlanContext cxt = {0};
      setPlanContext(pQuery, &cxt);

      SLogicNode* pLogicNode = nullptr;
      doCreateLogicPlan(&cxt, &pLogicNode);

      doOptimizeLogicPlan(&cxt, pLogicNode);

      SLogicSubplan* pLogicSubplan = nullptr;
      doSplitLogicPlan(&cxt, pLogicNode, &pLogicSubplan);

      SQueryLogicPlan* pLogicPlan = nullptr;
      doScaleOutLogicPlan(&cxt, pLogicSubplan, &pLogicPlan);

      SQueryPlan* pPlan = nullptr;
X
Xiaoyu Wang 已提交
67
      doCreatePhysiPlan(&cxt, pLogicPlan, &pPlan);
X
Xiaoyu Wang 已提交
68 69 70 71

      if (g_isDump) {
        dump();
      }
72 73 74 75 76 77
    } catch (...) {
      dump();
      throw;
    }
  }

X
Xiaoyu Wang 已提交
78
 private:
79 80 81 82 83 84
  struct caseEnv {
    string acctId_;
    string db_;
  };

  struct stmtEnv {
X
Xiaoyu Wang 已提交
85
    string            sql_;
86 87 88 89
    array<char, 1024> msgBuf_;
  };

  struct stmtRes {
X
Xiaoyu Wang 已提交
90 91 92 93 94 95
    string         ast_;
    string         rawLogicPlan_;
    string         optimizedLogicPlan_;
    string         splitLogicPlan_;
    string         scaledLogicPlan_;
    string         physiPlan_;
X
Xiaoyu Wang 已提交
96
    vector<string> physiSubplans_;
97 98 99 100 101 102 103 104 105 106 107 108
  };

  void reset() {
    stmtEnv_.sql_.clear();
    stmtEnv_.msgBuf_.fill(0);

    res_.ast_.clear();
    res_.rawLogicPlan_.clear();
    res_.optimizedLogicPlan_.clear();
    res_.splitLogicPlan_.clear();
    res_.scaledLogicPlan_.clear();
    res_.physiPlan_.clear();
109
    res_.physiSubplans_.clear();
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
  }

  void dump() {
    cout << "==========================================sql : [" << stmtEnv_.sql_ << "]" << endl;
    cout << "syntax tree : " << endl;
    cout << res_.ast_ << endl;
    cout << "raw logic plan : " << endl;
    cout << res_.rawLogicPlan_ << endl;
    cout << "optimized logic plan : " << endl;
    cout << res_.optimizedLogicPlan_ << endl;
    cout << "split logic plan : " << endl;
    cout << res_.splitLogicPlan_ << endl;
    cout << "scaled logic plan : " << endl;
    cout << res_.scaledLogicPlan_ << endl;
    cout << "physical plan : " << endl;
    cout << res_.physiPlan_ << endl;
X
Xiaoyu Wang 已提交
126 127 128 129
    cout << "physical subplan : " << endl;
    for (const auto& subplan : res_.physiSubplans_) {
      cout << subplan << endl;
    }
130
  }
X
Xiaoyu Wang 已提交
131

132 133 134
  void doParseSql(const string& sql, SQuery** pQuery) {
    stmtEnv_.sql_ = sql;
    transform(stmtEnv_.sql_.begin(), stmtEnv_.sql_.end(), stmtEnv_.sql_.begin(), ::tolower);
X
Xiaoyu Wang 已提交
135

136 137 138 139 140 141 142
    SParseContext cxt = {0};
    cxt.acctId = atoi(caseEnv_.acctId_.c_str());
    cxt.db = caseEnv_.db_.c_str();
    cxt.pSql = stmtEnv_.sql_.c_str();
    cxt.sqlLen = stmtEnv_.sql_.length();
    cxt.pMsg = stmtEnv_.msgBuf_.data();
    cxt.msgLen = stmtEnv_.msgBuf_.max_size();
X
Xiaoyu Wang 已提交
143

144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    DO_WITH_THROW(qParseQuerySql, &cxt, pQuery);
    res_.ast_ = toString((*pQuery)->pRoot);
  }

  void doCreateLogicPlan(SPlanContext* pCxt, SLogicNode** pLogicNode) {
    DO_WITH_THROW(createLogicPlan, pCxt, pLogicNode);
    res_.rawLogicPlan_ = toString((SNode*)(*pLogicNode));
  }

  void doOptimizeLogicPlan(SPlanContext* pCxt, SLogicNode* pLogicNode) {
    DO_WITH_THROW(optimizeLogicPlan, pCxt, pLogicNode);
    res_.optimizedLogicPlan_ = toString((SNode*)pLogicNode);
  }

  void doSplitLogicPlan(SPlanContext* pCxt, SLogicNode* pLogicNode, SLogicSubplan** pLogicSubplan) {
    DO_WITH_THROW(splitLogicPlan, pCxt, pLogicNode, pLogicSubplan);
    res_.splitLogicPlan_ = toString((SNode*)(*pLogicSubplan));
  }

  void doScaleOutLogicPlan(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan, SQueryLogicPlan** pLogicPlan) {
    DO_WITH_THROW(scaleOutLogicPlan, pCxt, pLogicSubplan, pLogicPlan);
    res_.scaledLogicPlan_ = toString((SNode*)(*pLogicPlan));
  }

X
Xiaoyu Wang 已提交
168 169
  void doCreatePhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan) {
    SArray* pExecNodeList = taosArrayInit(TARRAY_MIN_SIZE, sizeof(SQueryNodeAddr));
170 171
    DO_WITH_THROW(createPhysiPlan, pCxt, pLogicPlan, pPlan, pExecNodeList);
    res_.physiPlan_ = toString((SNode*)(*pPlan));
X
Xiaoyu Wang 已提交
172 173 174
    SNode* pNode;
    FOREACH(pNode, (*pPlan)->pSubplans) {
      SNode* pSubplan;
X
Xiaoyu Wang 已提交
175
      FOREACH(pSubplan, ((SNodeListNode*)pNode)->pNodeList) { res_.physiSubplans_.push_back(toString(pSubplan)); }
X
Xiaoyu Wang 已提交
176
    }
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
  }

  void setPlanContext(SQuery* pQuery, SPlanContext* pCxt) {
    if (QUERY_NODE_CREATE_TOPIC_STMT == nodeType(pQuery->pRoot)) {
      pCxt->pAstRoot = ((SCreateTopicStmt*)pQuery->pRoot)->pQuery;
      pCxt->topicQuery = true;
    } else if (QUERY_NODE_CREATE_INDEX_STMT == nodeType(pQuery->pRoot)) {
      SMCreateSmaReq req = {0};
      tDeserializeSMCreateSmaReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req);
      nodesStringToNode(req.ast, &pCxt->pAstRoot);
      pCxt->streamQuery = true;
    } else if (QUERY_NODE_CREATE_STREAM_STMT == nodeType(pQuery->pRoot)) {
      SCreateStreamStmt* pStmt = (SCreateStreamStmt*)pQuery->pRoot;
      pCxt->pAstRoot = pStmt->pQuery;
      pCxt->streamQuery = true;
      pCxt->triggerType = pStmt->pOptions->triggerType;
      pCxt->watermark = (NULL != pStmt->pOptions->pWatermark ? ((SValueNode*)pStmt->pOptions->pWatermark)->datum.i : 0);
    } else {
      pCxt->pAstRoot = pQuery->pRoot;
    }
  }

  string toString(const SNode* pRoot) {
X
Xiaoyu Wang 已提交
200
    char*   pStr = NULL;
201 202 203 204 205 206 207 208 209 210 211 212
    int32_t len = 0;
    DO_WITH_THROW(nodesNodeToString, pRoot, false, &pStr, &len)
    string str(pStr);
    taosMemoryFreeClear(pStr);
    return str;
  }

  caseEnv caseEnv_;
  stmtEnv stmtEnv_;
  stmtRes res_;
};

X
Xiaoyu Wang 已提交
213
PlannerTestBase::PlannerTestBase() : impl_(new PlannerTestBaseImpl()) {}
214

X
Xiaoyu Wang 已提交
215
PlannerTestBase::~PlannerTestBase() {}
216

X
Xiaoyu Wang 已提交
217
void PlannerTestBase::useDb(const std::string& acctId, const std::string& db) { impl_->useDb(acctId, db); }
218

X
Xiaoyu Wang 已提交
219
void PlannerTestBase::run(const std::string& sql) { return impl_->run(sql); }