planTestUtil.cpp 17.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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"
X
Xiaoyu Wang 已提交
17

wafwerar's avatar
wafwerar 已提交
18
#include <getopt.h>
19 20

#include <algorithm>
X
Xiaoyu Wang 已提交
21
#include <array>
22
#include <chrono>
23 24

#include "cmdnodes.h"
X
Xiaoyu Wang 已提交
25
#include "mockCatalogService.h"
26 27
#include "parser.h"
#include "planInt.h"
28
#include "tglobal.h"
29 30 31 32

using namespace std;
using namespace testing;

X
Xiaoyu Wang 已提交
33 34 35 36 37 38 39 40
#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);
41

X
Xiaoyu Wang 已提交
42 43 44 45 46 47 48 49 50 51 52 53 54
enum DumpModule {
  DUMP_MODULE_NOTHING = 1,
  DUMP_MODULE_PARSER,
  DUMP_MODULE_LOGIC,
  DUMP_MODULE_OPTIMIZED,
  DUMP_MODULE_SPLIT,
  DUMP_MODULE_SCALED,
  DUMP_MODULE_PHYSICAL,
  DUMP_MODULE_SUBPLAN,
  DUMP_MODULE_ALL
};

DumpModule g_dumpModule = DUMP_MODULE_NOTHING;
55
int32_t    g_skipSql = 0;
56
int32_t    g_limitSql = 0;
57
int32_t    g_logLevel = 131;
58
int32_t    g_queryPolicy = QUERY_POLICY_VNODE;
X
Xiaoyu Wang 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80

void setDumpModule(const char* pModule) {
  if (NULL == pModule) {
    g_dumpModule = DUMP_MODULE_ALL;
  } else if (0 == strncasecmp(pModule, "parser", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_PARSER;
  } else if (0 == strncasecmp(pModule, "logic", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_LOGIC;
  } else if (0 == strncasecmp(pModule, "optimized", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_OPTIMIZED;
  } else if (0 == strncasecmp(pModule, "split", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_SPLIT;
  } else if (0 == strncasecmp(pModule, "scaled", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_SCALED;
  } else if (0 == strncasecmp(pModule, "physical", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_PHYSICAL;
  } else if (0 == strncasecmp(pModule, "subplan", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_SUBPLAN;
  } else if (0 == strncasecmp(pModule, "all", strlen(pModule))) {
    g_dumpModule = DUMP_MODULE_PHYSICAL;
  }
}
X
Xiaoyu Wang 已提交
81

wafwerar's avatar
wafwerar 已提交
82
void setSkipSqlNum(const char* pNum) { g_skipSql = stoi(pNum); }
83
void setLimitSqlNum(const char* pNum) { g_limitSql = stoi(pNum); }
84
void setLogLevel(const char* pLogLevel) { g_logLevel = stoi(pLogLevel); }
85
void setQueryPolicy(const char* pQueryPolicy) { g_queryPolicy = stoi(pQueryPolicy); }
86 87 88

int32_t getLogLevel() { return g_logLevel; }

89
class PlannerTestBaseImpl {
X
Xiaoyu Wang 已提交
90
 public:
91
  PlannerTestBaseImpl() : sqlNo_(0), sqlNum_(0) {}
92

X
Xiaoyu Wang 已提交
93 94 95
  void useDb(const string& user, const string& db) {
    caseEnv_.acctId_ = 0;
    caseEnv_.user_ = user;
96
    caseEnv_.db_ = db;
97 98
    caseEnv_.numOfSkipSql_ = g_skipSql;
    caseEnv_.numOfLimitSql_ = g_limitSql;
99 100 101
  }

  void run(const string& sql) {
102
    ++sqlNo_;
103 104 105 106 107
    if (caseEnv_.numOfSkipSql_ > 0) {
      --(caseEnv_.numOfSkipSql_);
      return;
    }
    if (caseEnv_.numOfLimitSql_ > 0 && caseEnv_.numOfLimitSql_ == sqlNum_) {
108 109
      return;
    }
110
    ++sqlNum_;
111

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    switch (g_queryPolicy) {
      case QUERY_POLICY_VNODE:
      case QUERY_POLICY_HYBRID:
      case QUERY_POLICY_QNODE:
        runImpl(sql, g_queryPolicy);
        break;
      default:
        runImpl(sql, QUERY_POLICY_VNODE);
        runImpl(sql, QUERY_POLICY_HYBRID);
        runImpl(sql, QUERY_POLICY_QNODE);
        break;
    }
  }

  void runImpl(const string& sql, int32_t queryPolicy) {
127
    reset();
128
    tsQueryPolicy = queryPolicy;
129
    try {
130 131 132
      unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), _destroyQuery);
      doParseSql(sql, query.get());
      SQuery* pQuery = *(query.get());
133 134 135 136

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

X
Xiaoyu Wang 已提交
137 138
      SLogicSubplan* pLogicSubplan = nullptr;
      doCreateLogicPlan(&cxt, &pLogicSubplan);
X
Xiaoyu Wang 已提交
139 140
      unique_ptr<SLogicSubplan, void (*)(SLogicSubplan*)> logicSubplan(pLogicSubplan,
                                                                       (void (*)(SLogicSubplan*))nodesDestroyNode);
141

X
Xiaoyu Wang 已提交
142
      doOptimizeLogicPlan(&cxt, pLogicSubplan);
143

X
Xiaoyu Wang 已提交
144
      doSplitLogicPlan(&cxt, pLogicSubplan);
145 146 147

      SQueryLogicPlan* pLogicPlan = nullptr;
      doScaleOutLogicPlan(&cxt, pLogicSubplan, &pLogicPlan);
X
Xiaoyu Wang 已提交
148 149
      unique_ptr<SQueryLogicPlan, void (*)(SQueryLogicPlan*)> logicPlan(pLogicPlan,
                                                                        (void (*)(SQueryLogicPlan*))nodesDestroyNode);
150 151

      SQueryPlan* pPlan = nullptr;
X
Xiaoyu Wang 已提交
152
      doCreatePhysiPlan(&cxt, pLogicPlan, &pPlan);
X
Xiaoyu Wang 已提交
153
      unique_ptr<SQueryPlan, void (*)(SQueryPlan*)> plan(pPlan, (void (*)(SQueryPlan*))nodesDestroyNode);
X
Xiaoyu Wang 已提交
154

X
Xiaoyu Wang 已提交
155
      dump(g_dumpModule);
156
    } catch (...) {
X
Xiaoyu Wang 已提交
157
      dump(DUMP_MODULE_ALL);
158 159 160 161
      throw;
    }
  }

162
  void prepare(const string& sql) {
163
    if (caseEnv_.numOfSkipSql_ > 0) {
164 165 166
      return;
    }

167 168 169 170 171 172 173 174 175 176
    reset();
    try {
      doParseSql(sql, &stmtEnv_.pQuery_, true);
    } catch (...) {
      dump(DUMP_MODULE_ALL);
      throw;
    }
  }

  void bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
177
    if (caseEnv_.numOfSkipSql_ > 0) {
178 179 180
      return;
    }

181 182
    try {
      doBindParams(stmtEnv_.pQuery_, pParams, colIdx);
183 184 185 186 187 188 189
    } catch (...) {
      dump(DUMP_MODULE_ALL);
      throw;
    }
  }

  void exec() {
190 191
    if (caseEnv_.numOfSkipSql_ > 0) {
      --(caseEnv_.numOfSkipSql_);
192 193 194
      return;
    }

195 196
    try {
      doParseBoundSql(stmtEnv_.pQuery_);
197 198 199 200

      SPlanContext cxt = {0};
      setPlanContext(stmtEnv_.pQuery_, &cxt);

X
Xiaoyu Wang 已提交
201 202
      SLogicSubplan* pLogicSubplan = nullptr;
      doCreateLogicPlan(&cxt, &pLogicSubplan);
203 204
      unique_ptr<SLogicSubplan, void (*)(SLogicSubplan*)> logicSubplan(pLogicSubplan,
                                                                       (void (*)(SLogicSubplan*))nodesDestroyNode);
205

X
Xiaoyu Wang 已提交
206
      doOptimizeLogicPlan(&cxt, pLogicSubplan);
207

X
Xiaoyu Wang 已提交
208
      doSplitLogicPlan(&cxt, pLogicSubplan);
209 210 211

      SQueryLogicPlan* pLogicPlan = nullptr;
      doScaleOutLogicPlan(&cxt, pLogicSubplan, &pLogicPlan);
212 213
      unique_ptr<SQueryLogicPlan, void (*)(SQueryLogicPlan*)> logicPlan(pLogicPlan,
                                                                        (void (*)(SQueryLogicPlan*))nodesDestroyNode);
214 215 216

      SQueryPlan* pPlan = nullptr;
      doCreatePhysiPlan(&cxt, pLogicPlan, &pPlan);
217
      unique_ptr<SQueryPlan, void (*)(SQueryPlan*)> plan(pPlan, (void (*)(SQueryPlan*))nodesDestroyNode);
218 219 220 221 222 223 224 225

      dump(g_dumpModule);
    } catch (...) {
      dump(DUMP_MODULE_ALL);
      throw;
    }
  }

X
Xiaoyu Wang 已提交
226
 private:
227
  struct caseEnv {
X
Xiaoyu Wang 已提交
228 229
    int32_t acctId_;
    string  user_;
230
    string  db_;
231 232
    int32_t numOfSkipSql_;
    int32_t numOfLimitSql_;
233

234
    caseEnv() : numOfSkipSql_(0) {}
235 236 237
  };

  struct stmtEnv {
X
Xiaoyu Wang 已提交
238
    string            sql_;
239
    array<char, 1024> msgBuf_;
240 241
    SQuery*           pQuery_;

242
    stmtEnv() : pQuery_(nullptr) {}
243
    ~stmtEnv() { qDestroyQuery(pQuery_); }
244 245 246
  };

  struct stmtRes {
X
Xiaoyu Wang 已提交
247
    string         ast_;
248 249
    string         prepareAst_;
    string         boundAst_;
X
Xiaoyu Wang 已提交
250 251 252 253 254
    string         rawLogicPlan_;
    string         optimizedLogicPlan_;
    string         splitLogicPlan_;
    string         scaledLogicPlan_;
    string         physiPlan_;
255
    string         physiPlanMsg_;
X
Xiaoyu Wang 已提交
256
    vector<string> physiSubplans_;
257 258
  };

259 260 261 262 263 264 265 266
  static void _destroyQuery(SQuery** pQuery) {
    if (nullptr == pQuery) {
      return;
    }
    qDestroyQuery(*pQuery);
    taosMemoryFree(pQuery);
  }

267 268 269
  void reset() {
    stmtEnv_.sql_.clear();
    stmtEnv_.msgBuf_.fill(0);
270
    qDestroyQuery(stmtEnv_.pQuery_);
271 272

    res_.ast_.clear();
273
    res_.boundAst_.clear();
274 275 276 277 278
    res_.rawLogicPlan_.clear();
    res_.optimizedLogicPlan_.clear();
    res_.splitLogicPlan_.clear();
    res_.scaledLogicPlan_.clear();
    res_.physiPlan_.clear();
279
    res_.physiPlanMsg_.clear();
280
    res_.physiSubplans_.clear();
281 282
  }

X
Xiaoyu Wang 已提交
283
  void dump(DumpModule module) {
284 285
    cout << "========================================== " << sqlNo_ << " sql : [" << stmtEnv_.sql_ << "]" << endl;

X
Xiaoyu Wang 已提交
286 287 288 289 290
    if (DUMP_MODULE_NOTHING == module) {
      return;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_PARSER == module) {
291
      if (res_.prepareAst_.empty()) {
X
Xiaoyu Wang 已提交
292
        cout << "+++++++++++++++++++++syntax tree : " << endl;
293 294
        cout << res_.ast_ << endl;
      } else {
X
Xiaoyu Wang 已提交
295
        cout << "+++++++++++++++++++++prepare syntax tree : " << endl;
296
        cout << res_.prepareAst_ << endl;
X
Xiaoyu Wang 已提交
297
        cout << "+++++++++++++++++++++bound syntax tree : " << endl;
298
        cout << res_.boundAst_ << endl;
X
Xiaoyu Wang 已提交
299
        cout << "+++++++++++++++++++++syntax tree : " << endl;
300 301
        cout << res_.ast_ << endl;
      }
X
Xiaoyu Wang 已提交
302 303 304
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_LOGIC == module) {
X
Xiaoyu Wang 已提交
305
      cout << "+++++++++++++++++++++raw logic plan : " << endl;
X
Xiaoyu Wang 已提交
306 307 308 309
      cout << res_.rawLogicPlan_ << endl;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_OPTIMIZED == module) {
X
Xiaoyu Wang 已提交
310
      cout << "+++++++++++++++++++++optimized logic plan : " << endl;
X
Xiaoyu Wang 已提交
311 312 313 314
      cout << res_.optimizedLogicPlan_ << endl;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_SPLIT == module) {
X
Xiaoyu Wang 已提交
315
      cout << "+++++++++++++++++++++split logic plan : " << endl;
X
Xiaoyu Wang 已提交
316 317 318 319
      cout << res_.splitLogicPlan_ << endl;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_SCALED == module) {
X
Xiaoyu Wang 已提交
320
      cout << "+++++++++++++++++++++scaled logic plan : " << endl;
X
Xiaoyu Wang 已提交
321 322 323 324
      cout << res_.scaledLogicPlan_ << endl;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_PHYSICAL == module) {
X
Xiaoyu Wang 已提交
325
      cout << "+++++++++++++++++++++physical plan : " << endl;
X
Xiaoyu Wang 已提交
326 327 328 329
      cout << res_.physiPlan_ << endl;
    }

    if (DUMP_MODULE_ALL == module || DUMP_MODULE_SUBPLAN == module) {
X
Xiaoyu Wang 已提交
330
      cout << "+++++++++++++++++++++physical subplan : " << endl;
X
Xiaoyu Wang 已提交
331 332 333
      for (const auto& subplan : res_.physiSubplans_) {
        cout << subplan << endl;
      }
X
Xiaoyu Wang 已提交
334
    }
335
  }
X
Xiaoyu Wang 已提交
336

337
  void doParseSql(const string& sql, SQuery** pQuery, bool prepare = false) {
338 339
    stmtEnv_.sql_ = sql;
    transform(stmtEnv_.sql_.begin(), stmtEnv_.sql_.end(), stmtEnv_.sql_.begin(), ::tolower);
X
Xiaoyu Wang 已提交
340

341
    SParseContext cxt = {0};
X
Xiaoyu Wang 已提交
342
    cxt.acctId = caseEnv_.acctId_;
343 344 345 346 347
    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();
348
    cxt.svrVer = "3.0.0.0";
349
    cxt.enableSysInfo = true;
X
Xiaoyu Wang 已提交
350 351 352 353
    if (prepare) {
      SStmtCallback stmtCb = {0};
      cxt.pStmtCb = &stmtCb;
    }
X
Xiaoyu Wang 已提交
354

X
Xiaoyu Wang 已提交
355
    DO_WITH_THROW(qParseSql, &cxt, pQuery);
356
    if (prepare) {
357
      res_.prepareAst_ = toString((*pQuery)->pPrepareRoot);
358 359 360 361 362 363 364 365 366 367 368 369 370 371
    } else {
      res_.ast_ = toString((*pQuery)->pRoot);
    }
  }

  void doBindParams(SQuery* pQuery, TAOS_MULTI_BIND* pParams, int32_t colIdx) {
    DO_WITH_THROW(qStmtBindParams, pQuery, pParams, colIdx);
    if (colIdx < 0 || pQuery->placeholderNum == colIdx + 1) {
      res_.boundAst_ = toString(pQuery->pRoot);
    }
  }

  void doParseBoundSql(SQuery* pQuery) {
    SParseContext cxt = {0};
X
Xiaoyu Wang 已提交
372
    cxt.acctId = caseEnv_.acctId_;
373 374 375 376 377
    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 已提交
378
    cxt.pUser = caseEnv_.user_.c_str();
379 380 381

    DO_WITH_THROW(qStmtParseQuerySql, &cxt, pQuery);
    res_.ast_ = toString(pQuery->pRoot);
382 383
  }

X
Xiaoyu Wang 已提交
384 385 386
  void doCreateLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
    DO_WITH_THROW(createLogicPlan, pCxt, pLogicSubplan);
    res_.rawLogicPlan_ = toString((SNode*)(*pLogicSubplan));
387 388
  }

X
Xiaoyu Wang 已提交
389 390 391
  void doOptimizeLogicPlan(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
    DO_WITH_THROW(optimizeLogicPlan, pCxt, pLogicSubplan);
    res_.optimizedLogicPlan_ = toString((SNode*)pLogicSubplan);
392 393
  }

X
Xiaoyu Wang 已提交
394 395 396
  void doSplitLogicPlan(SPlanContext* pCxt, SLogicSubplan* pLogicSubplan) {
    DO_WITH_THROW(splitLogicPlan, pCxt, pLogicSubplan);
    res_.splitLogicPlan_ = toString((SNode*)(pLogicSubplan));
397 398 399 400 401 402 403
  }

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

X
Xiaoyu Wang 已提交
404
  void doCreatePhysiPlan(SPlanContext* pCxt, SQueryLogicPlan* pLogicPlan, SQueryPlan** pPlan) {
X
Xiaoyu Wang 已提交
405 406 407
    unique_ptr<SArray, void (*)(SArray*)> execNodeList((SArray*)taosArrayInit(TARRAY_MIN_SIZE, sizeof(SQueryNodeAddr)),
                                                       (void (*)(SArray*))taosArrayDestroy);
    DO_WITH_THROW(createPhysiPlan, pCxt, pLogicPlan, pPlan, execNodeList.get());
408
    res_.physiPlan_ = toString((SNode*)(*pPlan));
X
Xiaoyu Wang 已提交
409 410 411
    SNode* pNode;
    FOREACH(pNode, (*pPlan)->pSubplans) {
      SNode* pSubplan;
X
Xiaoyu Wang 已提交
412
      FOREACH(pSubplan, ((SNodeListNode*)pNode)->pNodeList) { res_.physiSubplans_.push_back(toString(pSubplan)); }
X
Xiaoyu Wang 已提交
413
    }
414
    res_.physiPlanMsg_ = toMsg((SNode*)(*pPlan));
415
    cout << "json len: " << res_.physiPlan_.length() << ", msg len: " << res_.physiPlanMsg_.length() << endl;
416 417 418
  }

  void setPlanContext(SQuery* pQuery, SPlanContext* pCxt) {
419
    pCxt->queryId = 1;
X
Xiaoyu Wang 已提交
420
    pCxt->pUser = caseEnv_.user_.c_str();
421
    if (QUERY_NODE_CREATE_TOPIC_STMT == nodeType(pQuery->pRoot)) {
422 423 424 425 426
      SCreateTopicStmt* pStmt = (SCreateTopicStmt*)pQuery->pRoot;
      pCxt->pAstRoot = pStmt->pQuery;
      pStmt->pQuery = nullptr;
      nodesDestroyNode(pQuery->pRoot);
      pQuery->pRoot = pCxt->pAstRoot;
427 428 429 430
      pCxt->topicQuery = true;
    } else if (QUERY_NODE_CREATE_INDEX_STMT == nodeType(pQuery->pRoot)) {
      SMCreateSmaReq req = {0};
      tDeserializeSMCreateSmaReq(pQuery->pCmdMsg->pMsg, pQuery->pCmdMsg->msgLen, &req);
X
Xiaoyu Wang 已提交
431
      g_mockCatalogService->createSmaIndex(&req);
432
      nodesStringToNode(req.ast, &pCxt->pAstRoot);
433 434 435
      tFreeSMCreateSmaReq(&req);
      nodesDestroyNode(pQuery->pRoot);
      pQuery->pRoot = pCxt->pAstRoot;
436 437 438 439
      pCxt->streamQuery = true;
    } else if (QUERY_NODE_CREATE_STREAM_STMT == nodeType(pQuery->pRoot)) {
      SCreateStreamStmt* pStmt = (SCreateStreamStmt*)pQuery->pRoot;
      pCxt->pAstRoot = pStmt->pQuery;
440
      pStmt->pQuery = nullptr;
441 442 443
      pCxt->streamQuery = true;
      pCxt->triggerType = pStmt->pOptions->triggerType;
      pCxt->watermark = (NULL != pStmt->pOptions->pWatermark ? ((SValueNode*)pStmt->pOptions->pWatermark)->datum.i : 0);
444 445
      nodesDestroyNode(pQuery->pRoot);
      pQuery->pRoot = pCxt->pAstRoot;
446 447 448 449 450 451
    } else {
      pCxt->pAstRoot = pQuery->pRoot;
    }
  }

  string toString(const SNode* pRoot) {
X
Xiaoyu Wang 已提交
452
    char*   pStr = NULL;
453
    int32_t len = 0;
454

455
    auto start = chrono::steady_clock::now();
456
    DO_WITH_THROW(nodesNodeToString, pRoot, false, &pStr, &len)
457 458 459 460
    if (QUERY_NODE_PHYSICAL_PLAN == nodeType(pRoot)) {
      cout << "nodesNodeToString: "
           << chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - start).count() << "us" << endl;
    }
461

462 463 464 465 466
    string str(pStr);
    taosMemoryFreeClear(pStr);
    return str;
  }

467 468 469
  string toMsg(const SNode* pRoot) {
    char*   pStr = NULL;
    int32_t len = 0;
470

471
    auto start = chrono::steady_clock::now();
472
    DO_WITH_THROW(nodesNodeToMsg, pRoot, &pStr, &len)
473 474
    cout << "nodesNodeToMsg: "
         << chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - start).count() << "us" << endl;
475

476
    string  copyStr(pStr, len);
477 478 479
    SNode*  pNode = NULL;
    char*   pNewStr = NULL;
    int32_t newlen = 0;
480
    DO_WITH_THROW(nodesMsgToNode, copyStr.c_str(), len, &pNode)
481 482 483
    DO_WITH_THROW(nodesNodeToMsg, pNode, &pNewStr, &newlen)
    if (newlen != len || 0 != memcmp(pStr, pNewStr, len)) {
      cout << "nodesNodeToMsg error!!!!!!!!!!!!!! len = " << len << ", newlen = " << newlen << endl;
484 485 486 487
      taosMemoryFreeClear(pNewStr);
      DO_WITH_THROW(nodesNodeToString, pRoot, false, &pNewStr, &newlen)
      cout << "orac node: " << pNewStr << endl;
      taosMemoryFreeClear(pNewStr);
488
      DO_WITH_THROW(nodesNodeToString, pNode, false, &pNewStr, &newlen)
489
      cout << "new node: " << pNewStr << endl;
490
    }
491
    nodesDestroyNode(pNode);
492 493
    taosMemoryFreeClear(pNewStr);

494 495 496 497 498
    string str(pStr, len);
    taosMemoryFreeClear(pStr);
    return str;
  }

499 500 501
  caseEnv caseEnv_;
  stmtEnv stmtEnv_;
  stmtRes res_;
502
  int32_t sqlNo_;
503
  int32_t sqlNum_;
504 505
};

X
Xiaoyu Wang 已提交
506
PlannerTestBase::PlannerTestBase() : impl_(new PlannerTestBaseImpl()) {}
507

X
Xiaoyu Wang 已提交
508
PlannerTestBase::~PlannerTestBase() {}
509

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

X
Xiaoyu Wang 已提交
512
void PlannerTestBase::run(const std::string& sql) { return impl_->run(sql); }
513 514 515 516 517 518 519 520

void PlannerTestBase::prepare(const std::string& sql) { return impl_->prepare(sql); }

void PlannerTestBase::bindParams(TAOS_MULTI_BIND* pParams, int32_t colIdx) {
  return impl_->bindParams(pParams, colIdx);
}

void PlannerTestBase::exec() { return impl_->exec(); }