301 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * 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 <gtest/gtest.h>
 | |
| 
 | |
| #include "nodes.h"
 | |
| #include "plannodes.h"
 | |
| #include "querynodes.h"
 | |
| 
 | |
| class NodesCloneTest : public testing::Test {
 | |
|  public:
 | |
|   void registerCheckFunc(const std::function<void(const SNode*, const SNode*)>& func) { checkFunc_ = func; }
 | |
| 
 | |
|   void run(const SNode* pSrc) {
 | |
|     std::unique_ptr<SNode, void (*)(SNode*)> pDst(nodesCloneNode(pSrc), nodesDestroyNode);
 | |
|     checkFunc_(pSrc, pDst.get());
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   std::function<void(const SNode*, const SNode*)> checkFunc_;
 | |
| };
 | |
| 
 | |
| TEST_F(NodesCloneTest, tempTable) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     STempTableNode* pSrcNode = (STempTableNode*)pSrc;
 | |
|     STempTableNode* pDstNode = (STempTableNode*)pDst;
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pSubquery), nodeType(pDstNode->pSubquery));
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_TEMP_TABLE));
 | |
|     STempTableNode* pNode = (STempTableNode*)srcNode.get();
 | |
|     pNode->pSubquery = nodesMakeNode(QUERY_NODE_SELECT_STMT);
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, joinTable) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SJoinTableNode* pSrcNode = (SJoinTableNode*)pSrc;
 | |
|     SJoinTableNode* pDstNode = (SJoinTableNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->joinType, pDstNode->joinType);
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pLeft), nodeType(pDstNode->pLeft));
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pRight), nodeType(pDstNode->pRight));
 | |
|     if (NULL != pSrcNode->pOnCond) {
 | |
|       ASSERT_EQ(nodeType(pSrcNode->pOnCond), nodeType(pDstNode->pOnCond));
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_JOIN_TABLE));
 | |
|     SJoinTableNode* pNode = (SJoinTableNode*)srcNode.get();
 | |
|     pNode->joinType = JOIN_TYPE_INNER;
 | |
|     pNode->pLeft = nodesMakeNode(QUERY_NODE_REAL_TABLE);
 | |
|     pNode->pRight = nodesMakeNode(QUERY_NODE_REAL_TABLE);
 | |
|     pNode->pOnCond = nodesMakeNode(QUERY_NODE_OPERATOR);
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, stateWindow) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SStateWindowNode* pSrcNode = (SStateWindowNode*)pSrc;
 | |
|     SStateWindowNode* pDstNode = (SStateWindowNode*)pDst;
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pCol), nodeType(pDstNode->pCol));
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pExpr), nodeType(pDstNode->pExpr));
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_STATE_WINDOW));
 | |
|     SStateWindowNode* pNode = (SStateWindowNode*)srcNode.get();
 | |
|     pNode->pCol = nodesMakeNode(QUERY_NODE_COLUMN);
 | |
|     pNode->pExpr = nodesMakeNode(QUERY_NODE_OPERATOR);
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, sessionWindow) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SSessionWindowNode* pSrcNode = (SSessionWindowNode*)pSrc;
 | |
|     SSessionWindowNode* pDstNode = (SSessionWindowNode*)pDst;
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pCol), nodeType(pDstNode->pCol));
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pGap), nodeType(pDstNode->pGap));
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_SESSION_WINDOW));
 | |
|     SSessionWindowNode* pNode = (SSessionWindowNode*)srcNode.get();
 | |
|     pNode->pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
 | |
|     pNode->pGap = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, intervalWindow) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SIntervalWindowNode* pSrcNode = (SIntervalWindowNode*)pSrc;
 | |
|     SIntervalWindowNode* pDstNode = (SIntervalWindowNode*)pDst;
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pInterval), nodeType(pDstNode->pInterval));
 | |
|     if (NULL != pSrcNode->pOffset) {
 | |
|       ASSERT_EQ(nodeType(pSrcNode->pOffset), nodeType(pDstNode->pOffset));
 | |
|     }
 | |
|     if (NULL != pSrcNode->pSliding) {
 | |
|       ASSERT_EQ(nodeType(pSrcNode->pSliding), nodeType(pDstNode->pSliding));
 | |
|     }
 | |
|     if (NULL != pSrcNode->pFill) {
 | |
|       ASSERT_EQ(nodeType(pSrcNode->pFill), nodeType(pDstNode->pFill));
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_INTERVAL_WINDOW));
 | |
|     SIntervalWindowNode* pNode = (SIntervalWindowNode*)srcNode.get();
 | |
|     pNode->pInterval = nodesMakeNode(QUERY_NODE_VALUE);
 | |
|     pNode->pOffset = nodesMakeNode(QUERY_NODE_VALUE);
 | |
|     pNode->pSliding = nodesMakeNode(QUERY_NODE_VALUE);
 | |
|     pNode->pFill = nodesMakeNode(QUERY_NODE_FILL);
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, fill) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SFillNode* pSrcNode = (SFillNode*)pSrc;
 | |
|     SFillNode* pDstNode = (SFillNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->mode, pDstNode->mode);
 | |
|     if (NULL != pSrcNode->pValues) {
 | |
|       ASSERT_EQ(nodeType(pSrcNode->pValues), nodeType(pDstNode->pValues));
 | |
|     }
 | |
|     ASSERT_EQ(nodeType(pSrcNode->pWStartTs), nodeType(pDstNode->pWStartTs));
 | |
|     ASSERT_EQ(pSrcNode->timeRange.skey, pDstNode->timeRange.skey);
 | |
|     ASSERT_EQ(pSrcNode->timeRange.ekey, pDstNode->timeRange.ekey);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_FILL));
 | |
|     SFillNode* pNode = (SFillNode*)srcNode.get();
 | |
|     pNode->mode = FILL_MODE_VALUE;
 | |
|     pNode->pValues = nodesMakeNode(QUERY_NODE_NODE_LIST);
 | |
|     pNode->pWStartTs = nodesMakeNode(QUERY_NODE_COLUMN);
 | |
|     pNode->timeRange.skey = 1666756692907;
 | |
|     pNode->timeRange.ekey = 1666756699907;
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, logicSubplan) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SLogicSubplan* pSrcNode = (SLogicSubplan*)pSrc;
 | |
|     SLogicSubplan* pDstNode = (SLogicSubplan*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->subplanType, pDstNode->subplanType);
 | |
|     ASSERT_EQ(pSrcNode->level, pDstNode->level);
 | |
|     ASSERT_EQ(pSrcNode->splitFlag, pDstNode->splitFlag);
 | |
|     ASSERT_EQ(pSrcNode->numOfComputeNodes, pDstNode->numOfComputeNodes);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_LOGIC_SUBPLAN));
 | |
|     SLogicSubplan* pNode = (SLogicSubplan*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiScan) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     STagScanPhysiNode* pSrcNode = (STagScanPhysiNode*)pSrc;
 | |
|     STagScanPhysiNode* pDstNode = (STagScanPhysiNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->scan.uid, pDstNode->scan.uid);
 | |
|     ASSERT_EQ(pSrcNode->scan.suid, pDstNode->scan.suid);
 | |
|     ASSERT_EQ(pSrcNode->scan.tableType, pDstNode->scan.tableType);
 | |
|     ASSERT_EQ(pSrcNode->onlyMetaCtbIdx, pDstNode->onlyMetaCtbIdx);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN));
 | |
|     STagScanPhysiNode* pNode = (STagScanPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiSystemTableScan) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SSystemTableScanPhysiNode* pSrcNode = (SSystemTableScanPhysiNode*)pSrc;
 | |
|     SSystemTableScanPhysiNode* pDstNode = (SSystemTableScanPhysiNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->showRewrite, pDstNode->showRewrite);
 | |
|     ASSERT_EQ(pSrcNode->accountId, pDstNode->accountId);
 | |
|     ASSERT_EQ(pSrcNode->sysInfo, pDstNode->sysInfo);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN));
 | |
|     SSystemTableScanPhysiNode* pNode = (SSystemTableScanPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiStreamSemiSessionWinodw) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SStreamSemiSessionWinodwPhysiNode* pSrcNode = (SStreamSemiSessionWinodwPhysiNode*)pSrc;
 | |
|     SStreamSemiSessionWinodwPhysiNode* pDstNode = (SStreamSemiSessionWinodwPhysiNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->gap, pDstNode->gap);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION));
 | |
|     SStreamSemiSessionWinodwPhysiNode* pNode = (SStreamSemiSessionWinodwPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiStreamFinalSessionWinodw) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SStreamFinalSessionWinodwPhysiNode* pSrcNode = (SStreamFinalSessionWinodwPhysiNode*)pSrc;
 | |
|     SStreamFinalSessionWinodwPhysiNode* pDstNode = (SStreamFinalSessionWinodwPhysiNode*)pDst;
 | |
|     ASSERT_EQ(pSrcNode->gap, pDstNode->gap);
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION));
 | |
|     SStreamFinalSessionWinodwPhysiNode* pNode = (SStreamFinalSessionWinodwPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiStreamPartition) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SStreamPartitionPhysiNode* pSrcNode = (SStreamPartitionPhysiNode*)pSrc;
 | |
|     SStreamPartitionPhysiNode* pDstNode = (SStreamPartitionPhysiNode*)pDst;
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION));
 | |
|     SStreamPartitionPhysiNode* pNode = (SStreamPartitionPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 | |
| 
 | |
| TEST_F(NodesCloneTest, physiPartition) {
 | |
|   registerCheckFunc([](const SNode* pSrc, const SNode* pDst) {
 | |
|     ASSERT_EQ(nodeType(pSrc), nodeType(pDst));
 | |
|     SPartitionPhysiNode* pSrcNode = (SPartitionPhysiNode*)pSrc;
 | |
|     SPartitionPhysiNode* pDstNode = (SPartitionPhysiNode*)pDst;
 | |
|   });
 | |
| 
 | |
|   std::unique_ptr<SNode, void (*)(SNode*)> srcNode(nullptr, nodesDestroyNode);
 | |
| 
 | |
|   run([&]() {
 | |
|     srcNode.reset(nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_PARTITION));
 | |
|     SPartitionPhysiNode* pNode = (SPartitionPhysiNode*)srcNode.get();
 | |
|     return srcNode.get();
 | |
|   }());
 | |
| }
 |