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

#include <algorithm>
#include <array>
20
#include <thread>
X
Xiaoyu Wang 已提交
21

22 23
#include "catalog.h"
#include "mockCatalogService.h"
X
Xiaoyu Wang 已提交
24 25 26
#include "parInt.h"

using namespace std;
27
using namespace std::placeholders;
X
Xiaoyu Wang 已提交
28 29
using namespace testing;

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
namespace ParserTest {

#define DO_WITH_THROW(func, ...)                                                                                     \
  do {                                                                                                               \
    int32_t code__ = func(__VA_ARGS__);                                                                              \
    if (!checkResultCode(#func, code__)) {                                                                           \
      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())); \
      } else {                                                                                                       \
        throw runtime_error("sql:[" + stmtEnv_.sql_ + "] " #func " expect " + to_string(stmtEnv_.expect_) +          \
                            " actual " + to_string(code__));                                                         \
      }                                                                                                              \
    } else if (TSDB_CODE_SUCCESS != code__) {                                                                        \
      throw TerminateFlag();                                                                                         \
    }                                                                                                                \
X
Xiaoyu Wang 已提交
46 47
  } while (0);

48
bool    g_dump = false;
49
bool    g_testAsyncApis = true;
50 51
int32_t g_logLevel = 131;
int32_t g_skipSql = 0;
52
int32_t g_limitSql = 0;
53

54 55 56
void setAsyncFlag(const char* pArg) { g_testAsyncApis = stoi(pArg) > 0 ? true : false; }
void setSkipSqlNum(const char* pArg) { g_skipSql = stoi(pArg); }
void setLimitSqlNum(const char* pArg) { g_limitSql = stoi(pArg); }
X
Xiaoyu Wang 已提交
57

58 59 60 61
struct TerminateFlag : public exception {
  const char* what() const throw() { return "success and terminate"; }
};

62 63 64 65
void setLogLevel(const char* pLogLevel) { g_logLevel = stoi(pLogLevel); }

int32_t getLogLevel() { return g_logLevel; }

X
Xiaoyu Wang 已提交
66 67
class ParserTestBaseImpl {
 public:
68
  ParserTestBaseImpl(ParserTestBase* pBase) : pBase_(pBase), sqlNo_(0), sqlNum_(0) {}
X
Xiaoyu Wang 已提交
69

70 71
  void login(const std::string& user) { caseEnv_.user_ = user; }

X
Xiaoyu Wang 已提交
72 73 74
  void useDb(const string& acctId, const string& db) {
    caseEnv_.acctId_ = acctId;
    caseEnv_.db_ = db;
75 76
    caseEnv_.numOfSkipSql_ = g_skipSql;
    caseEnv_.numOfLimitSql_ = g_limitSql;
X
Xiaoyu Wang 已提交
77 78
  }

79
  void run(const string& sql, int32_t expect, ParserStage checkStage) {
X
Xiaoyu Wang 已提交
80
    ++sqlNo_;
81 82
    if (caseEnv_.numOfSkipSql_ > 0) {
      --(caseEnv_.numOfSkipSql_);
83 84
      return;
    }
85 86 87 88
    if (caseEnv_.numOfLimitSql_ > 0 && caseEnv_.numOfLimitSql_ == sqlNum_) {
      return;
    }
    ++sqlNum_;
89

90 91
    runInternalFuncs(sql, expect, checkStage);
    runApis(sql, expect, checkStage);
92 93

    if (g_testAsyncApis) {
94 95
      runAsyncInternalFuncs(sql, expect, checkStage);
      runAsyncApis(sql, expect, checkStage);
96 97 98
    }
  }

X
Xiaoyu Wang 已提交
99 100
 private:
  struct caseEnv {
101
    string  acctId_;
102
    string  user_;
103
    string  db_;
104 105
    int32_t numOfSkipSql_;
    int32_t numOfLimitSql_;
106

107
    caseEnv() : user_("wangxiaoyu"), numOfSkipSql_(0) {}
X
Xiaoyu Wang 已提交
108 109 110 111 112
  };

  struct stmtEnv {
    string            sql_;
    array<char, 1024> msgBuf_;
113 114
    int32_t           expect_;
    string            checkFunc_;
X
Xiaoyu Wang 已提交
115 116 117 118 119 120 121 122
  };

  struct stmtRes {
    string parsedAst_;
    string translatedAst_;
    string calcConstAst_;
  };

123 124 125 126 127 128 129
  enum TestInterfaceType {
    TEST_INTERFACE_INTERNAL = 1,
    TEST_INTERFACE_API,
    TEST_INTERFACE_ASYNC_INTERNAL,
    TEST_INTERFACE_ASYNC_API
  };

130 131 132 133 134 135 136
  static void destoryParseContext(SParseContext* pCxt) {
    taosArrayDestroy(pCxt->pTableMetaPos);
    taosArrayDestroy(pCxt->pTableVgroupPos);
    delete pCxt;
  }

  static void destoryParseMetaCacheWarpper(SParseMetaCache* pMetaCache, bool request) {
137
    destoryParseMetaCache(pMetaCache, request);
138 139 140
    delete pMetaCache;
  }

141
  static void destroyQuery(SQuery** pQuery) {
142 143 144 145 146 147 148
    if (nullptr == pQuery) {
      return;
    }
    qDestroyQuery(*pQuery);
    taosMemoryFree(pQuery);
  }

149 150
  bool checkResultCode(const string& pFunc, int32_t resultCode) {
    return !(stmtEnv_.checkFunc_.empty())
151
               ? ((stmtEnv_.checkFunc_ == pFunc) ? stmtEnv_.expect_ == resultCode : TSDB_CODE_SUCCESS == resultCode)
152 153 154
               : true;
  }

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  string stageFunc(ParserStage stage, TestInterfaceType type) {
    switch (type) {
      case TEST_INTERFACE_INTERNAL:
      case TEST_INTERFACE_ASYNC_INTERNAL:
        switch (stage) {
          case PARSER_STAGE_PARSE:
            return "parse";
          case PARSER_STAGE_TRANSLATE:
            return "translate";
          case PARSER_STAGE_CALC_CONST:
            return "calculateConstant";
          default:
            break;
        }
        break;
      case TEST_INTERFACE_API:
        return "qParseSql";
      case TEST_INTERFACE_ASYNC_API:
        switch (stage) {
          case PARSER_STAGE_PARSE:
            return "qParseSqlSyntax";
          case PARSER_STAGE_TRANSLATE:
          case PARSER_STAGE_CALC_CONST:
            return "qAnalyseSqlSemantic";
          default:
            break;
        }
        break;
183 184 185 186 187 188
      default:
        break;
    }
    return "unknown";
  }

189
  void reset(int32_t expect, ParserStage checkStage, TestInterfaceType type) {
X
Xiaoyu Wang 已提交
190 191
    stmtEnv_.sql_.clear();
    stmtEnv_.msgBuf_.fill(0);
192
    stmtEnv_.expect_ = expect;
193
    stmtEnv_.checkFunc_ = stageFunc(checkStage, type);
X
Xiaoyu Wang 已提交
194 195 196 197 198 199 200

    res_.parsedAst_.clear();
    res_.translatedAst_.clear();
    res_.calcConstAst_.clear();
  }

  void dump() {
X
Xiaoyu Wang 已提交
201
    cout << "========================================== " << sqlNo_ << " sql : [" << stmtEnv_.sql_ << "]" << endl;
202 203 204 205 206 207 208 209 210 211 212 213
    if (!res_.parsedAst_.empty()) {
      cout << "raw syntax tree : " << endl;
      cout << res_.parsedAst_ << endl;
    }
    if (!res_.translatedAst_.empty()) {
      cout << "translated syntax tree : " << endl;
      cout << res_.translatedAst_ << endl;
    }
    if (!res_.calcConstAst_.empty()) {
      cout << "optimized syntax tree : " << endl;
      cout << res_.calcConstAst_ << endl;
    }
X
Xiaoyu Wang 已提交
214 215
  }

216
  void setParseContext(const string& sql, SParseContext* pCxt, bool async = false) {
X
Xiaoyu Wang 已提交
217
    stmtEnv_.sql_ = sql;
218
    strtolower((char*)stmtEnv_.sql_.c_str(), sql.c_str());
X
Xiaoyu Wang 已提交
219 220 221

    pCxt->acctId = atoi(caseEnv_.acctId_.c_str());
    pCxt->db = caseEnv_.db_.c_str();
222 223
    pCxt->pUser = caseEnv_.user_.c_str();
    pCxt->isSuperUser = caseEnv_.user_ == "root";
224
    pCxt->enableSysInfo = true;
X
Xiaoyu Wang 已提交
225 226 227 228
    pCxt->pSql = stmtEnv_.sql_.c_str();
    pCxt->sqlLen = stmtEnv_.sql_.length();
    pCxt->pMsg = stmtEnv_.msgBuf_.data();
    pCxt->msgLen = stmtEnv_.msgBuf_.max_size();
229
    pCxt->async = async;
230
    pCxt->svrVer = "3.0.0.0";
X
Xiaoyu Wang 已提交
231 232 233 234
  }

  void doParse(SParseContext* pCxt, SQuery** pQuery) {
    DO_WITH_THROW(parse, pCxt, pQuery);
X
Xiaoyu Wang 已提交
235
    ASSERT_NE(*pQuery, nullptr);
X
Xiaoyu Wang 已提交
236 237 238
    res_.parsedAst_ = toString((*pQuery)->pRoot);
  }

239 240
  void doCollectMetaKey(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
    DO_WITH_THROW(collectMetaKey, pCxt, pQuery, pMetaCache);
241 242
  }

X
Xiaoyu Wang 已提交
243
  void doBuildCatalogReq(SParseContext* pCxt, const SParseMetaCache* pMetaCache, SCatalogReq* pCatalogReq) {
X
Xiaoyu Wang 已提交
244
    DO_WITH_THROW(buildCatalogReq, pMetaCache, pCatalogReq);
245 246 247 248 249 250
  }

  void doGetAllMeta(const SCatalogReq* pCatalogReq, SMetaData* pMetaData) {
    DO_WITH_THROW(g_mockCatalogService->catalogGetAllMeta, pCatalogReq, pMetaData);
  }

X
Xiaoyu Wang 已提交
251 252
  void doPutMetaDataToCache(const SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SParseMetaCache* pMetaCache) {
    DO_WITH_THROW(putMetaDataToCache, pCatalogReq, pMetaData, pMetaCache);
253 254
  }

255 256 257
  void doAuthenticate(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
    DO_WITH_THROW(authenticate, pCxt, pQuery, pMetaCache);
  }
258

259 260
  void doTranslate(SParseContext* pCxt, SQuery* pQuery, SParseMetaCache* pMetaCache) {
    DO_WITH_THROW(translate, pCxt, pQuery, pMetaCache);
X
Xiaoyu Wang 已提交
261
    checkQuery(pQuery, PARSER_STAGE_TRANSLATE);
X
Xiaoyu Wang 已提交
262 263 264 265 266 267 268 269
    res_.translatedAst_ = toString(pQuery->pRoot);
  }

  void doCalculateConstant(SParseContext* pCxt, SQuery* pQuery) {
    DO_WITH_THROW(calculateConstant, pCxt, pQuery);
    res_.calcConstAst_ = toString(pQuery->pRoot);
  }

270 271 272 273 274 275 276 277 278
  void doParseSql(SParseContext* pCxt, SQuery** pQuery) {
    DO_WITH_THROW(qParseSql, pCxt, pQuery);
    ASSERT_NE(*pQuery, nullptr);
    res_.calcConstAst_ = toString((*pQuery)->pRoot);
  }

  void doParseSqlSyntax(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq) {
    DO_WITH_THROW(qParseSqlSyntax, pCxt, pQuery, pCatalogReq);
    ASSERT_NE(*pQuery, nullptr);
X
Xiaoyu Wang 已提交
279 280 281
    if (nullptr != (*pQuery)->pRoot) {
      res_.parsedAst_ = toString((*pQuery)->pRoot);
    }
282 283 284 285 286 287 288 289
  }

  void doAnalyseSqlSemantic(SParseContext* pCxt, const SCatalogReq* pCatalogReq, const SMetaData* pMetaData,
                            SQuery* pQuery) {
    DO_WITH_THROW(qAnalyseSqlSemantic, pCxt, pCatalogReq, pMetaData, pQuery);
    res_.calcConstAst_ = toString(pQuery->pRoot);
  }

X
Xiaoyu Wang 已提交
290 291
  void doParseInsertSql(SParseContext* pCxt, SQuery** pQuery, SCatalogReq* pCatalogReq, const SMetaData* pMetaData) {
    DO_WITH_THROW(parseInsertSql, pCxt, pQuery, pCatalogReq, pMetaData);
X
Xiaoyu Wang 已提交
292 293 294 295
    ASSERT_NE(*pQuery, nullptr);
    res_.parsedAst_ = toString((*pQuery)->pRoot);
  }

X
Xiaoyu Wang 已提交
296 297
  void doContinueParseSql(SParseContext* pCxt, SCatalogReq* pCatalogReq, const SMetaData* pMetaData, SQuery* pQuery) {
    DO_WITH_THROW(qContinueParseSql, pCxt, pCatalogReq, pMetaData, pQuery);
X
Xiaoyu Wang 已提交
298 299
  }

X
Xiaoyu Wang 已提交
300 301 302 303
  string toString(const SNode* pRoot) {
    char*   pStr = NULL;
    int32_t len = 0;
    DO_WITH_THROW(nodesNodeToString, pRoot, false, &pStr, &len)
304 305 306 307
    // check toObject
    SNode* pCopy = NULL;
    DO_WITH_THROW(nodesStringToNode, pStr, &pCopy)
    nodesDestroyNode(pCopy);
X
Xiaoyu Wang 已提交
308 309 310 311 312
    string str(pStr);
    taosMemoryFreeClear(pStr);
    return str;
  }

X
Xiaoyu Wang 已提交
313 314
  void checkQuery(const SQuery* pQuery, ParserStage stage) { pBase_->checkDdl(pQuery, stage); }

315 316 317 318 319 320
  void runInternalFuncs(const string& sql, int32_t expect, ParserStage checkStage) {
    reset(expect, checkStage, TEST_INTERFACE_INTERNAL);
    try {
      SParseContext cxt = {0};
      setParseContext(sql, &cxt);

X
Xiaoyu Wang 已提交
321
      if (qIsInsertValuesSql(cxt.pSql, cxt.sqlLen)) {
322
        unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
X
Xiaoyu Wang 已提交
323
        doParseInsertSql(&cxt, query.get(), nullptr, nullptr);
X
Xiaoyu Wang 已提交
324
      } else {
325
        unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
X
Xiaoyu Wang 已提交
326 327
        doParse(&cxt, query.get());
        SQuery* pQuery = *(query.get());
328

X
Xiaoyu Wang 已提交
329
        doAuthenticate(&cxt, pQuery, nullptr);
330

X
Xiaoyu Wang 已提交
331
        doTranslate(&cxt, pQuery, nullptr);
332

X
Xiaoyu Wang 已提交
333 334
        doCalculateConstant(&cxt, pQuery);
      }
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

      if (g_dump) {
        dump();
      }
    } catch (const TerminateFlag& e) {
      // success and terminate
      return;
    } catch (...) {
      dump();
      throw;
    }
  }

  void runApis(const string& sql, int32_t expect, ParserStage checkStage) {
    reset(expect, checkStage, TEST_INTERFACE_API);
    try {
      SParseContext cxt = {0};
      setParseContext(sql, &cxt);

354
      unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
355
      doParseSql(&cxt, query.get());
356 357 358 359 360 361 362 363 364 365 366 367 368

      if (g_dump) {
        dump();
      }
    } catch (const TerminateFlag& e) {
      // success and terminate
      return;
    } catch (...) {
      dump();
      throw;
    }
  }

X
Xiaoyu Wang 已提交
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
  void runQueryAsyncInternalFuncs(SParseContext* pParCxt) {
    unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
    bool                                    request = true;
    unique_ptr<SParseMetaCache, function<void(SParseMetaCache*)> > metaCache(
        new SParseMetaCache(), bind(destoryParseMetaCacheWarpper, _1, cref(request)));
    doParse(pParCxt, query.get());
    doCollectMetaKey(pParCxt, *(query.get()), metaCache.get());

    SQuery* pQuery = *(query.get());

    unique_ptr<SCatalogReq, void (*)(SCatalogReq*)> catalogReq(new SCatalogReq(),
                                                               MockCatalogService::destoryCatalogReq);
    doBuildCatalogReq(pParCxt, metaCache.get(), catalogReq.get());

    string err;
    thread t1([&]() {
      try {
        unique_ptr<SMetaData, void (*)(SMetaData*)> metaData(new SMetaData(), MockCatalogService::destoryMetaData);
        doGetAllMeta(catalogReq.get(), metaData.get());

        metaCache.reset(new SParseMetaCache());
        request = false;
        doPutMetaDataToCache(catalogReq.get(), metaData.get(), metaCache.get());

        doAuthenticate(pParCxt, pQuery, metaCache.get());

        doTranslate(pParCxt, pQuery, metaCache.get());

        doCalculateConstant(pParCxt, pQuery);
      } catch (const TerminateFlag& e) {
        // success and terminate
      } catch (const runtime_error& e) {
        err = e.what();
      } catch (...) {
        err = "unknown error";
X
Xiaoyu Wang 已提交
404
      }
X
Xiaoyu Wang 已提交
405
    });
X
Xiaoyu Wang 已提交
406

X
Xiaoyu Wang 已提交
407 408 409 410 411
    t1.join();
    if (!err.empty()) {
      throw runtime_error(err);
    }
  }
412

X
Xiaoyu Wang 已提交
413 414 415
  void runInsertAsyncInternalFuncsImpl(SParseContext* pParCxt, SQuery** pQuery, SCatalogReq* pCatalogReq,
                                       SMetaData* pMetaData) {
    doParseInsertSql(pParCxt, pQuery, pCatalogReq, pMetaData);
416

X
Xiaoyu Wang 已提交
417 418 419
    if (QUERY_EXEC_STAGE_SCHEDULE == (*pQuery)->execStage) {
      return;
    }
420

X
Xiaoyu Wang 已提交
421 422 423 424
    string err;
    thread t1([&]() {
      try {
        doGetAllMeta(pCatalogReq, pMetaData);
425

X
Xiaoyu Wang 已提交
426
        doParseInsertSql(pParCxt, pQuery, pCatalogReq, pMetaData);
427

X
Xiaoyu Wang 已提交
428 429
        if (QUERY_EXEC_STAGE_SCHEDULE != (*pQuery)->execStage) {
          runInsertAsyncInternalFuncsImpl(pParCxt, pQuery, pCatalogReq, pMetaData);
430
        }
X
Xiaoyu Wang 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
      } catch (const TerminateFlag& e) {
        // success and terminate
      } catch (const runtime_error& e) {
        err = e.what();
      } catch (...) {
        err = "unknown error";
      }
    });

    t1.join();
    if (!err.empty()) {
      throw runtime_error(err);
    }
  }

  void runInsertAsyncInternalFuncs(SParseContext* pParCxt) {
    unique_ptr<SQuery*, void (*)(SQuery**)>         query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
    unique_ptr<SCatalogReq, void (*)(SCatalogReq*)> catalogReq(new SCatalogReq(),
                                                               MockCatalogService::destoryCatalogReq);
    unique_ptr<SMetaData, void (*)(SMetaData*)>     metaData(new SMetaData(), MockCatalogService::destoryMetaData);
    runInsertAsyncInternalFuncsImpl(pParCxt, query.get(), catalogReq.get(), metaData.get());
  }

  void runAsyncInternalFuncs(const string& sql, int32_t expect, ParserStage checkStage) {
    reset(expect, checkStage, TEST_INTERFACE_ASYNC_INTERNAL);
    try {
      unique_ptr<SParseContext, function<void(SParseContext*)> > cxt(new SParseContext(), destoryParseContext);
      setParseContext(sql, cxt.get(), true);
459

X
Xiaoyu Wang 已提交
460 461 462 463 464
      bool isInsertValues = qIsInsertValuesSql(cxt->pSql, cxt->sqlLen);
      if (isInsertValues) {
        runInsertAsyncInternalFuncs(cxt.get());
      } else {
        runQueryAsyncInternalFuncs(cxt.get());
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
      }

      if (g_dump) {
        dump();
      }
    } catch (const TerminateFlag& e) {
      // success and terminate
      return;
    } catch (...) {
      dump();
      throw;
    }
  }

  void runAsyncApis(const string& sql, int32_t expect, ParserStage checkStage) {
    reset(expect, checkStage, TEST_INTERFACE_ASYNC_API);
    try {
482 483
      unique_ptr<SParseContext, function<void(SParseContext*)> > cxt(new SParseContext(), destoryParseContext);
      setParseContext(sql, cxt.get());
484 485 486

      unique_ptr<SCatalogReq, void (*)(SCatalogReq*)> catalogReq(new SCatalogReq(),
                                                                 MockCatalogService::destoryCatalogReq);
487 488
      unique_ptr<SQuery*, void (*)(SQuery**)> query((SQuery**)taosMemoryCalloc(1, sizeof(SQuery*)), destroyQuery);
      doParseSqlSyntax(cxt.get(), query.get(), catalogReq.get());
489
      SQuery* pQuery = *(query.get());
490

X
Xiaoyu Wang 已提交
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
      switch (pQuery->execStage) {
        case QUERY_EXEC_STAGE_PARSE:
        case QUERY_EXEC_STAGE_ANALYSE: {
          string err;
          thread t1([&]() {
            try {
              unique_ptr<SMetaData, void (*)(SMetaData*)> metaData(new SMetaData(),
                                                                   MockCatalogService::destoryMetaData);
              doGetAllMeta(catalogReq.get(), metaData.get());
              if (QUERY_EXEC_STAGE_PARSE == pQuery->execStage) {
                doContinueParseSql(cxt.get(), catalogReq.get(), metaData.get(), pQuery);
              } else {
                doAnalyseSqlSemantic(cxt.get(), catalogReq.get(), metaData.get(), pQuery);
              }
            } catch (const TerminateFlag& e) {
              // success and terminate
            } catch (const runtime_error& e) {
              err = e.what();
            } catch (...) {
              err = "unknown error";
            }
          });

          t1.join();
          if (!err.empty()) {
            throw runtime_error(err);
          }
          break;
519
        }
X
Xiaoyu Wang 已提交
520 521 522 523
        case QUERY_EXEC_STAGE_SCHEDULE:
          break;
        default:
          break;
524 525 526 527 528 529 530 531 532 533 534 535 536 537
      }

      if (g_dump) {
        dump();
      }
    } catch (const TerminateFlag& e) {
      // success and terminate
      return;
    } catch (...) {
      dump();
      throw;
    }
  }

X
Xiaoyu Wang 已提交
538 539 540 541
  caseEnv         caseEnv_;
  stmtEnv         stmtEnv_;
  stmtRes         res_;
  ParserTestBase* pBase_;
X
Xiaoyu Wang 已提交
542
  int32_t         sqlNo_;
543
  int32_t         sqlNum_;
X
Xiaoyu Wang 已提交
544 545
};

X
Xiaoyu Wang 已提交
546
ParserTestBase::ParserTestBase() : impl_(new ParserTestBaseImpl(this)) {}
X
Xiaoyu Wang 已提交
547 548 549

ParserTestBase::~ParserTestBase() {}

550 551
void ParserTestBase::login(const std::string& user) { return impl_->login(user); }

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

554 555 556 557
void ParserTestBase::run(const std::string& sql, int32_t expect, ParserStage checkStage) {
  return impl_->run(sql, expect, checkStage);
}

X
Xiaoyu Wang 已提交
558 559
void ParserTestBase::checkDdl(const SQuery* pQuery, ParserStage stage) { return; }

560
}  // namespace ParserTest