diff --git a/include/common/tmsg.h b/include/common/tmsg.h index 739d257d86..8366837b29 100644 --- a/include/common/tmsg.h +++ b/include/common/tmsg.h @@ -421,7 +421,7 @@ typedef enum ENodeType { // physical plan node QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN = 1100, QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, - QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, + QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, // INACTIVE QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN, @@ -435,7 +435,7 @@ typedef enum ENodeType { QUERY_NODE_PHYSICAL_PLAN_SORT, QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT, QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL, - QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, + QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, // INACTIVE QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL, QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL, diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index e5bacf85b2..3b5201aa1e 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -26,6 +26,8 @@ extern "C" { #define FUNC_AGGREGATE_UDF_ID 5001 #define FUNC_SCALAR_UDF_ID 5002 +extern const int32_t funcMgtBuiltinsNum; + typedef enum EFunctionType { // aggregate function FUNCTION_TYPE_APERCENTILE = 1, diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index a05211ece3..6d09ef6d88 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -788,9 +788,9 @@ typedef struct SDataDeleterNode { char tableFName[TSDB_TABLE_NAME_LEN]; char tsColName[TSDB_COL_NAME_LEN]; STimeWindow deleteTimeRange; - SNode* pAffectedRows; - SNode* pStartTs; - SNode* pEndTs; + SNode* pAffectedRows; // usless + SNode* pStartTs; // usless + SNode* pEndTs; // usless } SDataDeleterNode; typedef struct SSubplan { diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 81a3952463..d2f714f400 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -364,7 +364,7 @@ void* getTaskPoolWorkerCb(); #define NEED_CLIENT_REFRESH_VG_ERROR(_code) \ ((_code) == TSDB_CODE_VND_HASH_MISMATCH || (_code) == TSDB_CODE_VND_INVALID_VGROUP_ID) #define NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code) \ - ((_code) == TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER || (_code) == TSDB_CODE_MND_INVALID_SCHEMA_VER) + ((_code) == TSDB_CODE_TDB_INVALID_TABLE_SCHEMA_VER || (_code) == TSDB_CODE_MND_INVALID_SCHEMA_VER || (_code) == TSDB_CODE_SCH_DATA_SRC_EP_MISS) #define NEED_CLIENT_HANDLE_ERROR(_code) \ (NEED_CLIENT_RM_TBLMETA_ERROR(_code) || NEED_CLIENT_REFRESH_VG_ERROR(_code) || \ NEED_CLIENT_REFRESH_TBLMETA_ERROR(_code)) diff --git a/include/libs/scheduler/scheduler.h b/include/libs/scheduler/scheduler.h index b98170f168..af8deff1a0 100644 --- a/include/libs/scheduler/scheduler.h +++ b/include/libs/scheduler/scheduler.h @@ -76,8 +76,6 @@ int32_t schedulerExecJob(SSchedulerReq* pReq, int64_t* pJob); int32_t schedulerFetchRows(int64_t jobId, SSchedulerReq* pReq); -void schedulerFetchRowsA(int64_t job, schedulerFetchFp fp, void* param); - int32_t schedulerGetTasksStatus(int64_t job, SArray* pSub); void schedulerStopQueryHb(void* pTrans); @@ -100,6 +98,8 @@ void schedulerFreeJob(int64_t* job, int32_t errCode); void schedulerDestroy(void); +int32_t schedulerValidatePlan(SQueryPlan* pPlan); + #ifdef __cplusplus } #endif diff --git a/include/util/taoserror.h b/include/util/taoserror.h index a53923b904..2a67a3cae1 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -771,6 +771,7 @@ int32_t taosGetErrSize(); #define TSDB_CODE_SCH_TIMEOUT_ERROR TAOS_DEF_ERROR_CODE(0, 0x2504) #define TSDB_CODE_SCH_JOB_IS_DROPPING TAOS_DEF_ERROR_CODE(0, 0x2505) #define TSDB_CODE_SCH_JOB_NOT_EXISTS TAOS_DEF_ERROR_CODE(0, 0x2506) +#define TSDB_CODE_SCH_DATA_SRC_EP_MISS TAOS_DEF_ERROR_CODE(0, 0x2507) //parser #define TSDB_CODE_PAR_SYNTAX_ERROR TAOS_DEF_ERROR_CODE(0, 0x2600) diff --git a/include/util/tdef.h b/include/util/tdef.h index b924b377da..4aad89a142 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -188,6 +188,47 @@ typedef enum EOperatorType { OP_TYPE_ASSIGN = 200 } EOperatorType; +static const EOperatorType OPERATOR_ARRAY[] = { + OP_TYPE_ADD, + OP_TYPE_SUB, + OP_TYPE_MULTI, + OP_TYPE_DIV, + OP_TYPE_REM, + + OP_TYPE_MINUS, + + OP_TYPE_BIT_AND, + OP_TYPE_BIT_OR, + + OP_TYPE_GREATER_THAN, + OP_TYPE_GREATER_EQUAL, + OP_TYPE_LOWER_THAN, + OP_TYPE_LOWER_EQUAL, + OP_TYPE_EQUAL, + OP_TYPE_NOT_EQUAL, + OP_TYPE_IN, + OP_TYPE_NOT_IN, + OP_TYPE_LIKE, + OP_TYPE_NOT_LIKE, + OP_TYPE_MATCH, + OP_TYPE_NMATCH, + + OP_TYPE_IS_NULL, + OP_TYPE_IS_NOT_NULL, + OP_TYPE_IS_TRUE, + OP_TYPE_IS_FALSE, + OP_TYPE_IS_UNKNOWN, + OP_TYPE_IS_NOT_TRUE, + OP_TYPE_IS_NOT_FALSE, + OP_TYPE_IS_NOT_UNKNOWN, + //OP_TYPE_COMPARE_MAX_VALUE, + + OP_TYPE_JSON_GET_VALUE, + OP_TYPE_JSON_CONTAINS, + + OP_TYPE_ASSIGN +}; + #define OP_TYPE_CALC_MAX OP_TYPE_BIT_OR typedef enum ELogicConditionType { diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h index 8d45e8b4a8..114bc00125 100644 --- a/source/client/inc/clientInt.h +++ b/source/client/inc/clientInt.h @@ -58,6 +58,8 @@ enum { #define TD_RES_TMQ_METADATA(res) (*(int8_t*)(res) == RES_TYPE__TMQ_METADATA) #define TD_RES_TMQ_BATCH_META(res) (*(int8_t*)(res) == RES_TYPE__TMQ_BATCH_META) +#define TSC_MAX_SUBPLAN_CAPACITY_NUM 1000 + typedef struct SAppInstInfo SAppInstInfo; typedef struct { diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 9131d29f30..74fd4e13a7 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1250,6 +1250,7 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { void launchQueryImpl(SRequestObj* pRequest, SQuery* pQuery, bool keepQuery, void** res) { int32_t code = 0; + int32_t subplanNum = 0; if (pQuery->pRoot) { pRequest->stmtType = pQuery->pRoot->type; @@ -1405,6 +1406,7 @@ static int32_t asyncExecSchQuery(SRequestObj* pRequest, SQuery* pQuery, SMetaDat if (TSDB_CODE_SUCCESS == code) { code = schedulerExecJob(&req, &pRequest->body.queryJob); } + taosArrayDestroy(pNodeList); } else { qDestroyQueryPlan(pDag); diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index 7ea6b01bf3..834615bdaa 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -2346,8 +2346,13 @@ static void taosCheckAndSetDebugFlag(int32_t *pFlagPtr, char *name, int32_t flag if (noNeedToSetVars != NULL && taosArraySearch(noNeedToSetVars, name, taosLogVarComp, TD_EQ) != NULL) { return; } - if (taosSetDebugFlag(pFlagPtr, name, flag) != 0) { - uError("failed to set flag %s to %d", name, flag); + int32_t code = 0; + if ((code = taosSetDebugFlag(pFlagPtr, name, flag)) != 0) { + if (code != TSDB_CODE_CFG_NOT_FOUND) { + uError("failed to set flag %s to %d, since:%s", name, flag, tstrerror(code)); + } else { + uDebug("failed to set flag %s to %d, since:%s", name, flag, tstrerror(code)); + } } return; } diff --git a/source/libs/executor/inc/operator.h b/source/libs/executor/inc/operator.h index 7dfc7080d6..b2035ecfde 100644 --- a/source/libs/executor/inc/operator.h +++ b/source/libs/executor/inc/operator.h @@ -85,6 +85,8 @@ int32_t createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode* pExNo int32_t createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* pHandle, STableListInfo* pTableList, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo); +int32_t createTableSeqScanOperatorInfo(void* pReadHandle, SExecTaskInfo* pTaskInfo, SOperatorInfo** pOptrInfo); + int32_t createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanNode, SReadHandle* readHandle, STableListInfo* pTableListInfo, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo); int32_t createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysiNode* pPhyNode, STableListInfo* pTableListInfo, SNode* pTagCond, SNode*pTagIndexCond, SExecTaskInfo* pTaskInfo, SOperatorInfo** pInfo); diff --git a/source/libs/executor/test/CMakeLists.txt b/source/libs/executor/test/CMakeLists.txt index b5e58ee05e..c75de23c32 100644 --- a/source/libs/executor/test/CMakeLists.txt +++ b/source/libs/executor/test/CMakeLists.txt @@ -32,3 +32,15 @@ TARGET_INCLUDE_DIRECTORIES( PUBLIC "${TD_SOURCE_DIR}/include/common" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../inc" ) + +ADD_EXECUTABLE(queryPlanTests queryPlanTests.cpp) +TARGET_LINK_LIBRARIES( + queryPlanTests + PRIVATE os util common executor gtest_main qcom function planner scalar nodes vnode +) + +TARGET_INCLUDE_DIRECTORIES( + queryPlanTests + PUBLIC "${TD_SOURCE_DIR}/include/common" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../inc" +) diff --git a/source/libs/executor/test/queryPlanTests.cpp b/source/libs/executor/test/queryPlanTests.cpp new file mode 100755 index 0000000000..2b0c0e1118 --- /dev/null +++ b/source/libs/executor/test/queryPlanTests.cpp @@ -0,0 +1,3414 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include +#include + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wwrite-strings" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wsign-compare" +#pragma GCC diagnostic ignored "-Wformat" +#include + + +#ifdef WINDOWS +#define TD_USE_WINSOCK +#endif + +#include "os.h" + +#include "executor.h" +#include "executorInt.h" +#include "function.h" +#include "operator.h" +#include "taos.h" +#include "tdatablock.h" +#include "tdef.h" +#include "tvariant.h" +#include "stub.h" +#include "querytask.h" +#include "functionMgt.h" +#include "ttime.h" +#include "scheduler.h" + +namespace { + +#define QPT_MAX_LOOP 100000 +#define QPT_MAX_LEVEL_SUBPLAN_NUM 10 +#define QPT_MAX_SUBPLAN_LEVEL 2 +#define QPT_MAX_SUBPLAN_GROUP 5 +#define QPT_MAX_WHEN_THEN_NUM 10 +#define QPT_MAX_NODE_LEVEL 5 +#define QPT_MAX_STRING_LEN 1048576 +#define QPT_MAX_FUNC_PARAM 5 +#define QPT_MAX_LOGIC_PARAM 5 +#define QPT_MAX_NODE_LIST_NUM 5 +#define QPT_DEFAULT_VNODE_NUM 5 +#define QPT_MAX_DS_SRC_NUM 10 +#define QPT_MAX_ORDER_BY_NUM 10 +#define QPT_MAX_COLUMN_NUM 6 //8192 + +#define QPT_QUERY_NODE_COL 10000 + +typedef enum { + QPT_NODE_COLUMN, + QPT_NODE_EXPR, + QPT_NODE_FUNCTION, + QPT_NODE_VALUE, + QPT_NODE_SUBPLAN, + QPT_NODE_MAX_VALUE +} QPT_NODE_TYPE; + +enum { + QPT_PLAN_PHYSIC = 1, + QPT_PLAN_SINK, + QPT_PLAN_SUBPLAN, + QPT_PLAN_PLAN +}; + +typedef SNode* (*planBuildFunc)(int32_t); + + +typedef struct { + ENodeType type; + void* param; +} SQPTNodeParam; + +typedef struct { + bool singlePhysiNode; + uint64_t queryId; + uint64_t taskId; + int32_t subplanMaxLevel; + int32_t subplanType[QPT_MAX_SUBPLAN_LEVEL]; + int32_t subplanIdx[QPT_MAX_SUBPLAN_LEVEL]; + int32_t physiNodeParamNum; + SQPTNodeParam* physicNodeParam; +} SQPTPlanParam; + +typedef struct { + uint8_t precision; + char dbName[TSDB_DB_NAME_LEN]; +} SQPTDbParam; + + +typedef struct { + int32_t vnodeNum; + int32_t vgId; + SEpSet epSet; +} SQPTVnodeParam; + +typedef struct { + int32_t type; + char name[TSDB_COL_NAME_LEN]; + int32_t dtype; + int32_t len; + int8_t inUse; + bool hasIndex; + bool isPrimTs; + bool isPk; + EColumnType colType; +} SQPTCol; + +typedef struct { + int64_t uid; + int64_t suid; + int8_t tblType; + int32_t colNum; + int32_t tagNum; + int16_t pkNum; + char tblName[TSDB_TABLE_NAME_LEN]; + char tblAlias[TSDB_TABLE_NAME_LEN]; + SNodeList* pColList; + SNodeList* pTagList; + SNodeList* pColTagList; +} SQPTTblParam; + + +typedef struct { + bool correctExpected; + uint64_t schedulerId; + char userName[TSDB_USER_LEN]; + SQPTPlanParam plan; + SQPTDbParam db; + SQPTVnodeParam vnode; + SQPTTblParam tbl; +} SQPTParam; + + +typedef struct { + SPhysiNode* pCurr; + int32_t childrenNum; + SPhysiNode* pChild; // current child + SPhysiNode* pLeftChild; + SPhysiNode* pRightChild; + EOrder currTsOrder; + int16_t nextBlockId; + int32_t primaryTsSlotId; + int32_t nextSubplanId; + SExecTaskInfo* pCurrTask; +} SQPTBuildPlanCtx; + +typedef struct { + int32_t nodeLevel; + bool fromTable; + bool onlyTag; + bool onlyCol; + int16_t inputBlockId; + SNodeList* pInputList; +} SQPTMakeNodeCtx; + +typedef struct { + int64_t startTsUs; + int32_t code; + int64_t succeedTimes; + int64_t failedTimes; +} SQPTExecResult; + +typedef struct { + int32_t loopIdx; + char caseName[128]; + SQPTParam param; + SQPTBuildPlanCtx buildCtx; + SQPTMakeNodeCtx makeCtx; + SQPTMakeNodeCtx makeCtxBak; + SQPTExecResult result; +} SQPTCtx; + +typedef struct { + bool printTestInfo; + bool printInputRow; + bool printResRow; + bool logHistory; + bool noKeepResRows; +} SQPTCtrl; + +typedef struct { + int32_t type; + int32_t classify; + char* name; + planBuildFunc buildFunc; +} SQPTPlan; + +SNode* qptCreateTagScanPhysiNode(int32_t nodeType); +SNode* qptCreateTableScanPhysiNode(int32_t nodeType); +SNode* qptCreateTableSeqScanPhysiNode(int32_t nodeType); +SNode* qptCreateTableMergeScanPhysiNode(int32_t nodeType); +SNode* qptCreateStreamScanPhysiNode(int32_t nodeType); +SNode* qptCreateSysTableScanPhysiNode(int32_t nodeType); +SNode* qptCreateBlockDistScanPhysiNode(int32_t nodeType); +SNode* qptCreateLastRowScanPhysiNode(int32_t nodeType); +SNode* qptCreateTableCountScanPhysiNode(int32_t nodeType); + +SNode* qptCreateProjectPhysiNode(int32_t nodeType); +SNode* qptCreateMergeJoinPhysiNode(int32_t nodeType); +SNode* qptCreateHashAggPhysiNode(int32_t nodeType); +SNode* qptCreateExchangePhysiNode(int32_t nodeType); +SNode* qptCreateMergePhysiNode(int32_t nodeType); +SNode* qptCreateSortPhysiNode(int32_t nodeType); +SNode* qptCreateGroupSortPhysiNode(int32_t nodeType); +SNode* qptCreateIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateMergeIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateMergeAlignedIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateStreamIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateStreamFinalIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateStreamSemiIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateStreamMidIntervalPhysiNode(int32_t nodeType); +SNode* qptCreateFillPhysiNode(int32_t nodeType); +SNode* qptCreateStreamFillPhysiNode(int32_t nodeType); +SNode* qptCreateSessionPhysiNode(int32_t nodeType); +SNode* qptCreateStreamSessionPhysiNode(int32_t nodeType); +SNode* qptCreateStreamSemiSessionPhysiNode(int32_t nodeType); +SNode* qptCreateStreamFinalSessionPhysiNode(int32_t nodeType); +SNode* qptCreateStateWindowPhysiNode(int32_t nodeType); +SNode* qptCreateStreamStatePhysiNode(int32_t nodeType); +SNode* qptCreatePartitionPhysiNode(int32_t nodeType); +SNode* qptCreateStreamPartitionPhysiNode(int32_t nodeType); +SNode* qptCreateIndefRowsFuncPhysiNode(int32_t nodeType); +SNode* qptCreateInterpFuncPhysiNode(int32_t nodeType); +SNode* qptCreateMergeEventPhysiNode(int32_t nodeType); +SNode* qptCreateStreamEventPhysiNode(int32_t nodeType); +SNode* qptCreateCountWindowPhysiNode(int32_t nodeType); +SNode* qptCreateStreamCountWindowPhysiNode(int32_t nodeType); +SNode* qptCreateHashJoinPhysiNode(int32_t nodeType); +SNode* qptCreateGroupCachePhysiNode(int32_t nodeType); +SNode* qptCreateDynQueryCtrlPhysiNode(int32_t nodeType); +SNode* qptCreateDataDispatchPhysiNode(int32_t nodeType); +SNode* qptCreateDataInsertPhysiNode(int32_t nodeType); +SNode* qptCreateDataQueryInsertPhysiNode(int32_t nodeType); +SNode* qptCreateDataDeletePhysiNode(int32_t nodeType); +SNode* qptCreatePhysicalPlanNode(int32_t nodeIdx); +void qptCreatePhysiNodesTree(SPhysiNode** ppRes, SPhysiNode* pParent, int32_t level); +SNode* qptCreateQueryPlanNode(int32_t nodeType); +SNode* qptCreateSubplanNode(int32_t nodeType); + + +SQPTPlan qptPlans[] = { + {QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, QPT_PLAN_PHYSIC, "tagScan", qptCreateTagScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN, QPT_PLAN_PHYSIC, "tableScan", qptCreateTableScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN, QPT_PLAN_PHYSIC, "tableSeqScan", qptCreateTableSeqScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, QPT_PLAN_PHYSIC, "tableMergeScan", qptCreateTableMergeScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN, QPT_PLAN_PHYSIC, "streamScan", qptCreateStreamScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN, QPT_PLAN_PHYSIC, "sysTableScan", qptCreateSysTableScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN, QPT_PLAN_PHYSIC, "blockDistScan", qptCreateBlockDistScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN, QPT_PLAN_PHYSIC, "lastRowScan", qptCreateLastRowScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_PROJECT, QPT_PLAN_PHYSIC, "project", qptCreateProjectPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN, QPT_PLAN_PHYSIC, "mergeJoin", qptCreateMergeJoinPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_HASH_AGG, QPT_PLAN_PHYSIC, "hashAgg", qptCreateHashAggPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_EXCHANGE, QPT_PLAN_PHYSIC, "exchange", qptCreateExchangePhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE, QPT_PLAN_PHYSIC, "merge", qptCreateMergePhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_SORT, QPT_PLAN_PHYSIC, "sort", qptCreateSortPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT, QPT_PLAN_PHYSIC, "groupSort", qptCreateGroupSortPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL, QPT_PLAN_PHYSIC, "interval", qptCreateIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL, QPT_PLAN_PHYSIC, "mergeInterval", qptCreateMergeIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL, QPT_PLAN_PHYSIC, "mergeAlignedInterval", qptCreateMergeAlignedIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL, QPT_PLAN_PHYSIC, "streamInterval", qptCreateStreamIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL, QPT_PLAN_PHYSIC, "streamFinalInterval", qptCreateStreamFinalIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL, QPT_PLAN_PHYSIC, "streamSemiInterval", qptCreateStreamSemiIntervalPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_FILL, QPT_PLAN_PHYSIC, "fill", qptCreateFillPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_FILL, QPT_PLAN_PHYSIC, "streamFill", qptCreateStreamFillPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION, QPT_PLAN_PHYSIC, "sessionWindow", qptCreateSessionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION, QPT_PLAN_PHYSIC, "streamSession", qptCreateStreamSessionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION, QPT_PLAN_PHYSIC, "streamSemiSession", qptCreateStreamSemiSessionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION, QPT_PLAN_PHYSIC, "streamFinalSession", qptCreateStreamFinalSessionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE, QPT_PLAN_PHYSIC, "stateWindow", qptCreateStateWindowPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE, QPT_PLAN_PHYSIC, "streamState", qptCreateStreamStatePhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_PARTITION, QPT_PLAN_PHYSIC, "partition", qptCreatePartitionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION, QPT_PLAN_PHYSIC, "streamPartition", qptCreateStreamPartitionPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC, QPT_PLAN_PHYSIC, "indefRowsFunc", qptCreateIndefRowsFuncPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC, QPT_PLAN_PHYSIC, "interpFunc", qptCreateInterpFuncPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_DISPATCH, QPT_PLAN_SINK, "dataDispatch", qptCreateDataDispatchPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_INSERT, QPT_PLAN_SINK, "dataInseret", qptCreateDataInsertPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT, QPT_PLAN_SINK, "dataQueryInsert", qptCreateDataQueryInsertPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_DELETE, QPT_PLAN_SINK, "dataDelete", qptCreateDataDeletePhysiNode}, + {QUERY_NODE_PHYSICAL_SUBPLAN, QPT_PLAN_SUBPLAN, "subplan", qptCreateSubplanNode}, + {QUERY_NODE_PHYSICAL_PLAN, QPT_PLAN_PLAN, "plan", qptCreateQueryPlanNode}, + {QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN, QPT_PLAN_PHYSIC, "tableCountScan", qptCreateTableCountScanPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT, QPT_PLAN_PHYSIC, "eventWindow", qptCreateMergeEventPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT, QPT_PLAN_PHYSIC, "streamEventWindow", qptCreateStreamEventPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_HASH_JOIN, QPT_PLAN_PHYSIC, "hashJoin", qptCreateHashJoinPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_GROUP_CACHE, QPT_PLAN_PHYSIC, "groupCache", qptCreateGroupCachePhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_DYN_QUERY_CTRL, QPT_PLAN_PHYSIC, "dynQueryCtrl", qptCreateDynQueryCtrlPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT, QPT_PLAN_PHYSIC, "countWindow", qptCreateCountWindowPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT, QPT_PLAN_PHYSIC, "streamCountWindow", qptCreateStreamCountWindowPhysiNode}, + {QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL, QPT_PLAN_PHYSIC, "streamMidInterval", qptCreateStreamMidIntervalPhysiNode} +}; + + +#define QPT_PHYSIC_NODE_NUM() (sizeof(qptPlans)/sizeof(qptPlans[0])) +#define QPT_RAND_BOOL_V ((taosRand() % 2) ? true : false) +#define QPT_RAND_ORDER_V (QPT_RAND_BOOL_V ? ORDER_ASC : ORDER_DESC) +#define QPT_RAND_INT_V (taosRand() * (QPT_RAND_BOOL_V ? 1 : -1)) +#define QPT_LOW_PROB() ((taosRand() % 11) == 0) +#define QPT_MID_PROB() ((taosRand() % 11) <= 1) +#define QPT_HIGH_PROB() ((taosRand() % 11) <= 7) + +#define QPT_CORRECT_HIGH_PROB() (qptCtx.param.correctExpected || QPT_HIGH_PROB()) +#define QPT_NCORRECT_LOW_PROB() (!qptCtx.param.correctExpected && QPT_LOW_PROB()) + +#define QPT_VALID_DESC(_desc) ((_desc) && (QUERY_NODE_DATABLOCK_DESC == nodeType(_desc))) + +SQPTCtx qptCtx = {0}; +SQPTCtrl qptCtrl = {1, 0, 0, 0, 0}; +bool qptErrorRerun = false; +bool qptInRerun = false; +int32_t qptSink[] = {QUERY_NODE_PHYSICAL_PLAN_DISPATCH, QUERY_NODE_PHYSICAL_PLAN_INSERT, QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT, QUERY_NODE_PHYSICAL_PLAN_DELETE}; + + +SNode* qptMakeExprNode(SNode** ppNode); +void qptMakeNodeList(QPT_NODE_TYPE nodeType, SNodeList** ppList); + +int32_t qptGetSpecificPlanIndex(int32_t type) { + int32_t planNum = sizeof(qptPlans) / sizeof(qptPlans[0]); + for (int32_t i = 0; i < planNum; ++i) { + if (qptPlans[i].type == type) { + return i; + } + } + + return -1; +} + +int32_t qptGetColumnRandLen(int32_t colType) { + switch (colType) { + case TSDB_DATA_TYPE_NULL: + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: + return tDataTypes[colType].bytes; + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_GEOMETRY: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + case TSDB_DATA_TYPE_NCHAR: + return taosRand() % TSDB_MAX_BINARY_LEN; + default: + assert(0); + break; + } + + return 0; +} + + +void qptInitSingleTableCol(SQPTCol* pCol, int32_t idx, EColumnType colType) { + if (COLUMN_TYPE_COLUMN == colType && 0 == idx) { + sprintf(pCol->name, "primts%d", idx); + pCol->dtype = TSDB_DATA_TYPE_TIMESTAMP; + pCol->len = qptGetColumnRandLen(pCol->dtype); + pCol->inUse = 0; + pCol->hasIndex = false; + pCol->isPrimTs = true; + pCol->isPk = false; + pCol->colType = colType; + + return; + } + + sprintf(pCol->name, "%s%d", COLUMN_TYPE_COLUMN == colType ? "col" : "tag", idx); + pCol->dtype = taosRand() % TSDB_DATA_TYPE_MAX; + pCol->len = qptGetColumnRandLen(pCol->dtype); + pCol->inUse = 0; + pCol->hasIndex = COLUMN_TYPE_COLUMN == colType ? false : QPT_RAND_BOOL_V; + pCol->isPrimTs = false; + pCol->isPk = COLUMN_TYPE_COLUMN == colType ? QPT_RAND_BOOL_V : false;; + pCol->colType = colType; +} + + +void qptPrintBeginInfo() { + if (!qptCtrl.printTestInfo) { + return; + } + + printf("\n%dth TEST [%s] START\n", qptCtx.loopIdx, qptCtx.caseName); + +/* + char inputStat[4] = {0}; + JT_PRINTF("\n%dth TEST [%s] START\nBasic Info:\n\t asc:%d\n\t filter:%d\n\t maxRows:left-%d right-%d\n\t " + "maxGrpRows:left-%d right-%d\n\t blkRows:%d\n\t colCond:%s\n\t joinType:%s\n\t " + "subType:%s\n\t inputStat:%s\n\t groupJoin:%s\n", jtCtx.loopIdx, caseName, jtCtx.asc, jtCtx.filter, jtCtx.leftMaxRows, jtCtx.rightMaxRows, + jtCtx.leftMaxGrpRows, jtCtx.rightMaxGrpRows, jtCtx.blkRows, jtColCondStr[jtCtx.colCond], jtJoinTypeStr[jtCtx.joinType], + jtSubTypeStr[jtCtx.subType], getInputStatStr(inputStat), jtCtx.grpJoin ? "true" : "false"); + + if (JOIN_STYPE_ASOF == jtCtx.subType) { + JT_PRINTF("\t asofOp:%s\n\t JLimit:%" PRId64 "\n", getAsofOpStr(), jtCtx.jLimit); + } else if (JOIN_STYPE_WIN == jtCtx.subType) { + JT_PRINTF("\t windowOffset:[%" PRId64 ", %" PRId64 "]\n\t JLimit:%" PRId64 "\n", jtCtx.winStartOffset, jtCtx.winEndOffset, jtCtx.jLimit); + } + + JT_PRINTF("Input Info:\n\t totalBlk:left-%d right-%d\n\t totalRows:left-%d right-%d\n\t " + "blkRowSize:%d\n\t inputCols:left-%s %s %s %s right-%s %s %s %s\n", + (int32_t)taosArrayGetSize(jtCtx.leftBlkList), (int32_t)taosArrayGetSize(jtCtx.rightBlkList), + jtCtx.leftTotalRows, jtCtx.rightTotalRows, + jtCtx.blkRowSize, tDataTypes[jtInputColType[0]].name, tDataTypes[jtInputColType[1]].name, + tDataTypes[jtInputColType[2]].name, tDataTypes[jtInputColType[3]].name, tDataTypes[jtInputColType[0]].name, + tDataTypes[jtInputColType[1]].name, tDataTypes[jtInputColType[2]].name, tDataTypes[jtInputColType[3]].name); + + if (jtCtx.colEqNum) { + JT_PRINTF("\t colEqNum:%d\n", jtCtx.colEqNum); + printColList("colEqList", false, jtCtx.colEqList, false, "="); + } + + if (jtCtx.colOnNum) { + JT_PRINTF("\t colOnNum:%d\n", jtCtx.colOnNum); + printColList("colOnList", false, jtCtx.colOnList, false, ">"); + } + + if (jtCtx.leftFilterNum) { + JT_PRINTF("\t leftFilterNum:%d\n", jtCtx.leftFilterNum); + printColList("leftFilterList", true, jtCtx.leftFilterColList, true, ">"); + } + + if (jtCtx.rightFilterNum) { + JT_PRINTF("\t rightFilterNum:%d\n", jtCtx.rightFilterNum); + printColList("rightFilterList", false, jtCtx.rightFilterColList, true, ">"); + } + + JT_PRINTF("\t resColSize:%d\n\t resColNum:%d\n\t resColList:", jtCtx.resColSize, jtCtx.resColNum); + for (int32_t i = 0; i < jtCtx.resColNum; ++i) { + int32_t s = jtCtx.resColInSlot[i]; + int32_t idx = s >= MAX_SLOT_NUM ? s - MAX_SLOT_NUM : s; + JT_PRINTF("%sc%d[%s]\t", s >= MAX_SLOT_NUM ? "r" : "l", s, tDataTypes[jtInputColType[idx]].name); + } + + if (jtCtrl.printInputRow) { + printInputData(); + } +*/ +} + +void qptPrintEndInfo() { + if (!qptCtrl.printTestInfo) { + return; + } + + printf("\n\t%dth TEST [%s] END, result - %s%s\n", qptCtx.loopIdx, qptCtx.caseName, + (0 == qptCtx.result.code) ? "succeed" : "failed with error:", + (0 == qptCtx.result.code) ? "" : tstrerror(qptCtx.result.code)); +} + +void qptPrintStatInfo() { + printf("\n\tAll %d times TEST [%s] END, result - succeed:%" PRId64 " failed:%" PRId64 "\n", qptCtx.loopIdx + 1, qptCtx.caseName, + qptCtx.result.succeedTimes, qptCtx.result.failedTimes); +} + + +bool qptGetDynamicOp() { + if (QPT_NCORRECT_LOW_PROB()) { + return QPT_RAND_BOOL_V; + } + + if (qptCtx.buildCtx.pChild) { + return qptCtx.buildCtx.pChild->dynamicOp; + } + + return QPT_RAND_BOOL_V; +} + +EOrder qptGetCurrTsOrder() { + return QPT_CORRECT_HIGH_PROB() ? qptCtx.buildCtx.currTsOrder : QPT_RAND_ORDER_V; +} + +void qptGetRandValue(uint8_t* pType, int32_t* pLen, void** ppVal) { + if (*pType == (uint8_t)-1 || QPT_NCORRECT_LOW_PROB()) { + int32_t typeMax = TSDB_DATA_TYPE_MAX; + if (QPT_NCORRECT_LOW_PROB()) { + typeMax++; + } + + *pType = taosRand() % typeMax; + } + + switch (*pType) { + case TSDB_DATA_TYPE_NULL: + *pLen = QPT_CORRECT_HIGH_PROB() ? 0 : taosRand(); + if (ppVal) { + *ppVal = NULL; + } + break; + case TSDB_DATA_TYPE_BOOL: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(bool*)*ppVal = QPT_RAND_BOOL_V; + } + break; + case TSDB_DATA_TYPE_TINYINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(int8_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_SMALLINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(int16_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_INT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(int32_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(int64_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_FLOAT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(float*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_DOUBLE: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(double*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_GEOMETRY: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + *pLen = taosRand() % QPT_MAX_STRING_LEN; + if (ppVal) { + *ppVal = taosMemoryCalloc(1, *pLen + VARSTR_HEADER_SIZE); + assert(*ppVal); + varDataSetLen(*ppVal, *pLen); + memset((char*)*ppVal + VARSTR_HEADER_SIZE, 'A' + taosRand() % 26, *pLen); + } + break; + case TSDB_DATA_TYPE_NCHAR: { + *pLen = taosRand() % QPT_MAX_STRING_LEN; + if (ppVal) { + char* pTmp = (char*)taosMemoryCalloc(1, *pLen + 1); + assert(pTmp); + memset(pTmp, 'A' + taosRand() % 26, *pLen); + *ppVal = taosMemoryCalloc(1, *pLen * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE); + assert(*ppVal); + assert(taosMbsToUcs4(pTmp, *pLen, (TdUcs4 *)varDataVal(*ppVal), *pLen * TSDB_NCHAR_SIZE, NULL)); + *pLen *= TSDB_NCHAR_SIZE; + varDataSetLen(*ppVal, *pLen); + taosMemoryFree(pTmp); + } + break; + } + case TSDB_DATA_TYPE_UTINYINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(uint8_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_USMALLINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(uint16_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_UINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(uint32_t*)*ppVal = taosRand(); + } + break; + case TSDB_DATA_TYPE_UBIGINT: + *pLen = QPT_CORRECT_HIGH_PROB() ? tDataTypes[*pType].bytes : taosRand(); + if (ppVal) { + *ppVal = taosMemoryMalloc(tDataTypes[*pType].bytes); + assert(*ppVal); + *(uint64_t*)*ppVal = taosRand(); + } + break; + default: + *pLen = taosRand() % QPT_MAX_STRING_LEN; + if (ppVal) { + *ppVal = taosMemoryCalloc(1, *pLen); + assert(*ppVal); + memset((char*)*ppVal, 'a' + taosRand() % 26, *pLen); + } + break; + } +} + +void qptFreeRandValue(int32_t* pType, void* pVal) { + switch (*pType) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: + case TSDB_DATA_TYPE_TIMESTAMP: + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: + taosMemoryFree(pVal); + break; + case TSDB_DATA_TYPE_NULL: + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_GEOMETRY: + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + break; + default: + assert(0); + break; + } +} + +void qptGetRandRealTableType(int8_t* tableType) { + while (true) { + int8_t tType = taosRand() % TSDB_TABLE_MAX; + switch (tType) { + case TSDB_SUPER_TABLE: + case TSDB_CHILD_TABLE: + case TSDB_NORMAL_TABLE: + case TSDB_SYSTEM_TABLE: + *tableType = tType; + return; + default: + break; + } + } +} + +int32_t qptGetInputSlotId(SDataBlockDescNode* pInput) { + if (pInput && pInput->pSlots && pInput->pSlots->length > 0 && QPT_CORRECT_HIGH_PROB()) { + return taosRand() % pInput->pSlots->length; + } + + return taosRand(); +} + +ENullOrder qptGetRandNullOrder() { + if (QPT_NCORRECT_LOW_PROB()) { + return (ENullOrder)taosRand(); + } + + return (ENullOrder)(taosRand() % NULL_ORDER_LAST + 1); +} + +int8_t qptGetRandTimestampUnit() { + static int8_t units[] = {TIME_UNIT_NANOSECOND, TIME_UNIT_MICROSECOND, TIME_UNIT_MILLISECOND, TIME_UNIT_SECOND, + TIME_UNIT_MINUTE, TIME_UNIT_HOUR, TIME_UNIT_DAY, TIME_UNIT_WEEK, TIME_UNIT_MONTH, TIME_UNIT_YEAR}; + + return units[taosRand() % (sizeof(units) / sizeof(units[0]))]; +} + +int32_t qptGetInputPrimaryTsSlotId() { + if (QPT_CORRECT_HIGH_PROB()) { + return qptCtx.buildCtx.primaryTsSlotId; + } + + return taosRand() % QPT_MAX_COLUMN_NUM; +} + +int32_t qptGetRandSubplanMsgType() { + int32_t msgTypeList[] = {TDMT_VND_DELETE, TDMT_SCH_MERGE_QUERY, TDMT_SCH_QUERY, TDMT_VND_SUBMIT}; + + return QPT_CORRECT_HIGH_PROB() ? msgTypeList[taosRand() % (sizeof(msgTypeList)/sizeof(msgTypeList[0]))] : taosRand(); +} + +void qptNodesCalloc(int32_t num, int32_t size, void** pOut) { + void* p = taosMemoryCalloc(num, size); + assert(p); + *(char*)p = 0; + *pOut = (char*)p + 1; +} + +void qptNodesFree(void* pNode) { + void* p = (char*)pNode - 1; + taosMemoryFree(p); +} + +EFillMode qptGetRandFillMode() { + if (QPT_CORRECT_HIGH_PROB()) { + return (EFillMode)(taosRand() % FILL_MODE_NEXT + 1); + } + + return (EFillMode)(taosRand()); +} + + +void qptGetRandTimeWindow(STimeWindow* pWindow) { + if (QPT_CORRECT_HIGH_PROB()) { + pWindow->skey = taosRand(); + pWindow->ekey = pWindow->skey + taosRand(); + return; + } + + pWindow->skey = taosRand(); + pWindow->ekey = taosRand(); +} + +int32_t qptGetSubplanNum(SNodeList* pList) { + if (QPT_NCORRECT_LOW_PROB()) { + return taosRand(); + } + + int32_t subplanNum = 0; + SNode* pNode = NULL; + FOREACH(pNode, pList) { + if (NULL == pNode || QUERY_NODE_NODE_LIST != nodeType(pNode)) { + continue; + } + + SNodeListNode* pNodeListNode = (SNodeListNode*)pNode; + + if (NULL == pNodeListNode->pNodeList) { + continue; + } + + subplanNum += pNodeListNode->pNodeList->length; + } + + return subplanNum; +} + +int32_t qptNodesListAppend(SNodeList* pList, SNode* pNode) { + SListCell* p = NULL; + qptNodesCalloc(1, sizeof(SListCell), (void**)&p); + + p->pNode = pNode; + if (NULL == pList->pHead) { + pList->pHead = p; + } + if (NULL != pList->pTail) { + pList->pTail->pNext = p; + } + p->pPrev = pList->pTail; + pList->pTail = p; + ++(pList->length); + return TSDB_CODE_SUCCESS; +} + +int32_t qptNodesListStrictAppend(SNodeList* pList, SNode* pNode) { + int32_t code = qptNodesListAppend(pList, pNode); + if (TSDB_CODE_SUCCESS != code) { + nodesDestroyNode(pNode); + } + return code; +} + +int32_t qptNodesListMakeStrictAppend(SNodeList** pList, SNode* pNode) { + if (NULL == *pList) { + int32_t code = nodesMakeList(pList); + if (NULL == *pList) { + return code; + } + } + return qptNodesListStrictAppend(*pList, pNode); +} + +SNode* qptMakeRandNode(SNode** ppNode) { + SNode* pNode = NULL; + nodesMakeNode((ENodeType)taosRand(), ppNode ? ppNode : &pNode); + return ppNode ? *ppNode : pNode; +} + + + +SNode* qptMakeColumnFromTable(int32_t colIdx) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(NULL); + } + + if (colIdx < 0) { + return NULL; + } + + SColumnNode* pCol = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol)); + assert(pCol); + + SQPTCol fakeCol; + fakeCol.type = QPT_QUERY_NODE_COL; + qptInitSingleTableCol(&fakeCol, taosRand(), (EColumnType)(taosRand() % COLUMN_TYPE_GROUP_KEY + 1)); + + SQPTCol* pTbCol = qptCtx.makeCtx.pInputList ? (SQPTCol*)nodesListGetNode(qptCtx.makeCtx.pInputList, colIdx) : &fakeCol; + + int16_t blkId = QPT_CORRECT_HIGH_PROB() ? qptCtx.makeCtx.inputBlockId : taosRand(); + + if (QPT_CORRECT_HIGH_PROB()) { + pCol->node.resType.type = pTbCol->dtype; + pCol->node.resType.bytes = pTbCol->len; + + pCol->tableId = qptCtx.param.tbl.uid; + pCol->tableType = qptCtx.param.tbl.tblType; + pCol->colId = colIdx; + pCol->projIdx = colIdx; + pCol->colType = pTbCol->colType; + pCol->hasIndex = pTbCol->hasIndex; + pCol->isPrimTs = pTbCol->isPrimTs; + strcpy(pCol->dbName, qptCtx.param.db.dbName); + strcpy(pCol->tableName, qptCtx.param.tbl.tblName); + strcpy(pCol->tableAlias, qptCtx.param.tbl.tblAlias); + strcpy(pCol->colName, pTbCol->name); + pCol->dataBlockId = blkId; + pCol->slotId = colIdx; + pCol->numOfPKs = qptCtx.param.tbl.pkNum; + pCol->tableHasPk = qptCtx.param.tbl.pkNum > 0; + pCol->isPk = pTbCol->isPk; + pCol->projRefIdx = 0; + pCol->resIdx = 0; + } else { + qptGetRandValue(&pCol->node.resType.type, &pCol->node.resType.bytes, NULL); + + pCol->tableId = taosRand(); + pCol->tableType = taosRand() % TSDB_TABLE_MAX; + pCol->colId = QPT_RAND_BOOL_V ? taosRand() : colIdx; + pCol->projIdx = taosRand(); + pCol->colType = QPT_RAND_BOOL_V ? pTbCol->colType : (EColumnType)(taosRand() % (COLUMN_TYPE_GROUP_KEY + 1)); + pCol->hasIndex = QPT_RAND_BOOL_V; + pCol->isPrimTs = QPT_RAND_BOOL_V; + if (QPT_RAND_BOOL_V) { + pCol->dbName[0] = 0; + } else { + strcpy(pCol->dbName, qptCtx.param.db.dbName); + } + if (QPT_RAND_BOOL_V) { + pCol->tableName[0] = 0; + } else { + strcpy(pCol->tableName, qptCtx.param.tbl.tblName); + } + if (QPT_RAND_BOOL_V) { + pCol->tableAlias[0] = 0; + } else { + strcpy(pCol->tableAlias, qptCtx.param.tbl.tblAlias); + } + if (QPT_RAND_BOOL_V) { + pCol->colName[0] = 0; + } else { + strcpy(pCol->colName, pTbCol->name); + } + + pCol->dataBlockId = blkId; + pCol->slotId = QPT_RAND_BOOL_V ? taosRand() : colIdx; + pCol->numOfPKs = QPT_RAND_BOOL_V ? taosRand() : qptCtx.param.tbl.pkNum; + pCol->tableHasPk = QPT_RAND_BOOL_V ? QPT_RAND_BOOL_V : (qptCtx.param.tbl.pkNum > 0); + pCol->isPk = QPT_RAND_BOOL_V ? QPT_RAND_BOOL_V : pTbCol->isPk; + pCol->projRefIdx = taosRand(); + pCol->resIdx = taosRand(); + } + + return (SNode*)pCol; +} + + +SNode* qptMakeWhenThenNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + assert(0 == nodesMakeNode(QUERY_NODE_WHEN_THEN, ppNode)); + assert(*ppNode); + SWhenThenNode* pWhenThen = (SWhenThenNode*)*ppNode; + + qptMakeExprNode(&pWhenThen->pWhen); + + qptMakeExprNode(&pWhenThen->pThen); + + return *ppNode; +} + + +SNode* qptMakeCaseWhenNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + assert(0 == nodesMakeNode(QUERY_NODE_CASE_WHEN, ppNode)); + assert(*ppNode); + + SCaseWhenNode* pCaseWhen = (SCaseWhenNode*)*ppNode; + + qptCtx.makeCtx.nodeLevel++; + + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pCaseWhen->pCase); + } + + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pCaseWhen->pElse); + } + + int32_t whenNum = taosRand() % QPT_MAX_WHEN_THEN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < whenNum; ++i) { + SNode* pNode = NULL; + qptMakeWhenThenNode(&pNode); + qptNodesListMakeStrictAppend(&pCaseWhen->pWhenThenList, pNode); + } + + return *ppNode; +} + + +SNode* qptMakeOperatorNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + EOperatorType opType = OPERATOR_ARRAY[taosRand() % (sizeof(OPERATOR_ARRAY)/sizeof(OPERATOR_ARRAY[0]))]; + assert(0 == nodesMakeNode(QUERY_NODE_OPERATOR, ppNode)); + + SOperatorNode* pOp = (SOperatorNode*)*ppNode; + pOp->opType = QPT_CORRECT_HIGH_PROB() ? opType : (EOperatorType)(opType + 1); + + qptCtx.makeCtx.nodeLevel++; + + switch (pOp->opType) { + case OP_TYPE_ADD: + case OP_TYPE_SUB: + case OP_TYPE_MULTI: + case OP_TYPE_DIV: + case OP_TYPE_REM: + case OP_TYPE_BIT_AND: + case OP_TYPE_BIT_OR: + case OP_TYPE_GREATER_THAN: + case OP_TYPE_GREATER_EQUAL: + case OP_TYPE_LOWER_THAN: + case OP_TYPE_LOWER_EQUAL: + case OP_TYPE_EQUAL: + case OP_TYPE_NOT_EQUAL: + case OP_TYPE_LIKE: + case OP_TYPE_NOT_LIKE: + case OP_TYPE_MATCH: + case OP_TYPE_NMATCH: + case OP_TYPE_IN: + case OP_TYPE_NOT_IN: + case OP_TYPE_JSON_GET_VALUE: + case OP_TYPE_JSON_CONTAINS: + case OP_TYPE_ASSIGN: + if (QPT_CORRECT_HIGH_PROB()) { + qptMakeExprNode(&pOp->pLeft); + qptMakeExprNode(&pOp->pRight); + } else { + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pLeft); + } + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pRight); + } + } + break; + + case OP_TYPE_IS_NULL: + case OP_TYPE_IS_NOT_NULL: + case OP_TYPE_IS_TRUE: + case OP_TYPE_IS_FALSE: + case OP_TYPE_IS_UNKNOWN: + case OP_TYPE_IS_NOT_TRUE: + case OP_TYPE_IS_NOT_FALSE: + case OP_TYPE_IS_NOT_UNKNOWN: + case OP_TYPE_MINUS: + if (QPT_CORRECT_HIGH_PROB()) { + qptMakeExprNode(&pOp->pLeft); + } else { + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pLeft); + } + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pRight); + } + } + break; + default: + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pLeft); + } + if (QPT_RAND_BOOL_V) { + qptMakeExprNode(&pOp->pRight); + } + break; + } + + return *ppNode; +} + +SNode* qptMakeColumnNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SColumnNode* pCol = NULL; + + if (QPT_CORRECT_HIGH_PROB() && qptCtx.makeCtx.pInputList) { + SNodeList* pColList = qptCtx.makeCtx.pInputList; + int32_t colIdx = taosRand() % pColList->length; + SQPTCol* pNode = (SQPTCol*)nodesListGetNode(pColList, colIdx); + if (pNode) { + switch (pNode->type) { + case QUERY_NODE_SLOT_DESC: { + nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol); + SSlotDescNode* pSlot = (SSlotDescNode*)pNode; + pCol->node.resType = pSlot->dataType; + pCol->dataBlockId = qptCtx.makeCtx.inputBlockId; + pCol->slotId = pSlot->slotId; + break; + } + case QPT_QUERY_NODE_COL: { + pCol = (SColumnNode*)qptMakeColumnFromTable(colIdx); + break; + } + default: + break; + } + } + } + + if (NULL == pCol) { + nodesMakeNode(QUERY_NODE_COLUMN, (SNode**)&pCol); + qptGetRandValue(&pCol->node.resType.type, &pCol->node.resType.bytes, NULL); + pCol->dataBlockId = taosRand(); + pCol->slotId = taosRand(); + } + + *ppNode = (SNode*)pCol; + + return *ppNode; +} + +void qptNodesSetValueNodeValue(SValueNode* pNode, void* value) { + switch (pNode->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + taosMemoryFree(value); + break; + case TSDB_DATA_TYPE_BOOL: + pNode->datum.b = *(bool*)value; + taosMemoryFree(value); + *(bool*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.b : QPT_RAND_BOOL_V; + break; + case TSDB_DATA_TYPE_TINYINT: + pNode->datum.i = *(int8_t*)value; + taosMemoryFree(value); + *(int8_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.i : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_SMALLINT: + pNode->datum.i = *(int16_t*)value; + taosMemoryFree(value); + *(int16_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.i : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_INT: + pNode->datum.i = *(int32_t*)value; + taosMemoryFree(value); + *(int32_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.i : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_BIGINT: + pNode->datum.i = *(int64_t*)value; + taosMemoryFree(value); + *(int64_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.i : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_TIMESTAMP: + pNode->datum.i = *(int64_t*)value; + taosMemoryFree(value); + *(int64_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.i : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_UTINYINT: + pNode->datum.u = *(int8_t*)value; + taosMemoryFree(value); + *(int8_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.u : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_USMALLINT: + pNode->datum.u = *(int16_t*)value; + taosMemoryFree(value); + *(int16_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.u : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_UINT: + pNode->datum.u = *(int32_t*)value; + taosMemoryFree(value); + *(int32_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.u : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_UBIGINT: + pNode->datum.u = *(uint64_t*)value; + taosMemoryFree(value); + *(uint64_t*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.u : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_FLOAT: + pNode->datum.d = *(float*)value; + taosMemoryFree(value); + *(float*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.d : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_DOUBLE: + pNode->datum.d = *(double*)value; + taosMemoryFree(value); + *(double*)&pNode->typeData = qptCtx.param.correctExpected ? pNode->datum.d : QPT_RAND_INT_V; + break; + case TSDB_DATA_TYPE_NCHAR: + case TSDB_DATA_TYPE_VARCHAR: + case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_GEOMETRY: + if (qptCtx.param.correctExpected || QPT_MID_PROB()) { + pNode->datum.p = (char*)value; + } else { + } + taosMemoryFree(value); + pNode->datum.p = NULL; + break; + case TSDB_DATA_TYPE_DECIMAL: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: + taosMemoryFree(value); + pNode->datum.p = NULL; + break; + default: + taosMemoryFree(value); + break; + } +} + + +SNode* qptMakeValueNode(uint8_t valType, SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SValueNode* pVal = NULL; + nodesMakeNode(QUERY_NODE_VALUE, (SNode**)&pVal); + + int32_t valBytes; + void* pValue = NULL; + qptGetRandValue(&valType, &valBytes, &pValue); + + pVal->node.resType.type = valType; + pVal->node.resType.bytes = valBytes; + + qptNodesSetValueNodeValue(pVal, pValue); + + *ppNode = (SNode*)pVal; + + return *ppNode; +} + +SNode* qptMakeFunctionNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SFunctionNode* pFunc = NULL; + nodesMakeNode(QUERY_NODE_FUNCTION, (SNode**)&pFunc); + + if (QPT_CORRECT_HIGH_PROB()) { + int32_t funcIdx = taosRand() % funcMgtBuiltinsNum; + char* funcName = fmGetFuncName(funcIdx); + strcpy(pFunc->functionName, funcName); + taosMemoryFree(funcName); + fmGetFuncInfo(pFunc, NULL, 0); + } else { + int32_t funcIdx = taosRand(); + if (QPT_RAND_BOOL_V) { + strcpy(pFunc->functionName, "invalidFuncName"); + } else { + pFunc->functionName[0] = 0; + } + fmGetFuncInfo(pFunc, NULL, 0); + } + + qptCtx.makeCtx.nodeLevel++; + + if (QPT_CORRECT_HIGH_PROB()) { + // TODO + } else { + int32_t paramNum = taosRand() % QPT_MAX_FUNC_PARAM; + for (int32_t i = 0; i < paramNum; ++i) { + SNode* pNode = NULL; + qptMakeExprNode(&pNode); + qptNodesListMakeStrictAppend(&pFunc->pParameterList, pNode); + } + } + + *ppNode = (SNode*)pFunc; + + return *ppNode; +} + + + + +SNode* qptMakeLogicCondNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SLogicConditionNode* pLogic = NULL; + nodesMakeNode(QUERY_NODE_LOGIC_CONDITION, (SNode**)&pLogic); + + if (QPT_CORRECT_HIGH_PROB()) { + pLogic->condType = (taosRand() % 3) ? ((taosRand() % 2) ? LOGIC_COND_TYPE_AND : LOGIC_COND_TYPE_OR) : LOGIC_COND_TYPE_NOT; + } else { + pLogic->condType = (ELogicConditionType)taosRand(); + } + + qptCtx.makeCtx.nodeLevel++; + + int32_t paramNum = QPT_CORRECT_HIGH_PROB() ? (taosRand() % QPT_MAX_LOGIC_PARAM + 1) : (taosRand() % QPT_MAX_LOGIC_PARAM); + for (int32_t i = 0; i < paramNum; ++i) { + SNode* pNode = NULL; + qptMakeExprNode(&pNode); + qptNodesListMakeStrictAppend(&pLogic->pParameterList, pNode); + } + + *ppNode = (SNode*)pLogic; + + return *ppNode; +} + +SNode* qptMakeNodeListNode(QPT_NODE_TYPE nodeType, SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SNode* pTmp = NULL; + if (NULL == ppNode) { + ppNode = &pTmp; + } + + SNodeListNode* pList = NULL; + nodesMakeNode(QUERY_NODE_NODE_LIST, (SNode**)&pList); + + qptCtx.makeCtx.nodeLevel++; + + qptMakeNodeList(nodeType, &pList->pNodeList); + + *ppNode = (SNode*)pList; + + return *ppNode; +} + +SNode* qptMakeTempTableNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + STempTableNode* pTemp = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_TEMP_TABLE, (SNode**)&pTemp)); + + if (QPT_CORRECT_HIGH_PROB()) { + // TODO + } + + *ppNode = (SNode*)pTemp; + + return *ppNode; +} + +SNode* qptMakeJoinTableNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SJoinTableNode* pJoin = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_JOIN_TABLE, (SNode**)&pJoin)); + + if (QPT_CORRECT_HIGH_PROB()) { + // TODO + } + + *ppNode = (SNode*)pJoin; + + return *ppNode; +} + +SNode* qptMakeRealTableNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SRealTableNode* pReal = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_REAL_TABLE, (SNode**)&pReal)); + + if (QPT_CORRECT_HIGH_PROB()) { + // TODO + } + + *ppNode = (SNode*)pReal; + + return *ppNode; +} + + + +SNode* qptMakeNonRealTableNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + if (QPT_CORRECT_HIGH_PROB()) { + if (QPT_RAND_BOOL_V) { + qptMakeTempTableNode(ppNode); + } else { + qptMakeJoinTableNode(ppNode); + } + } else { + qptMakeRealTableNode(ppNode); + } + + return *ppNode; +} + +SNode* qptMakeExprNode(SNode** ppNode) { + SNode* pNode = NULL; + if (NULL == ppNode) { + ppNode = &pNode; + } + + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + int32_t nodeTypeMaxValue = 9; + if (qptCtx.makeCtx.nodeLevel >= QPT_MAX_NODE_LEVEL) { + nodeTypeMaxValue = 2; + } + + switch (taosRand() % nodeTypeMaxValue) { + case 0: + qptMakeColumnNode(ppNode); + break; + case 1: + qptMakeValueNode(-1, ppNode); + break; + case 2: + qptMakeFunctionNode(ppNode); + break; + case 3: + qptMakeLogicCondNode(ppNode); + break; + case 4: + qptMakeNodeListNode(QPT_NODE_EXPR, ppNode); + break; + case 5: + qptMakeOperatorNode(ppNode); + break; + case 6: + qptMakeNonRealTableNode(ppNode); + break; + case 7: + qptMakeCaseWhenNode(ppNode); + break; + case 8: + qptMakeWhenThenNode(ppNode); + break; + default: + assert(0); + break; + } + + return *ppNode; +} + + +SNode* qptMakeLimitNode(SNode** ppNode) { + SNode* pNode = NULL; + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(&pNode); + } + + assert(0 == nodesMakeNode(QUERY_NODE_LIMIT, &pNode)); + assert(pNode); + + SLimitNode* pLimit = (SLimitNode*)pNode; + + if (!qptCtx.param.correctExpected) { + if (taosRand() % 2) { + pLimit->limit = taosRand() * ((taosRand() % 2) ? 1 : -1); + } + if (taosRand() % 2) { + pLimit->offset = taosRand() * ((taosRand() % 2) ? 1 : -1); + } + } else { + pLimit->limit = taosRand(); + if (taosRand() % 2) { + pLimit->offset = taosRand(); + } + } + + *ppNode = pNode; + + return pNode; +} + + +SNode* qptMakeWindowOffsetNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SNode* pNode = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_WINDOW_OFFSET, &pNode)); + assert(pNode); + + SWindowOffsetNode* pWinOffset = (SWindowOffsetNode*)pNode; + qptMakeValueNode(TSDB_DATA_TYPE_BIGINT, &pWinOffset->pStartOffset); + qptMakeValueNode(TSDB_DATA_TYPE_BIGINT, &pWinOffset->pEndOffset); + + *ppNode = pNode; + + return pNode; +} + +void qptSaveMakeNodeCtx() { + qptCtx.makeCtxBak.nodeLevel = qptCtx.makeCtx.nodeLevel; +} + +void qptRestoreMakeNodeCtx() { + qptCtx.makeCtx.nodeLevel = qptCtx.makeCtxBak.nodeLevel; +} + + +void qptResetTableCols() { + SNode* pTmp = NULL; + FOREACH(pTmp, qptCtx.param.tbl.pColList) { + ((SQPTCol*)pTmp)->inUse = 0; + } + FOREACH(pTmp, qptCtx.param.tbl.pTagList) { + ((SQPTCol*)pTmp)->inUse = 0; + } +} + +void qptResetMakeNodeCtx() { + SQPTMakeNodeCtx* pCtx = &qptCtx.makeCtx; + pCtx->nodeLevel = 1; + + if (pCtx->fromTable) { + qptResetTableCols(); + } +} + +void qptInitMakeNodeCtx(bool fromTable, bool onlyTag, bool onlyCol, int16_t inputBlockId, SNodeList* pInputList) { + SQPTMakeNodeCtx* pCtx = &qptCtx.makeCtx; + + pCtx->onlyTag = onlyTag; + pCtx->fromTable = fromTable; + pCtx->onlyCol = onlyCol; + + if (NULL == pInputList) { + if (fromTable) { + inputBlockId = (qptCtx.buildCtx.pCurr && qptCtx.buildCtx.pCurr->pOutputDataBlockDesc) ? qptCtx.buildCtx.pCurr->pOutputDataBlockDesc->dataBlockId : taosRand(); + pInputList = onlyTag ? qptCtx.param.tbl.pTagList : (onlyCol ? qptCtx.param.tbl.pColList : qptCtx.param.tbl.pColTagList); + } else if (qptCtx.buildCtx.pChild && qptCtx.buildCtx.pChild->pOutputDataBlockDesc) { + inputBlockId = qptCtx.buildCtx.pChild->pOutputDataBlockDesc->dataBlockId; + pInputList = qptCtx.buildCtx.pChild->pOutputDataBlockDesc->pSlots; + } + } + + pCtx->inputBlockId = inputBlockId; + pCtx->pInputList = pInputList; + + qptResetMakeNodeCtx(); +} + +SNode* qptMakeConditionNode() { + SNode* pNode = NULL; + qptMakeExprNode(&pNode); + + return pNode; +} + + +SNode* qptMakeSlotDescNode(const char* pName, const SNode* pNode, int16_t slotId, bool output, bool reserve) { + SSlotDescNode* pSlot = NULL; + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode((SNode**)&pSlot); + } + + assert(0 == nodesMakeNode(QUERY_NODE_SLOT_DESC, (SNode**)&pSlot)); + + QPT_RAND_BOOL_V ? (pSlot->name[0] = 0) : snprintf(pSlot->name, sizeof(pSlot->name), "%s", pName); + pSlot->slotId = QPT_CORRECT_HIGH_PROB() ? slotId : taosRand(); + if (QPT_CORRECT_HIGH_PROB()) { + pSlot->dataType = ((SExprNode*)pNode)->resType; + } else { + qptGetRandValue(&pSlot->dataType.type, &pSlot->dataType.bytes, NULL); + } + + pSlot->reserve = reserve; + pSlot->output = output; + + return (SNode*)pSlot; +} + + +SNode* qptMakeDataBlockDescNode(bool forSink) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(NULL); + } + + SDataBlockDescNode* pDesc = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_DATABLOCK_DESC, (SNode**)&pDesc)); + + pDesc->dataBlockId = QPT_CORRECT_HIGH_PROB() ? (forSink ? (qptCtx.buildCtx.nextBlockId - 1) : qptCtx.buildCtx.nextBlockId++) : QPT_RAND_INT_V; + pDesc->precision = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.db.precision : QPT_RAND_INT_V; + + return (SNode*)pDesc; +} + +SNode* qptMakeDataBlockDescNodeFromNode(bool forSink) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(NULL); + } + + SDataBlockDescNode* pDesc = NULL; + SDataBlockDescNode* pInput = qptCtx.buildCtx.pCurr ? qptCtx.buildCtx.pCurr->pOutputDataBlockDesc : NULL; + SNode* pTmp = NULL, *pTmp2 = NULL; + + if (QPT_VALID_DESC(pInput)) { + if (QPT_CORRECT_HIGH_PROB()) { + nodesCloneNode((SNode*)pInput, (SNode**)&pDesc); + } else { + assert(0 == nodesMakeNode(QUERY_NODE_DATABLOCK_DESC, (SNode**)&pDesc)); + + pDesc->dataBlockId = QPT_CORRECT_HIGH_PROB() ? pInput->dataBlockId : QPT_RAND_INT_V; + pDesc->precision = QPT_CORRECT_HIGH_PROB() ? pInput->precision : QPT_RAND_INT_V; + pDesc->totalRowSize = QPT_CORRECT_HIGH_PROB() ? pInput->totalRowSize : QPT_RAND_INT_V; + pDesc->outputRowSize = QPT_CORRECT_HIGH_PROB() ? pInput->outputRowSize : QPT_RAND_INT_V; + + FOREACH(pTmp, pInput->pSlots) { + if (QPT_RAND_BOOL_V) { + nodesCloneNode(pTmp, &pTmp2); + qptNodesListMakeStrictAppend(&pDesc->pSlots, pTmp2); + } + } + } + } else { + assert(0 == nodesMakeNode(QUERY_NODE_DATABLOCK_DESC, (SNode**)&pDesc)); + + pDesc->dataBlockId = QPT_CORRECT_HIGH_PROB() ? (forSink ? (qptCtx.buildCtx.nextBlockId - 1) : qptCtx.buildCtx.nextBlockId++) : QPT_RAND_INT_V; + pDesc->precision = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.db.precision : QPT_RAND_INT_V; + pDesc->totalRowSize = QPT_RAND_INT_V; + pDesc->outputRowSize = QPT_RAND_INT_V; + + int32_t slotNum = taosRand() % QPT_MAX_COLUMN_NUM; + for (int32_t i = 0; i < slotNum; ++i) { + pTmp2 = qptMakeExprNode(NULL); + if (QPT_CORRECT_HIGH_PROB()) { + pTmp = qptMakeSlotDescNode(NULL, pTmp2, i, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V); + nodesDestroyNode(pTmp2); + } else { + pTmp = pTmp2; + } + + qptNodesListMakeStrictAppend(&pDesc->pSlots, pTmp); + } + } + + return (SNode*)pDesc; +} + + + +SNode* qptMakeTargetNode(SNode* pNode, int16_t dataBlockId, int16_t slotId, SNode** pOutput) { + if (QPT_NCORRECT_LOW_PROB()) { + nodesDestroyNode(pNode); + return qptMakeRandNode(pOutput); + } + + STargetNode* pTarget = NULL; + assert(0 == nodesMakeNode(QUERY_NODE_TARGET, (SNode**)&pTarget)); + + pTarget->dataBlockId = QPT_CORRECT_HIGH_PROB() ? dataBlockId : taosRand(); + pTarget->slotId = QPT_CORRECT_HIGH_PROB() ? slotId : taosRand(); + pTarget->pExpr = QPT_CORRECT_HIGH_PROB() ? pNode : qptMakeRandNode(NULL); + if (pTarget->pExpr != pNode) { + nodesDestroyNode(pNode); + } + + *pOutput = (SNode*)pTarget; + + return *pOutput; +} + +SNode* qptMakeDownstreamSrcNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SDownstreamSourceNode* pDs = NULL; + nodesMakeNode(QUERY_NODE_DOWNSTREAM_SOURCE, (SNode**)&pDs); + + pDs->addr.nodeId = qptCtx.param.vnode.vgId; + memcpy(&pDs->addr.epSet, &qptCtx.param.vnode.epSet, sizeof(pDs->addr.epSet)); + pDs->taskId = (QPT_CORRECT_HIGH_PROB() && qptCtx.buildCtx.pCurrTask) ? qptCtx.buildCtx.pCurrTask->id.taskId : taosRand(); + pDs->schedId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.schedulerId : taosRand(); + pDs->execId = taosRand(); + pDs->fetchMsgType = QPT_CORRECT_HIGH_PROB() ? (QPT_RAND_BOOL_V ? TDMT_SCH_FETCH : TDMT_SCH_MERGE_FETCH) : taosRand(); + pDs->localExec = QPT_RAND_BOOL_V; + + *ppNode = (SNode*)pDs; + + return *ppNode; +} + +SNode* qptMakeOrderByExprNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + SOrderByExprNode* pOrder = NULL; + nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR, (SNode**)&pOrder); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pOrder->pExpr); + + pOrder->order = (EOrder)(QPT_CORRECT_HIGH_PROB() ? (QPT_RAND_BOOL_V ? ORDER_ASC : ORDER_DESC) : taosRand()); + pOrder->nullOrder = qptGetRandNullOrder(); + + *ppNode = (SNode*)pOrder; + + return *ppNode; +} + +SNode* qptMakeSubplanNode(SNode** ppNode) { + if (QPT_NCORRECT_LOW_PROB()) { + return qptMakeRandNode(ppNode); + } + + *ppNode = (SNode*)qptCreateSubplanNode(QUERY_NODE_PHYSICAL_SUBPLAN); + + return *ppNode; +} + + + + +SPhysiNode* qptCreatePhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = NULL; + assert(0 == nodesMakeNode((ENodeType)nodeType, (SNode**)&pPhysiNode)); + assert(pPhysiNode); + + qptCtx.buildCtx.pCurr = pPhysiNode; + + qptMakeLimitNode(&pPhysiNode->pLimit); + qptMakeLimitNode(&pPhysiNode->pSlimit); + pPhysiNode->dynamicOp = qptGetDynamicOp(); + pPhysiNode->inputTsOrder = qptGetCurrTsOrder(); + + pPhysiNode->pOutputDataBlockDesc = (SDataBlockDescNode*)qptMakeDataBlockDescNode(false); + + return pPhysiNode; +} + +void qptPostCreatePhysiNode(SPhysiNode* pPhysiNode) { + pPhysiNode->outputTsOrder = qptGetCurrTsOrder(); + + if (QPT_RAND_BOOL_V) { + qptInitMakeNodeCtx((QPT_CORRECT_HIGH_PROB() && qptCtx.buildCtx.pChild) ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + pPhysiNode->pConditions = qptMakeConditionNode(); + } + +} + +void qptMarkTableInUseCols(int32_t colNum, int32_t totalColNum) { + if (colNum >= totalColNum) { + for (int32_t i = 0; i < totalColNum; ++i) { + SQPTCol* pNode = (SQPTCol*)nodesListGetNode(qptCtx.makeCtx.pInputList, i); + assert(pNode->type == QPT_QUERY_NODE_COL); + pNode->inUse = 1; + } + return; + } + + int32_t colInUse = 0; + do { + int32_t colIdx = taosRand() % totalColNum; + SQPTCol* pNode = (SQPTCol*)nodesListGetNode(qptCtx.makeCtx.pInputList, colIdx); + assert(pNode->type == QPT_QUERY_NODE_COL); + + if (pNode->inUse) { + continue; + } + + pNode->inUse = 1; + colInUse++; + } while (colInUse < colNum); +} + + +void qptMakeTableScanColList( SNodeList** ppCols) { + if (QPT_NCORRECT_LOW_PROB()) { + if (QPT_RAND_BOOL_V) { + nodesMakeList(ppCols); + } else { + *ppCols = NULL; + } + + return; + } + + int32_t colNum = (QPT_CORRECT_HIGH_PROB() && qptCtx.makeCtx.pInputList) ? (taosRand() % qptCtx.makeCtx.pInputList->length + 1) : (taosRand() % QPT_MAX_COLUMN_NUM); + int32_t colAdded = 0; + + if (qptCtx.makeCtx.pInputList) { + if (QPT_CORRECT_HIGH_PROB()) { + qptMarkTableInUseCols(colNum, qptCtx.makeCtx.pInputList->length); + + for (int32_t i = 0; colAdded < colNum; ++i) { + int32_t idx = (i < qptCtx.makeCtx.pInputList->length) ? i : (taosRand() % qptCtx.makeCtx.pInputList->length); + SQPTCol* pNode = (SQPTCol*)nodesListGetNode(qptCtx.makeCtx.pInputList, idx); + assert(pNode->type == QPT_QUERY_NODE_COL); + + if (0 == pNode->inUse) { + continue; + } + + assert(0 == qptNodesListMakeStrictAppend(ppCols, qptMakeColumnFromTable(idx))); + colAdded++; + } + + return; + } + + for (int32_t i = 0; i < colNum; ++i) { + int32_t colIdx = taosRand(); + colIdx = (colIdx >= qptCtx.makeCtx.pInputList->length) ? -1 : colIdx; + + assert(0 == qptNodesListMakeStrictAppend(ppCols, qptMakeColumnFromTable(colIdx))); + } + } else { + for (int32_t i = 0; i < colNum; ++i) { + int32_t colIdx = taosRand(); + assert(0 == qptNodesListMakeStrictAppend(ppCols, qptMakeColumnFromTable(colIdx))); + } + } +} + + +void qptCreateTableScanCols( int16_t blockId, SNodeList** ppList) { + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? false : true, QPT_CORRECT_HIGH_PROB() ? true : false, 0, NULL); + qptMakeTableScanColList(ppList); +} + +void qptCreateTableScanPseudoCols( int16_t blockId, SNodeList** ppList) { + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? false : true, 0, NULL); + qptMakeTableScanColList(ppList); +} + + +void qptAddDataBlockSlots(SNodeList* pList, SDataBlockDescNode* pDataBlockDesc) { + if (NULL == pDataBlockDesc || QUERY_NODE_DATABLOCK_DESC != nodeType(pDataBlockDesc)) { + return; + } + + int16_t nextSlotId = LIST_LENGTH(pDataBlockDesc->pSlots), slotId = 0; + SNode* pNode = NULL; + bool output = QPT_RAND_BOOL_V; + + FOREACH(pNode, pList) { + if (NULL == pNode) { + continue; + } + + SNode* pExpr = QUERY_NODE_ORDER_BY_EXPR == nodeType(pNode) ? ((SOrderByExprNode*)pNode)->pExpr : pNode; + if (QPT_CORRECT_HIGH_PROB()) { + SNode* pDesc = QPT_CORRECT_HIGH_PROB() ? qptMakeSlotDescNode(NULL, pExpr, nextSlotId, output, QPT_RAND_BOOL_V) : qptMakeExprNode(NULL); + assert(0 == qptNodesListMakeStrictAppend(&pDataBlockDesc->pSlots, pDesc)); + pDataBlockDesc->totalRowSize += QPT_CORRECT_HIGH_PROB() ? ((SExprNode*)pExpr)->resType.bytes : taosRand(); + if (output && QPT_RAND_BOOL_V) { + pDataBlockDesc->outputRowSize += QPT_CORRECT_HIGH_PROB() ? ((SExprNode*)pExpr)->resType.bytes : taosRand(); + } + } + + slotId = nextSlotId; + ++nextSlotId; + + if (QPT_CORRECT_HIGH_PROB()) { + SNode* pTarget = NULL; + qptMakeTargetNode(pNode, pDataBlockDesc->dataBlockId, slotId, &pTarget); + REPLACE_NODE(pTarget); + } + } +} + +SNode* qptMakeSpecTypeNode(QPT_NODE_TYPE nodeType, SNode** ppNode) { + switch (nodeType) { + case QPT_NODE_COLUMN: + return qptMakeColumnNode(ppNode); + case QPT_NODE_FUNCTION: + return qptMakeFunctionNode(ppNode); + case QPT_NODE_EXPR: + return qptMakeExprNode(ppNode); + case QPT_NODE_VALUE: + return qptMakeValueNode(-1, ppNode); + default: + break; + } + + return qptMakeRandNode(ppNode); +} + + +void qptMakeRandNodeList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t exprNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < exprNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeSpecTypeNode((QPT_NODE_TYPE)(taosRand() % (QPT_NODE_MAX_VALUE + 1)), &pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + + +void qptMakeExprList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t exprNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < exprNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeExprNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + +void qptMakeValueList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t colNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < colNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeValueNode(-1, &pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + +void qptMakeColumnList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t colNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < colNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeColumnNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + +void qptMakeTargetList(QPT_NODE_TYPE nodeType, int16_t datablockId, SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t tarNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < tarNum; ++i) { + SNode* pNode = NULL, *pExpr = NULL; + qptRestoreMakeNodeCtx(); + qptMakeSpecTypeNode(nodeType, &pExpr); + qptMakeTargetNode(pExpr, datablockId, i, &pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + +void qptMakeFunctionList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t funcNum = taosRand() % QPT_MAX_COLUMN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < funcNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeFunctionNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + + +void qptMakeDownstreamSrcList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t dsNum = taosRand() % QPT_MAX_DS_SRC_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < dsNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeDownstreamSrcNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + + +void qptMakeOrerByExprList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t orderNum = taosRand() % QPT_MAX_ORDER_BY_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < orderNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeOrderByExprNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + + +void qptMakeSubplanList(SNodeList** ppList) { + qptSaveMakeNodeCtx(); + + int32_t planNum = taosRand() % QPT_MAX_LEVEL_SUBPLAN_NUM + (QPT_CORRECT_HIGH_PROB() ? 1 : 0); + for (int32_t i = 0; i < planNum; ++i) { + SNode* pNode = NULL; + qptRestoreMakeNodeCtx(); + qptMakeSubplanNode(&pNode); + qptNodesListMakeStrictAppend(ppList, pNode); + } +} + +void qptMakeSpecTypeNodeList(QPT_NODE_TYPE nodeType, SNodeList** ppList) { + switch (nodeType) { + case QPT_NODE_COLUMN: + return qptMakeColumnList(ppList); + case QPT_NODE_FUNCTION: + return qptMakeFunctionList(ppList); + case QPT_NODE_EXPR: + return qptMakeExprList(ppList); + case QPT_NODE_VALUE: + return qptMakeValueList(ppList); + case QPT_NODE_SUBPLAN: + return qptMakeSubplanList(ppList); + default: + break; + } + + return qptMakeRandNodeList(ppList); +} + + +void qptMakeNodeList(QPT_NODE_TYPE nodeType, SNodeList** ppList) { + qptMakeSpecTypeNodeList(nodeType, ppList); +} + + + +void qptMakeAppendToTargetList(SNodeList* pInputList, int16_t blockId, SNodeList** ppOutList) { + SNode* pNode = NULL; + FOREACH(pNode, pInputList) { + if (QPT_CORRECT_HIGH_PROB()) { + SNode* pTarget = NULL; + int16_t slotId = ((*ppOutList) && (*ppOutList)->length) ? (*ppOutList)->length : 0; + qptMakeTargetNode(pNode, blockId, slotId, &pTarget); + qptNodesListMakeStrictAppend(ppOutList, pTarget); + } + } +} + +void qptCreateScanPhysiNodeImpl( SScanPhysiNode* pScan) { + SDataBlockDescNode* pDesc = pScan->node.pOutputDataBlockDesc; + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && QPT_VALID_DESC(pDesc)) ? pDesc->dataBlockId : taosRand(); + qptCreateTableScanCols(blockId, &pScan->pScanCols); + + qptAddDataBlockSlots(pScan->pScanCols, pDesc); + + if (taosRand() % 2) { + blockId = (QPT_CORRECT_HIGH_PROB() && QPT_VALID_DESC(pDesc)) ? pDesc->dataBlockId : taosRand(); + qptCreateTableScanPseudoCols(blockId, &pScan->pScanPseudoCols); + } + + qptAddDataBlockSlots(pScan->pScanPseudoCols, pDesc); + + pScan->uid = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.uid : taosRand(); + pScan->suid = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.suid : taosRand(); + pScan->tableType = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.tblType : taosRand(); + pScan->groupOrderScan = (taosRand() % 2) ? true : false; + + SName tblName = {0}; + toName(1, qptCtx.param.db.dbName, qptCtx.param.tbl.tblName, &tblName); + if (QPT_CORRECT_HIGH_PROB()) { + memcpy(&pScan->tableName, &tblName, sizeof(SName)); + } else { + pScan->tableName.acctId = 0; + pScan->tableName.dbname[0] = 0; + pScan->tableName.tname[0] = 0; + } + + qptCtx.buildCtx.currTsOrder = QPT_CORRECT_HIGH_PROB() ? qptCtx.buildCtx.currTsOrder : QPT_RAND_ORDER_V; +} + + + +SNode* qptCreateTagScanPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + STagScanPhysiNode* pTagScanNode = (STagScanPhysiNode*)pPhysiNode; + pTagScanNode->onlyMetaCtbIdx = (taosRand() % 2) ? true : false; + + qptCreateScanPhysiNodeImpl(&pTagScanNode->scan); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateTableScanPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + STableScanPhysiNode* pTableScanNode = (STableScanPhysiNode*)pPhysiNode; + pTableScanNode->scanSeq[0] = taosRand() % 4; + pTableScanNode->scanSeq[1] = taosRand() % 4; + pTableScanNode->scanRange.skey = taosRand(); + pTableScanNode->scanRange.ekey = taosRand(); + pTableScanNode->ratio = taosRand(); + pTableScanNode->dataRequired = taosRand(); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeFunctionList(&pTableScanNode->pDynamicScanFuncs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? false : true, 0, NULL); + qptMakeColumnList(&pTableScanNode->pGroupTags); + + pTableScanNode->groupSort = QPT_RAND_BOOL_V; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? false : true, 0, NULL); + qptMakeExprList(&pTableScanNode->pTags); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pTableScanNode->pSubtable); + pTableScanNode->interval = taosRand(); + pTableScanNode->offset = taosRand(); + pTableScanNode->sliding = taosRand(); + pTableScanNode->intervalUnit = taosRand(); + pTableScanNode->slidingUnit = taosRand(); + pTableScanNode->triggerType = taosRand(); + pTableScanNode->watermark = taosRand(); + pTableScanNode->igExpired = taosRand(); + pTableScanNode->assignBlockUid = QPT_RAND_BOOL_V; + pTableScanNode->igCheckUpdate = taosRand(); + pTableScanNode->filesetDelimited = QPT_RAND_BOOL_V; + pTableScanNode->needCountEmptyTable = QPT_RAND_BOOL_V; + pTableScanNode->paraTablesSort = QPT_RAND_BOOL_V; + pTableScanNode->smallDataTsSort = QPT_RAND_BOOL_V; + + qptCreateScanPhysiNodeImpl(&pTableScanNode->scan); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateTableSeqScanPhysiNode(int32_t nodeType) { + return qptCreateTableScanPhysiNode(nodeType); +} + +SNode* qptCreateTableMergeScanPhysiNode(int32_t nodeType) { + return qptCreateTableScanPhysiNode(nodeType); +} + +SNode* qptCreateStreamScanPhysiNode(int32_t nodeType) { + return qptCreateTableScanPhysiNode(nodeType); +} + +SNode* qptCreateSysTableScanPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SSystemTableScanPhysiNode* pSysScanNode = (SSystemTableScanPhysiNode*)pPhysiNode; + + memcpy(&pSysScanNode->mgmtEpSet, &qptCtx.param.vnode.epSet, sizeof(pSysScanNode->mgmtEpSet)); + pSysScanNode->showRewrite = QPT_RAND_BOOL_V; + pSysScanNode->accountId = QPT_CORRECT_HIGH_PROB() ? 1 : taosRand(); + pSysScanNode->sysInfo = QPT_RAND_BOOL_V; + + qptCreateScanPhysiNodeImpl(&pSysScanNode->scan); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateBlockDistScanPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SBlockDistScanPhysiNode* pBlkScanNode = (SBlockDistScanPhysiNode*)pPhysiNode; + + qptCreateScanPhysiNodeImpl((SScanPhysiNode*)pBlkScanNode); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateLastRowScanPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SLastRowScanPhysiNode* pLRScanNode = (SLastRowScanPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_CORRECT_HIGH_PROB() ? false : true, 0, NULL); + qptMakeColumnList(&pLRScanNode->pGroupTags); + + pLRScanNode->groupSort = QPT_RAND_BOOL_V; + pLRScanNode->ignoreNull = QPT_RAND_BOOL_V; + + if (QPT_CORRECT_HIGH_PROB()) { + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeAppendToTargetList(pLRScanNode->scan.pScanCols, blockId, &pLRScanNode->pTargets); + } + + if (QPT_CORRECT_HIGH_PROB()) { + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeAppendToTargetList(pLRScanNode->scan.pScanPseudoCols, blockId, &pLRScanNode->pTargets); + } + + if (QPT_RAND_BOOL_V) { + int32_t funcNum = taosRand() % QPT_MAX_COLUMN_NUM; + pLRScanNode->pFuncTypes = taosArrayInit(funcNum, sizeof(int32_t)); + assert(pLRScanNode->pFuncTypes); + for (int32_t i = 0; i < funcNum; ++i) { + int32_t funcType = taosRand(); + taosArrayPush(pLRScanNode->pFuncTypes, &funcType); + } + } + + qptCreateScanPhysiNodeImpl(&pLRScanNode->scan); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateTableCountScanPhysiNode(int32_t nodeType) { + return qptCreateLastRowScanPhysiNode(nodeType); +} + + +SNode* qptCreateProjectPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SProjectPhysiNode* pProject = (SProjectPhysiNode*)pPhysiNode; + + pProject->mergeDataBlock = QPT_RAND_BOOL_V; + pProject->ignoreGroupId = QPT_RAND_BOOL_V; + pProject->inputIgnoreGroup = QPT_RAND_BOOL_V; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pProject->pProjections); + + qptAddDataBlockSlots(pProject->pProjections, pProject->node.pOutputDataBlockDesc); + + qptPostCreatePhysiNode(pPhysiNode); + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateMergeJoinPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SSortMergeJoinPhysiNode* pJoin = (SSortMergeJoinPhysiNode*)pPhysiNode; + + pJoin->joinType = (EJoinType)(taosRand() % JOIN_TYPE_MAX_VALUE + (QPT_CORRECT_HIGH_PROB() ? 0 : 1)); + pJoin->subType = (EJoinSubType)(taosRand() % JOIN_STYPE_MAX_VALUE + (QPT_CORRECT_HIGH_PROB() ? 0 : 1)); + qptMakeWindowOffsetNode(&pJoin->pWindowOffset); + qptMakeLimitNode(&pJoin->pJLimit); + pJoin->asofOpType = OPERATOR_ARRAY[taosRand() % (sizeof(OPERATOR_ARRAY)/sizeof(OPERATOR_ARRAY[0]))] + (QPT_CORRECT_HIGH_PROB() ? 0 : 1); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->leftPrimExpr); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->rightPrimExpr); + + pJoin->leftPrimSlotId = qptGetInputSlotId(qptCtx.buildCtx.pChild ? qptCtx.buildCtx.pChild->pOutputDataBlockDesc : NULL); + pJoin->rightPrimSlotId = qptGetInputSlotId(qptCtx.buildCtx.pChild ? qptCtx.buildCtx.pChild->pOutputDataBlockDesc : NULL); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pJoin->pEqLeft); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pJoin->pEqRight); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pPrimKeyCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pColEqCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pColOnCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pFullOnCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pJoin->pTargets); + + for (int32_t i = 0; i < 2; i++) { + pJoin->inputStat[i].inputRowNum = taosRand(); + pJoin->inputStat[i].inputRowSize = taosRand(); + } + + pJoin->seqWinGroup = QPT_RAND_BOOL_V; + pJoin->grpJoin = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateHashAggPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SAggPhysiNode* pAgg = (SAggPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pAgg->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pAgg->pGroupKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_FUNCTION, blockId, &pAgg->pAggFuncs); + + pAgg->mergeDataBlock = QPT_RAND_BOOL_V; + pAgg->groupKeyOptimized = QPT_RAND_BOOL_V; + pAgg->hasCountLikeFunc = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateExchangePhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SExchangePhysiNode* pExc = (SExchangePhysiNode*)pPhysiNode; + + pExc->srcStartGroupId = taosRand(); + pExc->srcEndGroupId = taosRand(); + pExc->singleChannel = QPT_RAND_BOOL_V; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeDownstreamSrcList(&pExc->pSrcEndPoints); + + pExc->seqRecvData = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateMergePhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SMergePhysiNode* pMerge = (SMergePhysiNode*)pPhysiNode; + + pMerge->type = (EMergeType)(QPT_CORRECT_HIGH_PROB() ? (taosRand() % (MERGE_TYPE_MAX_VALUE - 1) + 1) : taosRand()); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeOrerByExprList(&pMerge->pMergeKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pMerge->pTargets); + + pMerge->numOfChannels = taosRand(); + pMerge->numOfSubplans = taosRand(); + pMerge->srcGroupId = taosRand(); + pMerge->srcEndGroupId = taosRand(); + pMerge->groupSort = QPT_RAND_BOOL_V; + pMerge->ignoreGroupId = QPT_RAND_BOOL_V; + pMerge->inputWithGroupId = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateSortPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SSortPhysiNode* pSort = (SSortPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pSort->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeOrerByExprList(&pSort->pSortKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pSort->pTargets); + + pSort->calcGroupId = QPT_RAND_BOOL_V; + pSort->excludePkCol = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateGroupSortPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SGroupSortPhysiNode* pSort = (SGroupSortPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pSort->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeOrerByExprList(&pSort->pSortKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pSort->pTargets); + + pSort->calcGroupId = QPT_RAND_BOOL_V; + pSort->excludePkCol = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +void qptCreateWindowPhysiNode(SWindowPhysiNode* pWindow) { + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pWindow->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeFunctionList(&pWindow->pFuncs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnNode(&pWindow->pTspk); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnNode(&pWindow->pTsEnd); + + pWindow->triggerType = taosRand(); + pWindow->watermark = taosRand(); + pWindow->deleteMark = taosRand(); + pWindow->igExpired = taosRand(); + pWindow->destHasPrimayKey = taosRand(); + pWindow->mergeDataBlock = QPT_RAND_BOOL_V; +} + +SNode* qptCreateIntervalPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SIntervalPhysiNode* pInterval = (SIntervalPhysiNode*)pPhysiNode; + + qptCreateWindowPhysiNode(&pInterval->window); + + pInterval->interval = taosRand(); + pInterval->offset = taosRand(); + pInterval->sliding = taosRand(); + pInterval->intervalUnit = qptGetRandTimestampUnit(); + pInterval->slidingUnit = qptGetRandTimestampUnit(); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateMergeIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + +SNode* qptCreateMergeAlignedIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + +SNode* qptCreateStreamIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + +SNode* qptCreateStreamFinalIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + +SNode* qptCreateStreamSemiIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + + +SNode* qptCreateStreamMidIntervalPhysiNode(int32_t nodeType) { + return qptCreateIntervalPhysiNode(nodeType); +} + + +SNode* qptCreateFillPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SFillPhysiNode* pFill = (SFillPhysiNode*)pPhysiNode; + + pFill->mode = qptGetRandFillMode(); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pFill->pFillExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pFill->pNotFillExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnNode(&pFill->pWStartTs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeNodeListNode(QPT_NODE_VALUE, &pFill->pValues); + + qptGetRandTimeWindow(&pFill->timeRange); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamFillPhysiNode(int32_t nodeType) { + return qptCreateFillPhysiNode(nodeType); +} + + +SNode* qptCreateSessionPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SSessionWinodwPhysiNode* pSession = (SSessionWinodwPhysiNode*)pPhysiNode; + + qptCreateWindowPhysiNode(&pSession->window); + + pSession->gap = taosRand(); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamSessionPhysiNode(int32_t nodeType) { + return qptCreateSessionPhysiNode(nodeType); +} + +SNode* qptCreateStreamSemiSessionPhysiNode(int32_t nodeType) { + return qptCreateSessionPhysiNode(nodeType); +} + +SNode* qptCreateStreamFinalSessionPhysiNode(int32_t nodeType) { + return qptCreateSessionPhysiNode(nodeType); +} + +SNode* qptCreateStateWindowPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SStateWinodwPhysiNode* pState = (SStateWinodwPhysiNode*)pPhysiNode; + + qptCreateWindowPhysiNode(&pState->window); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnNode(&pState->pStateKey); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamStatePhysiNode(int32_t nodeType) { + return qptCreateStateWindowPhysiNode(nodeType); +} + +void qptCreatePartitionPhysiNodeImpl(SPartitionPhysiNode* pPartition) { + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprList(&pPartition->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, pPartition->node.pOutputDataBlockDesc ? pPartition->node.pOutputDataBlockDesc->dataBlockId : taosRand(), pPartition->pExprs); + qptMakeColumnList(&pPartition->pPartitionKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pPartition->pPartitionKeys); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPartition->node.pOutputDataBlockDesc) ? pPartition->node.pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pPartition->pTargets); + + pPartition->needBlockOutputTsOrder = QPT_RAND_BOOL_V; + pPartition->tsSlotId = qptGetInputPrimaryTsSlotId(); +} + +SNode* qptCreatePartitionPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SPartitionPhysiNode* pPartition = (SPartitionPhysiNode*)pPhysiNode; + + qptCreatePartitionPhysiNodeImpl(pPartition); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamPartitionPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SStreamPartitionPhysiNode* pPartition = (SStreamPartitionPhysiNode*)pPhysiNode; + + qptCreatePartitionPhysiNodeImpl(&pPartition->part); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pPartition->pTags); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pPartition->pSubtable); + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateIndefRowsFuncPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SIndefRowsFuncPhysiNode* pFunc = (SIndefRowsFuncPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pFunc->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_FUNCTION, blockId, &pFunc->pFuncs); + + return (SNode*)pPhysiNode; +} + + +SNode* qptCreateInterpFuncPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SInterpFuncPhysiNode* pFunc = (SInterpFuncPhysiNode*)pPhysiNode; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pFunc->pExprs); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_FUNCTION, blockId, &pFunc->pFuncs); + + qptGetRandTimeWindow(&pFunc->timeRange); + + pFunc->interval = taosRand(); + pFunc->intervalUnit = qptGetRandTimestampUnit(); + + pFunc->fillMode = qptGetRandFillMode(); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeNodeListNode(QPT_NODE_VALUE, &pFunc->pFillValues); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnNode(&pFunc->pTimeSeries); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateMergeEventPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SEventWinodwPhysiNode* pEvent = (SEventWinodwPhysiNode*)pPhysiNode; + + qptCreateWindowPhysiNode(&pEvent->window); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pEvent->pStartCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pEvent->pEndCond); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamEventPhysiNode(int32_t nodeType) { + return qptCreateMergeEventPhysiNode(nodeType); +} + +SNode* qptCreateCountWindowPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SCountWinodwPhysiNode* pCount = (SCountWinodwPhysiNode*)pPhysiNode; + + qptCreateWindowPhysiNode(&pCount->window); + + pCount->windowCount = taosRand(); + pCount->windowSliding = taosRand(); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateStreamCountWindowPhysiNode(int32_t nodeType) { + return qptCreateCountWindowPhysiNode(nodeType); +} + +SNode* qptCreateHashJoinPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SHashJoinPhysiNode* pJoin = (SHashJoinPhysiNode*)pPhysiNode; + + pJoin->joinType = (EJoinType)(taosRand() % JOIN_TYPE_MAX_VALUE + (QPT_CORRECT_HIGH_PROB() ? 0 : 1)); + pJoin->subType = (EJoinSubType)(taosRand() % JOIN_STYPE_MAX_VALUE + (QPT_CORRECT_HIGH_PROB() ? 0 : 1)); + qptMakeWindowOffsetNode(&pJoin->pWindowOffset); + qptMakeLimitNode(&pJoin->pJLimit); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pJoin->pOnLeft); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pJoin->pOnRight); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->leftPrimExpr); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->rightPrimExpr); + + pJoin->leftPrimSlotId = qptGetInputSlotId(qptCtx.buildCtx.pChild ? qptCtx.buildCtx.pChild->pOutputDataBlockDesc : NULL); + pJoin->rightPrimSlotId = qptGetInputSlotId(qptCtx.buildCtx.pChild ? qptCtx.buildCtx.pChild->pOutputDataBlockDesc : NULL); + + pJoin->timeRangeTarget = QPT_CORRECT_HIGH_PROB() ? (taosRand() % 3) : taosRand(); + qptGetRandTimeWindow(&pJoin->timeRange); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pLeftOnCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pRightOnCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pFullOnCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + int16_t blockId = (QPT_CORRECT_HIGH_PROB() && pPhysiNode->pOutputDataBlockDesc) ? pPhysiNode->pOutputDataBlockDesc->dataBlockId : taosRand(); + qptMakeTargetList(QPT_NODE_EXPR, blockId, &pJoin->pTargets); + + for (int32_t i = 0; i < 2; i++) { + pJoin->inputStat[i].inputRowNum = taosRand(); + pJoin->inputStat[i].inputRowSize = taosRand(); + } + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pPrimKeyCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pColEqCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pJoin->pTagEqCond); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateGroupCachePhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SGroupCachePhysiNode* pGroup = (SGroupCachePhysiNode*)pPhysiNode; + + pGroup->grpColsMayBeNull = QPT_RAND_BOOL_V; + pGroup->grpByUid = QPT_RAND_BOOL_V; + pGroup->globalGrp = QPT_RAND_BOOL_V; + pGroup->batchFetch = QPT_RAND_BOOL_V; + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pGroup->pGroupCols); + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateDynQueryCtrlPhysiNode(int32_t nodeType) { + SPhysiNode* pPhysiNode = qptCreatePhysiNode(nodeType); + + SDynQueryCtrlPhysiNode* pDyn = (SDynQueryCtrlPhysiNode*)pPhysiNode; + + pDyn->qType = QPT_CORRECT_HIGH_PROB() ? DYN_QTYPE_STB_HASH : (EDynQueryType)taosRand(); + + SStbJoinDynCtrlBasic* pJoin = &pDyn->stbJoin; + pJoin->batchFetch = QPT_RAND_BOOL_V; + pJoin->vgSlot[0] = taosRand(); + pJoin->vgSlot[1] = taosRand(); + pJoin->uidSlot[0] = taosRand(); + pJoin->uidSlot[1] = taosRand(); + pJoin->srcScan[0] = QPT_RAND_BOOL_V; + pJoin->srcScan[1] = QPT_RAND_BOOL_V; + + return (SNode*)pPhysiNode; +} + +SNode* qptCreateDataSinkNode(int32_t nodeType) { + SDataSinkNode* pSinkNode = NULL; + assert(0 == nodesMakeNode((ENodeType)nodeType, (SNode**)&pSinkNode)); + assert(pSinkNode); + + if (QPT_CORRECT_HIGH_PROB() && qptCtx.buildCtx.pCurr && qptCtx.buildCtx.pCurr->pOutputDataBlockDesc) { + pSinkNode->pInputDataBlockDesc = (SDataBlockDescNode*)qptMakeDataBlockDescNodeFromNode(true); + } else { + pSinkNode->pInputDataBlockDesc = (SDataBlockDescNode*)qptMakeDataBlockDescNode(true); + } + + return (SNode*)pSinkNode; +} + +SNode* qptCreateDataDispatchPhysiNode(int32_t nodeType) { + return (SNode*)qptCreateDataSinkNode(nodeType); +} + +SNode* qptCreateDataInsertPhysiNode(int32_t nodeType) { + SDataInserterNode* pInserter = (SDataInserterNode*)qptCreateDataSinkNode(nodeType); + + pInserter->numOfTables = taosRand(); + pInserter->size = taosRand(); + pInserter->pData = QPT_RAND_BOOL_V ? taosMemoryMalloc(1) : NULL; + + return (SNode*)pInserter; +} + +SNode* qptCreateDataQueryInsertPhysiNode(int32_t nodeType) { + SQueryInserterNode* pInserter = (SQueryInserterNode*)qptCreateDataSinkNode(nodeType); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptMakeColumnList(&pInserter->pCols); + + pInserter->tableId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.uid : taosRand(); + pInserter->stableId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.suid : taosRand(); + pInserter->tableType = QPT_CORRECT_HIGH_PROB() ? (QPT_RAND_BOOL_V ? TSDB_CHILD_TABLE : TSDB_NORMAL_TABLE) : (taosRand() % TSDB_TABLE_MAX); + if (QPT_CORRECT_HIGH_PROB()) { + strcpy(pInserter->tableName, qptCtx.param.tbl.tblName); + } else { + pInserter->tableName[0] = QPT_RAND_BOOL_V ? 'a' : 0; + } + pInserter->vgId = qptCtx.param.vnode.vgId; + memcpy(&pInserter->epSet, &qptCtx.param.vnode.epSet, sizeof(pInserter->epSet)); + pInserter->explain = QPT_RAND_BOOL_V; + + return (SNode*)pInserter; +} + + +SNode* qptCreateDataDeletePhysiNode(int32_t nodeType) { + SDataDeleterNode* pDeleter = (SDataDeleterNode*)qptCreateDataSinkNode(nodeType); + + pDeleter->tableId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.tbl.uid : taosRand(); + pDeleter->tableType = QPT_CORRECT_HIGH_PROB() ? (QPT_RAND_BOOL_V ? TSDB_CHILD_TABLE : TSDB_NORMAL_TABLE) : (taosRand() % TSDB_TABLE_MAX); + if (QPT_CORRECT_HIGH_PROB()) { + sprintf(pDeleter->tableFName, "1.%s.%s", qptCtx.param.db.dbName, qptCtx.param.tbl.tblName); + } else { + pDeleter->tableFName[0] = QPT_RAND_BOOL_V ? 'a' : 0; + } + + SQPTCol* pCol = (SQPTCol*)nodesListGetNode(qptCtx.param.tbl.pColList, 0); + if (QPT_CORRECT_HIGH_PROB() && pCol) { + strcpy(pDeleter->tsColName, pCol->name); + } else { + pDeleter->tsColName[0] = QPT_RAND_BOOL_V ? 't' : 0; + } + + qptGetRandTimeWindow(&pDeleter->deleteTimeRange); + + return (SNode*)pDeleter; +} + +void qptBuildSinkIdx(int32_t* pSinkIdx) { + +} + +void qptCreateSubplanDataSink(SDataSinkNode** ppOutput) { + static int32_t sinkIdx[sizeof(qptSink) / sizeof(qptSink[0])] = {-1}; + int32_t nodeIdx = 0; + + if (sinkIdx[0] < 0) { + qptBuildSinkIdx(sinkIdx); + } + + nodeIdx = taosRand() % (sizeof(sinkIdx)/sizeof(sinkIdx[0])); + + *ppOutput = (SDataSinkNode*)qptCreatePhysicalPlanNode(nodeIdx); +} + + +SNode* qptCreateSubplanNode(int32_t nodeType) { + SSubplan* pSubplan = NULL; + assert(0 == nodesMakeNode((ENodeType)nodeType, (SNode**)&pSubplan)); + + pSubplan->id.queryId = qptCtx.param.plan.queryId; + pSubplan->id.groupId = taosRand() % QPT_MAX_SUBPLAN_GROUP; + pSubplan->id.subplanId = qptCtx.buildCtx.nextSubplanId++; + + pSubplan->subplanType = QPT_CORRECT_HIGH_PROB() ? (ESubplanType)(taosRand() % SUBPLAN_TYPE_COMPUTE + 1) : (ESubplanType)taosRand(); + pSubplan->msgType = qptGetRandSubplanMsgType(); + pSubplan->level = taosRand() % QPT_MAX_SUBPLAN_LEVEL; + sprintf(pSubplan->dbFName, "1.%s", qptCtx.param.db.dbName); + strcpy(pSubplan->user, qptCtx.param.userName); + pSubplan->execNode.nodeId = qptCtx.param.vnode.vgId; + memcpy(&pSubplan->execNode.epSet, &qptCtx.param.vnode.epSet, sizeof(pSubplan->execNode.epSet)); + pSubplan->execNodeStat.tableNum = taosRand(); + + qptCreatePhysiNodesTree(&pSubplan->pNode, NULL, 0); + + qptCreateSubplanDataSink(&pSubplan->pDataSink); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pSubplan->pTagCond); + + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_CORRECT_HIGH_PROB() ? true : false, QPT_RAND_BOOL_V, 0, NULL); + qptMakeExprNode(&pSubplan->pTagIndexCond); + + pSubplan->showRewrite = QPT_RAND_BOOL_V; + pSubplan->isView = QPT_RAND_BOOL_V; + pSubplan->isAudit = QPT_RAND_BOOL_V; + pSubplan->dynamicRowThreshold = QPT_RAND_BOOL_V; + pSubplan->rowsThreshold = taosRand(); + + return (SNode*)pSubplan; +} + + +SNode* qptCreatePhysicalPlanNode(int32_t nodeIdx) { + if (qptPlans[nodeIdx].buildFunc) { + return (*qptPlans[nodeIdx].buildFunc)(qptPlans[nodeIdx].type); + } + + return NULL; +} + +SNode* qptCreateRealPhysicalPlanNode() { + int32_t nodeIdx = 0; + + do { + nodeIdx = taosRand() % (sizeof(qptPlans) / sizeof(qptPlans[0])); + if (QPT_PLAN_PHYSIC != qptPlans[nodeIdx].classify) { + continue; + } + + return qptCreatePhysicalPlanNode(nodeIdx); + } while (true); +} + +void qptCreatePhysiNodesTree(SPhysiNode** ppRes, SPhysiNode* pParent, int32_t level) { + SPhysiNode* pNew = NULL; + if (level < QPT_MAX_SUBPLAN_LEVEL && (NULL == pParent || QPT_RAND_BOOL_V)) { + pNew = (SPhysiNode*)qptCreateRealPhysicalPlanNode(); + pNew->pParent = pParent; + int32_t childrenNum = taosRand() % QPT_MAX_LEVEL_SUBPLAN_NUM; + for (int32_t i = 0; i < childrenNum; ++i) { + qptCreatePhysiNodesTree(NULL, pNew, level + 1); + } + } else if (QPT_RAND_BOOL_V) { + return; + } + + if (pParent) { + qptNodesListMakeStrictAppend(&pParent->pChildren, (SNode*)pNew); + } else { + *ppRes = pNew; + } +} + +void qptAppendParentsSubplan(SNodeList* pParents, SNodeList* pNew) { + SNode* pNode = NULL; + FOREACH(pNode, pNew) { + if (NULL == pNode || QUERY_NODE_PHYSICAL_SUBPLAN != nodeType(pNode)) { + continue; + } + + qptNodesListMakeStrictAppend(&pParents, pNode); + } +} + +void qptSetSubplansRelation(SNodeList* pParents, SNodeList* pNew) { + int32_t parentIdx = 0; + SNode* pNode = NULL; + SSubplan* pChild = NULL; + SSubplan* pParent = NULL; + FOREACH(pNode, pNew) { + if (QPT_CORRECT_HIGH_PROB()) { + pChild = (SSubplan*)pNode; + parentIdx = taosRand() % pParents->length; + pParent = (SSubplan*)nodesListGetNode(pParents, parentIdx); + qptNodesListMakeStrictAppend(&pParent->pChildren, pNode); + qptNodesListMakeStrictAppend(&pChild->pParents, (SNode*)pParent); + } + } +} + +void qptBuildSubplansRelation(SNodeList* pList) { + SNode* pNode = NULL; + SNodeList* pParents = NULL; + FOREACH(pNode, pList) { + if (NULL == pNode || QUERY_NODE_NODE_LIST != nodeType(pNode)) { + continue; + } + + SNodeListNode* pNodeList = (SNodeListNode*)pNode; + + if (NULL == pParents) { + qptAppendParentsSubplan(pParents, pNodeList->pNodeList); + continue; + } + + qptSetSubplansRelation(pParents, pNodeList->pNodeList); + qptAppendParentsSubplan(pParents, pNodeList->pNodeList); + } +} + +SNode* qptCreateQueryPlanNode(int32_t nodeType) { + SQueryPlan* pPlan = NULL; + assert(0 == nodesMakeNode((ENodeType)nodeType, (SNode**)&pPlan)); + + int32_t subplanNum = 0, subplanLevelNum = taosRand() % QPT_MAX_SUBPLAN_LEVEL; + pPlan->queryId = QPT_CORRECT_HIGH_PROB() ? qptCtx.param.plan.queryId : taosRand(); + + for (int32_t l = 0; l < subplanLevelNum; ++l) { + qptInitMakeNodeCtx(QPT_CORRECT_HIGH_PROB() ? false : true, QPT_RAND_BOOL_V, QPT_RAND_BOOL_V, 0, NULL); + qptNodesListMakeStrictAppend(&pPlan->pSubplans, qptMakeNodeListNode(QPT_NODE_SUBPLAN, NULL)); + } + + pPlan->numOfSubplans = qptGetSubplanNum(pPlan->pSubplans); + qptBuildSubplansRelation(pPlan->pSubplans); + + pPlan->explainInfo.mode = (EExplainMode)(taosRand() % EXPLAIN_MODE_ANALYZE + 1); + pPlan->explainInfo.verbose = QPT_RAND_BOOL_V; + pPlan->explainInfo.ratio = taosRand(); + + pPlan->pPostPlan = QPT_RAND_BOOL_V ? NULL : (void*)0x1; + + return (SNode*)pPlan; +} + + +void qptRerunBlockedHere() { + while (qptInRerun) { + taosSsleep(1); + } +} + +void qptResetForReRun() { + qptCtx.param.plan.taskId = 1; + qptCtx.param.vnode.vgId = 1; + + qptResetTableCols(); + + qptCtx.buildCtx.pCurr = NULL; + qptCtx.buildCtx.pCurrTask = NULL; + + qptCtx.result.code = 0; +} + +void qptSingleTestDone(bool* contLoop) { +/* + if (jtRes.succeed) { + *contLoop = false; + return; + } +*/ + + if (qptErrorRerun) { + *contLoop = false; + return; + } + + qptInRerun = true; +} + + +void qptInitLogFile() { + const char *defaultLogFileNamePrefix = "queryPlanTestlog"; + const int32_t maxLogFileNum = 10; + + tsAsyncLog = 0; + qDebugFlag = 159; + TAOS_STRCPY(tsLogDir, TD_LOG_DIR_PATH); + + if (taosInitLog(defaultLogFileNamePrefix, maxLogFileNum, false) < 0) { + printf("failed to open log file in directory:%s\n", tsLogDir); + } +} + + + +void qptInitTest() { + qptInitLogFile(); +} + +void qptHandleTestEnd() { + +} + +void qptExecPlan(SReadHandle* pReadHandle, SNode* pNode, SExecTaskInfo* pTaskInfo, SOperatorInfo** ppOperaotr) { + switch (nodeType(pNode)) { + case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: + qptCtx.result.code = createTagScanOperatorInfo(pReadHandle, (STagScanPhysiNode*)pNode, NULL, NULL, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: + qptCtx.result.code = createTableScanOperatorInfo((STableScanPhysiNode*)pNode, pReadHandle, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN: + qptCtx.result.code = createTableSeqScanOperatorInfo(pReadHandle, pTaskInfo, ppOperaotr); // usless + break; + case QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN: + qptCtx.result.code = createTableMergeScanOperatorInfo((STableScanPhysiNode*)pNode, pReadHandle, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SCAN: + qptCtx.result.code = createStreamScanOperatorInfo(pReadHandle, (STableScanPhysiNode*)pNode, NULL, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_SYSTABLE_SCAN: + qptCtx.result.code = createSysTableScanOperatorInfo(pReadHandle, (SSystemTableScanPhysiNode*)pNode, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: + qptCtx.result.code = createDataBlockInfoScanOperator(pReadHandle, (SBlockDistScanPhysiNode*)pNode, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_LAST_ROW_SCAN: + qptCtx.result.code = createCacherowsScanOperator((SLastRowScanPhysiNode*)pNode, pReadHandle, NULL, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_PROJECT: + qptCtx.result.code = createProjectOperatorInfo(NULL, (SProjectPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_JOIN: + qptCtx.result.code = createMergeJoinOperatorInfo(NULL, 0, (SSortMergeJoinPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_HASH_AGG: { + SAggPhysiNode* pAggNode = (SAggPhysiNode*)pNode; + if (pAggNode->pGroupKeys != NULL) { + qptCtx.result.code = createGroupOperatorInfo(NULL, pAggNode, pTaskInfo, ppOperaotr); + } else { + qptCtx.result.code = createAggregateOperatorInfo(NULL, pAggNode, pTaskInfo, ppOperaotr); + } + break; + } + case QUERY_NODE_PHYSICAL_PLAN_EXCHANGE: + qptCtx.result.code = createExchangeOperatorInfo(NULL, (SExchangePhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE: + qptCtx.result.code = createMultiwayMergeOperatorInfo(NULL, 0, (SMergePhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_SORT: + qptCtx.result.code = createSortOperatorInfo(NULL, (SSortPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_GROUP_SORT: + qptCtx.result.code = createGroupSortOperatorInfo(NULL, (SGroupSortPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: + qptCtx.result.code = createIntervalOperatorInfo(NULL, (SIntervalPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: + qptCtx.result.code = createMergeIntervalOperatorInfo(NULL, (SMergeIntervalPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: + qptCtx.result.code = createMergeAlignedIntervalOperatorInfo(NULL, (SMergeAlignedIntervalPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL: + qptCtx.result.code = createStreamIntervalOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_INTERVAL: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_MID_INTERVAL: + case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL: + qptCtx.result.code = createStreamFinalIntervalOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, 0, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_FILL: + qptCtx.result.code = createFillOperatorInfo(NULL, (SFillPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_FILL: + qptCtx.result.code = createStreamFillOperatorInfo(NULL, (SStreamFillPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_SESSION: + qptCtx.result.code = createSessionAggOperatorInfo(NULL, (SSessionWinodwPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SESSION: + qptCtx.result.code = createStreamSessionAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_SEMI_SESSION: + qptCtx.result.code = createStreamFinalSessionAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, 0, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_SESSION: + qptCtx.result.code = createStreamFinalSessionAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, 0, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_STATE: + qptCtx.result.code = createStatewindowOperatorInfo(NULL, (SStateWinodwPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_STATE: + qptCtx.result.code = createStreamStateAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_PARTITION: + qptCtx.result.code = createPartitionOperatorInfo(NULL, (SPartitionPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION: + qptCtx.result.code = createStreamPartitionOperatorInfo(NULL, (SStreamPartitionPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_INDEF_ROWS_FUNC: + qptCtx.result.code = createIndefinitOutputOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_INTERP_FUNC: + qptCtx.result.code = createTimeSliceOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_INSERT: + qptCtx.result.code = 0; + break; + case QUERY_NODE_PHYSICAL_PLAN_DISPATCH: + case QUERY_NODE_PHYSICAL_PLAN_QUERY_INSERT: + case QUERY_NODE_PHYSICAL_PLAN_DELETE: { + DataSinkHandle handle = NULL; + qptCtx.result.code = dsCreateDataSinker(NULL, (SDataSinkNode*)pNode, &handle, NULL, NULL); + dsDestroyDataSinker(handle); + break; + } + case QUERY_NODE_PHYSICAL_SUBPLAN: { + DataSinkHandle handle = NULL; + qptCtx.result.code = qCreateExecTask(pReadHandle, qptCtx.param.vnode.vgId, pTaskInfo->id.taskId, (SSubplan*)pNode, (qTaskInfo_t*)&pTaskInfo, &handle, + QPT_RAND_BOOL_V ? 0 : 1, taosStrdup("sql string"), OPTR_EXEC_MODEL_BATCH); + break; + } + case QUERY_NODE_PHYSICAL_PLAN: { + qptCtx.result.code = schedulerValidatePlan((SQueryPlan*)pNode); + break; + } + case QUERY_NODE_PHYSICAL_PLAN_TABLE_COUNT_SCAN: + qptCtx.result.code = createTableCountScanOperatorInfo(pReadHandle, (STableCountScanPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_EVENT: + qptCtx.result.code = createEventwindowOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_EVENT: + qptCtx.result.code = createStreamEventAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, pReadHandle, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_HASH_JOIN: + qptCtx.result.code = createHashJoinOperatorInfo(NULL, 0, (SHashJoinPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_GROUP_CACHE: + qptCtx.result.code = createGroupCacheOperatorInfo(NULL, 0, (SGroupCachePhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_DYN_QUERY_CTRL: + qptCtx.result.code = createDynQueryCtrlOperatorInfo(NULL, 0, (SDynQueryCtrlPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_COUNT: + qptCtx.result.code = createCountwindowOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, ppOperaotr); + break; + case QUERY_NODE_PHYSICAL_PLAN_STREAM_COUNT: + qptCtx.result.code = createStreamCountAggOperatorInfo(NULL, (SPhysiNode*)pNode, pTaskInfo, pReadHandle, ppOperaotr); + break; + default: + assert(0); + } + + if (qptCtx.result.code) { + qptCtx.result.failedTimes++; + } else { + qptCtx.result.succeedTimes++; + } + +} + +void qptRunSingleOpTest() { + SNode* pNode = NULL; + SReadHandle readHandle = {0}; + SOperatorInfo* pOperator = NULL; + SExecTaskInfo* pTaskInfo = NULL; + SStorageAPI storageAPI = {0}; + + qptResetForReRun(); + + doCreateTask(qptCtx.param.plan.queryId, qptCtx.param.plan.taskId, qptCtx.param.vnode.vgId, OPTR_EXEC_MODEL_BATCH, &storageAPI, &pTaskInfo); + qptCtx.buildCtx.pCurrTask = pTaskInfo; + + pNode = (SNode*)qptCreatePhysicalPlanNode(qptCtx.param.plan.subplanIdx[0]); + + qptPrintBeginInfo(); + + qptCtx.result.startTsUs = taosGetTimestampUs(); + + qptExecPlan(&readHandle, pNode, pTaskInfo, &pOperator); + + doDestroyTask(pTaskInfo); + destroyOperator(pOperator); + nodesDestroyNode((SNode*)pNode); + + qptPrintEndInfo(); + + qptHandleTestEnd(); +} + +void qptRunSubplanTest() { + SNode* pNode = NULL; + SReadHandle readHandle = {0}; + SOperatorInfo* pOperator = NULL; + + if (qptCtx.loopIdx > 0) { + qptResetForReRun(); + } + + //pNode = (SNode*)qptCreatePhysicalPlanNode(qptCtx.param.plan.subplanType[0]); + + qptPrintBeginInfo(); + + qptCtx.result.startTsUs = taosGetTimestampUs(); + //qptCtx.result.code = createTagScanOperatorInfo(&readHandle, (STagScanPhysiNode*)pNode, NULL, NULL, NULL, NULL, &pOperator); + //qptCtx.result.code = createProjectOperatorInfo(NULL, (SProjectPhysiNode*)pNode, NULL, &pOperator); + + destroyOperator(pOperator); + nodesDestroyNode((SNode*)pNode); + + qptPrintEndInfo(); + + qptHandleTestEnd(); +} + + +void qptRunPlanTest() { + if (qptCtx.param.plan.singlePhysiNode) { + qptRunSingleOpTest(); + } else { + qptRunSubplanTest(); + } +} + +SQPTNodeParam* qptInitNodeParam(int32_t nodeType) { + return NULL; +} + +void qptInitTableCols(SNodeList** ppList, int32_t colNum, EColumnType colType) { + SQPTCol* pCol = NULL; + int32_t tbnameIdx = -1; + if (QPT_RAND_BOOL_V && COLUMN_TYPE_TAG == colType) { + tbnameIdx = taosRand() % colNum; + } + + for (int32_t i = 0; i < colNum; ++i) { + qptNodesCalloc(1, sizeof(SQPTCol), (void**)&pCol); + pCol->type = QPT_QUERY_NODE_COL; + + if (tbnameIdx >= 0 && i == tbnameIdx) { + strcpy(pCol->name, "tbname"); + pCol->dtype = TSDB_DATA_TYPE_VARCHAR; + pCol->len = qptGetColumnRandLen(pCol->dtype); + pCol->inUse = 0; + pCol->hasIndex = QPT_RAND_BOOL_V; + pCol->isPrimTs = QPT_RAND_BOOL_V; + pCol->isPk = QPT_RAND_BOOL_V; + pCol->colType = COLUMN_TYPE_TBNAME; + + qptNodesListMakeStrictAppend(ppList, (SNode *)pCol); + continue; + } + + qptInitSingleTableCol(pCol, i, colType); + + qptNodesListMakeStrictAppend(ppList, (SNode *)pCol); + } +} + +void qptInitTestCtx(bool correctExpected, bool singleNode, int32_t nodeType, int32_t nodeIdx, int32_t paramNum, SQPTNodeParam* nodeParam) { + qptCtx.param.correctExpected = correctExpected; + qptCtx.param.schedulerId = taosRand(); + strcpy(qptCtx.param.userName, "user1"); + qptCtx.param.plan.singlePhysiNode = singleNode; + + if (singleNode) { + qptCtx.param.plan.subplanMaxLevel = 1; + qptCtx.param.plan.subplanType[0] = nodeType; + qptCtx.param.plan.subplanIdx[0] = nodeIdx; + } else { + qptCtx.param.plan.subplanMaxLevel = taosRand() % QPT_MAX_SUBPLAN_LEVEL + 1; + for (int32_t i = 0; i < qptCtx.param.plan.subplanMaxLevel; ++i) { + nodeIdx = taosRand() % QPT_PHYSIC_NODE_NUM(); + qptCtx.param.plan.subplanType[i] = qptPlans[nodeIdx].type; + qptCtx.param.plan.subplanIdx[i] = nodeIdx; + } + } + + if (paramNum > 0) { + qptCtx.param.plan.physiNodeParamNum = paramNum; + qptCtx.param.plan.physicNodeParam = nodeParam; + } + + qptCtx.param.plan.queryId++; + qptCtx.param.plan.taskId++; + + qptCtx.param.db.precision = TSDB_TIME_PRECISION_MILLI; + strcpy(qptCtx.param.db.dbName, "qptdb1"); + + qptCtx.param.vnode.vnodeNum = QPT_DEFAULT_VNODE_NUM; + qptCtx.param.vnode.vgId = 1; + qptCtx.param.vnode.epSet.numOfEps = 1; + qptCtx.param.vnode.epSet.inUse = 0; + strcpy(qptCtx.param.vnode.epSet.eps[0].fqdn, "127.0.0.1"); + qptCtx.param.vnode.epSet.eps[0].port = 6030; + + qptCtx.param.tbl.uid = 100; + qptCtx.param.tbl.suid = 1; + qptGetRandRealTableType(&qptCtx.param.tbl.tblType); + qptCtx.param.tbl.colNum = taosRand() % 4096 + 1; + qptCtx.param.tbl.tagNum = taosRand() % 128 + 1; + qptCtx.param.tbl.pkNum = taosRand() % 2; + strcpy(qptCtx.param.tbl.tblName, "qpttbl1"); + strcpy(qptCtx.param.tbl.tblName, "tbl1"); + + qptInitTableCols(&qptCtx.param.tbl.pColList, qptCtx.param.tbl.colNum, COLUMN_TYPE_COLUMN); + qptInitTableCols(&qptCtx.param.tbl.pTagList, qptCtx.param.tbl.tagNum, COLUMN_TYPE_TAG); + + SNode* pTmp = NULL; + FOREACH(pTmp, qptCtx.param.tbl.pColList) { + qptNodesListMakeStrictAppend(&qptCtx.param.tbl.pColTagList, pTmp); + } + FOREACH(pTmp, qptCtx.param.tbl.pTagList) { + qptNodesListMakeStrictAppend(&qptCtx.param.tbl.pColTagList, pTmp); + } + + qptCtx.buildCtx.nextBlockId++; + qptCtx.buildCtx.nextSubplanId++; +} + +void qptDestroyTestCtx() { + SNode* pTmp = NULL; + FOREACH(pTmp, qptCtx.param.tbl.pColList) { + qptNodesFree(pTmp); + } + FOREACH(pTmp, qptCtx.param.tbl.pTagList) { + qptNodesFree(pTmp); + } + nodesClearList(qptCtx.param.tbl.pColList); + nodesClearList(qptCtx.param.tbl.pTagList); + nodesClearList(qptCtx.param.tbl.pColTagList); + + qptCtx.param.tbl.pColList = NULL; + qptCtx.param.tbl.pTagList = NULL; + qptCtx.param.tbl.pColTagList = NULL; +} + +} // namespace + +#if 1 +#if 0 +TEST(singleRandNodeTest, loopPlans) { + char* caseType = "singleRandNodeTest:loopPlans"; + + for (qptCtx.loopIdx = 0; qptCtx.loopIdx < QPT_MAX_LOOP; ++qptCtx.loopIdx) { + for (int32_t i = 0; i < sizeof(qptPlans)/sizeof(qptPlans[0]); ++i) { + sprintf(qptCtx.caseName, "%s:%s", caseType, qptPlans[i].name); + qptInitTestCtx(false, true, qptPlans[i].type, i, 0, NULL); + + qptRunPlanTest(); + + qptDestroyTestCtx(); + } + } + + qptPrintStatInfo(); +} +#endif +#if 1 +TEST(singleRandNodeTest, specificPlan) { + char* caseType = "singleRandNodeTest:specificPlan"; + + int32_t idx = qptGetSpecificPlanIndex(QUERY_NODE_PHYSICAL_PLAN); + for (qptCtx.loopIdx = 0; qptCtx.loopIdx < QPT_MAX_LOOP; ++qptCtx.loopIdx) { + sprintf(qptCtx.caseName, "%s:%s", caseType, qptPlans[idx].name); + qptInitTestCtx(false, true, qptPlans[idx].type, idx, 0, NULL); + + qptRunPlanTest(); + + qptDestroyTestCtx(); + } + + qptPrintStatInfo(); +} +#endif + + +#endif + + +int main(int argc, char** argv) { + taosSeedRand(taosGetTimestampSec()); + qptInitTest(); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} + + + +#pragma GCC diagnosti diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 5e21cd94e8..6837ecbf20 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -1393,6 +1393,11 @@ static int32_t translateRepeat(SFunctionNode* pFunc, char* pErrBuf, int32_t len) } static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (numOfParams <= 0) { + return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); + } + // The number of parameters has been limited by the syntax definition SExprNode* pPara0 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0); @@ -1550,6 +1555,11 @@ static int32_t translateIn2GeomOutBool(SFunctionNode* pFunc, char* pErrBuf, int3 } static int32_t translateSelectValue(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (numOfParams <= 0) { + return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); + } + pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType; return TSDB_CODE_SUCCESS; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 6830dd01b6..af51eff8a9 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -703,6 +703,8 @@ int32_t nodesMakeNode(ENodeType type, SNode** ppNodeOut) { code = makeNode(type, sizeof(SGroupSortPhysiNode), &pNode); break; case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: code = makeNode(type, sizeof(SIntervalPhysiNode), &pNode); break; + case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: + code = makeNode(type, sizeof(SMergeIntervalPhysiNode), &pNode); break; case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: code = makeNode(type, sizeof(SMergeAlignedIntervalPhysiNode), &pNode); break; case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL: @@ -1606,10 +1608,14 @@ void nodesDestroyNode(SNode* pNode) { case QUERY_NODE_PHYSICAL_PLAN_HASH_JOIN: { SHashJoinPhysiNode* pPhyNode = (SHashJoinPhysiNode*)pNode; destroyPhysiNode((SPhysiNode*)pPhyNode); + nodesDestroyNode(pPhyNode->pWindowOffset); + nodesDestroyNode(pPhyNode->pJLimit); nodesDestroyList(pPhyNode->pOnLeft); nodesDestroyList(pPhyNode->pOnRight); nodesDestroyNode(pPhyNode->leftPrimExpr); nodesDestroyNode(pPhyNode->rightPrimExpr); + nodesDestroyNode(pPhyNode->pLeftOnCond); + nodesDestroyNode(pPhyNode->pRightOnCond); nodesDestroyNode(pPhyNode->pFullOnCond); nodesDestroyList(pPhyNode->pTargets); @@ -1617,8 +1623,6 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pPhyNode->pColEqCond); nodesDestroyNode(pPhyNode->pTagEqCond); - nodesDestroyNode(pPhyNode->pLeftOnCond); - nodesDestroyNode(pPhyNode->pRightOnCond); break; } case QUERY_NODE_PHYSICAL_PLAN_HASH_AGG: { @@ -1652,6 +1656,7 @@ void nodesDestroyNode(SNode* pNode) { break; } case QUERY_NODE_PHYSICAL_PLAN_HASH_INTERVAL: + case QUERY_NODE_PHYSICAL_PLAN_MERGE_INTERVAL: case QUERY_NODE_PHYSICAL_PLAN_MERGE_ALIGNED_INTERVAL: case QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL: case QUERY_NODE_PHYSICAL_PLAN_STREAM_FINAL_INTERVAL: @@ -2056,6 +2061,8 @@ void* nodesGetValueFromNode(SValueNode* pNode) { int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value) { switch (pNode->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + break; case TSDB_DATA_TYPE_BOOL: pNode->datum.b = *(bool*)value; *(bool*)&pNode->typeData = pNode->datum.b; @@ -2107,7 +2114,10 @@ int32_t nodesSetValueNodeValue(SValueNode* pNode, void* value) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: + case TSDB_DATA_TYPE_DECIMAL: case TSDB_DATA_TYPE_JSON: + case TSDB_DATA_TYPE_BLOB: + case TSDB_DATA_TYPE_MEDIUMBLOB: case TSDB_DATA_TYPE_GEOMETRY: pNode->datum.p = (char*)value; break; diff --git a/source/libs/planner/inc/planInt.h b/source/libs/planner/inc/planInt.h index beb277493c..59e771454c 100644 --- a/source/libs/planner/inc/planInt.h +++ b/source/libs/planner/inc/planInt.h @@ -24,6 +24,18 @@ extern "C" { #include "tsimplehash.h" #include "taoserror.h" + +typedef struct SPhysiPlanContext { + SPlanContext* pPlanCxt; + int32_t errCode; + int16_t nextDataBlockId; + SArray* pLocationHelper; + SArray* pProjIdxLocHelper; + bool hasScan; + bool hasSysScan; +} SPhysiPlanContext; + + #define planFatal(param, ...) qFatal("PLAN: " param, ##__VA_ARGS__) #define planError(param, ...) qError("PLAN: " param, ##__VA_ARGS__) #define planWarn(param, ...) qWarn("PLAN: " param, ##__VA_ARGS__) diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index f05966802b..d80cfc1761 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -30,15 +30,6 @@ typedef struct SSlotIndex { SArray* pSlotIdsInfo; // duplicate name slot } SSlotIndex; -typedef struct SPhysiPlanContext { - SPlanContext* pPlanCxt; - int32_t errCode; - int16_t nextDataBlockId; - SArray* pLocationHelper; - SArray* pProjIdxLocHelper; - bool hasScan; - bool hasSysScan; -} SPhysiPlanContext; static int32_t getSlotKey(SNode* pNode, const char* pStmtName, char** ppKey, int32_t *pLen, uint16_t extraBufLen) { int32_t code = 0; diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index 8a156e8a06..96b9d2da8d 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -62,6 +62,7 @@ typedef enum { #define SCH_DEFAULT_MAX_RETRY_NUM 6 #define SCH_MIN_AYSNC_EXEC_NUM 3 #define SCH_DEFAULT_RETRY_TOTAL_ROUND 3 +#define SCH_DEFAULT_TASK_CAPACITY_NUM 1000 typedef struct SSchDebug { bool lockEnable; @@ -318,6 +319,8 @@ typedef struct SSchTaskCtx { extern SSchedulerMgmt schMgmt; +#define SCH_GET_TASK_CAPACITY(_n) ((_n) > SCH_DEFAULT_TASK_CAPACITY_NUM ? SCH_DEFAULT_TASK_CAPACITY_NUM : (_n)) + #define SCH_TASK_TIMEOUT(_task) \ ((taosGetTimestampUs() - *(int64_t *)taosArrayGet((_task)->profile.execTime, (_task)->execId)) > (_task)->timeoutUsec) @@ -330,8 +333,8 @@ extern SSchedulerMgmt schMgmt; #define SCH_TASK_EID(_task) ((_task) ? (_task)->execId : -1) #define SCH_IS_DATA_BIND_QRY_TASK(task) ((task)->plan->subplanType == SUBPLAN_TYPE_SCAN) -#define SCH_IS_DATA_BIND_TASK(task) \ - (((task)->plan->subplanType == SUBPLAN_TYPE_SCAN) || ((task)->plan->subplanType == SUBPLAN_TYPE_MODIFY)) +#define SCH_IS_DATA_BIND_PLAN(_plan) (((_plan)->subplanType == SUBPLAN_TYPE_SCAN) || ((_plan)->subplanType == SUBPLAN_TYPE_MODIFY)) +#define SCH_IS_DATA_BIND_TASK(task) SCH_IS_DATA_BIND_PLAN((task)->plan) #define SCH_IS_LEAF_TASK(_job, _task) (((_task)->level->level + 1) == (_job)->levelNum) #define SCH_IS_DATA_MERGE_TASK(task) (!SCH_IS_DATA_BIND_TASK(task)) #define SCH_IS_LOCAL_EXEC_TASK(_job, _task) \ @@ -641,6 +644,7 @@ void schDropTaskInHashList(SSchJob *pJob, SHashObj *list); int32_t schNotifyTaskInHashList(SSchJob *pJob, SHashObj *list, ETaskNotifyType type, SSchTask *pTask); int32_t schLaunchLevelTasks(SSchJob *pJob, SSchLevel *level); void schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask); +int32_t schValidateSubplan(SSchJob *pJob, SSubplan* pSubplan, int32_t level, int32_t idx, int32_t taskNum); int32_t schInitTask(SSchJob *pJob, SSchTask *pTask, SSubplan *pPlan, SSchLevel *pLevel); int32_t schSwitchTaskCandidateAddr(SSchJob *pJob, SSchTask *pTask); void schDirectPostJobRes(SSchedulerReq *pReq, int32_t errCode); diff --git a/source/libs/scheduler/src/schJob.c b/source/libs/scheduler/src/schJob.c index 03145da939..375a316185 100644 --- a/source/libs/scheduler/src/schJob.c +++ b/source/libs/scheduler/src/schJob.c @@ -200,7 +200,12 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { SSubplan *child = (SSubplan *)nodesListGetNode(pPlan->pChildren, n); if (NULL == child) { SCH_JOB_ELOG("fail to get the %dth child subplan, childNum: %d", n, childNum); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (QUERY_NODE_PHYSICAL_SUBPLAN != nodeType(child)) { + SCH_JOB_ELOG("invalid subplan type for the %dth child, level:%d, subplanNodeType:%d", n, i, nodeType(child)); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } SSchTask **childTask = taosHashGet(planToTask, &child, POINTER_BYTES); @@ -242,6 +247,11 @@ int32_t schBuildTaskRalation(SSchJob *pJob, SHashObj *planToTask) { SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); } + if (QUERY_NODE_PHYSICAL_SUBPLAN != nodeType(parent)) { + SCH_JOB_ELOG("invalid subplan type for the %dth parent, level:%d, subplanNodeType:%d", n, i, nodeType(parent)); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + SSchTask **parentTask = taosHashGet(planToTask, &parent, POINTER_BYTES); if (NULL == parentTask || NULL == *parentTask) { SCH_TASK_ELOG("subplan parent relationship error, level:%d, taskIdx:%d, childIdx:%d", i, m, n); @@ -307,7 +317,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); } - pJob->dataSrcTasks = taosArrayInit(pDag->numOfSubplans, POINTER_BYTES); + pJob->dataSrcTasks = taosArrayInit(SCH_GET_TASK_CAPACITY(pDag->numOfSubplans), POINTER_BYTES); if (NULL == pJob->dataSrcTasks) { SCH_ERR_RET(terrno); } @@ -319,12 +329,12 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { } SHashObj *planToTask = taosHashInit( - pDag->numOfSubplans, + SCH_GET_TASK_CAPACITY(pDag->numOfSubplans), taosGetDefaultHashFunction(POINTER_BYTES == sizeof(int64_t) ? TSDB_DATA_TYPE_BIGINT : TSDB_DATA_TYPE_INT), false, HASH_NO_LOCK); if (NULL == planToTask) { SCH_JOB_ELOG("taosHashInit %d failed", SCHEDULE_DEFAULT_MAX_TASK_NUM); - SCH_ERR_RET(terrno); + SCH_ERR_JRET(terrno); } pJob->levels = taosArrayInit(levelNum, sizeof(SSchLevel)); @@ -339,6 +349,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SSchLevel level = {0}; SNodeListNode *plans = NULL; int32_t taskNum = 0; + int32_t totalTaskNum = 0; SSchLevel *pLevel = NULL; level.status = JOB_TASK_STATUS_INIT; @@ -352,7 +363,7 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { pLevel = taosArrayGet(pJob->levels, i); if (NULL == pLevel) { SCH_JOB_ELOG("fail to get the %dth level, levelNum: %d", i, levelNum); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } pLevel->level = i; @@ -363,12 +374,23 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } + if (QUERY_NODE_NODE_LIST != nodeType(plans)) { + SCH_JOB_ELOG("invalid level plan, level:%d, planNodeType:%d", i, nodeType(plans)); + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); + } + taskNum = (int32_t)LIST_LENGTH(plans->pNodeList); if (taskNum <= 0) { SCH_JOB_ELOG("invalid level plan number:%d, level:%d", taskNum, i); SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); } + totalTaskNum += taskNum; + if (totalTaskNum > pDag->numOfSubplans) { + SCH_JOB_ELOG("current totalTaskNum %d is bigger than numOfSubplans %d, level:%d", totalTaskNum, pDag->numOfSubplans, i); + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); + } + pLevel->taskNum = taskNum; pLevel->subTasks = taosArrayInit(taskNum, sizeof(SSchTask)); @@ -379,11 +401,9 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { for (int32_t n = 0; n < taskNum; ++n) { SSubplan *plan = (SSubplan *)nodesListGetNode(plans->pNodeList, n); - if (NULL == plan) { - SCH_JOB_ELOG("fail to get the %dth subplan, taskNum: %d", n, taskNum); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); - } + SCH_ERR_JRET(schValidateSubplan(pJob, plan, pLevel->level, n, taskNum)); + SCH_SET_JOB_TYPE(pJob, plan->subplanType); SSchTask task = {0}; @@ -397,14 +417,16 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SCH_ERR_JRET(schAppendJobDataSrc(pJob, pTask)); - if (0 != taosHashPut(planToTask, &plan, POINTER_BYTES, &pTask, POINTER_BYTES)) { - SCH_TASK_ELOG("taosHashPut to planToTaks failed, taskIdx:%d", n); - SCH_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + code = taosHashPut(planToTask, &plan, POINTER_BYTES, &pTask, POINTER_BYTES); + if (0 != code) { + SCH_TASK_ELOG("taosHashPut to planToTaks failed, taskIdx:%d, error:%s", n, tstrerror(code)); + SCH_ERR_JRET(code); } - if (0 != taosHashPut(pJob->taskList, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES)) { - SCH_TASK_ELOG("taosHashPut to taskList failed, taskIdx:%d", n); - SCH_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); + code = taosHashPut(pJob->taskList, &pTask->taskId, sizeof(pTask->taskId), &pTask, POINTER_BYTES); + if (0 != code) { + SCH_TASK_ELOG("taosHashPut to taskList failed, taskIdx:%d, error:%s", n, tstrerror(code)); + SCH_ERR_JRET(code); } ++pJob->taskNum; @@ -413,6 +435,11 @@ int32_t schValidateAndBuildJob(SQueryPlan *pDag, SSchJob *pJob) { SCH_JOB_DLOG("level %d initialized, taskNum:%d", i, taskNum); } + if (totalTaskNum != pDag->numOfSubplans) { + SCH_JOB_ELOG("totalTaskNum %d mis-match with numOfSubplans %d", totalTaskNum, pDag->numOfSubplans); + SCH_ERR_JRET(TSDB_CODE_QRY_INVALID_INPUT); + } + SCH_ERR_JRET(schBuildTaskRalation(pJob, planToTask)); _return: @@ -781,9 +808,11 @@ void schFreeJobImpl(void *job) { } taosMemoryFree(pJob); - int32_t jobNum = atomic_sub_fetch_32(&schMgmt.jobNum, 1); - if (jobNum == 0) { - schCloseJobRef(); + if (refId > 0) { + int32_t jobNum = atomic_sub_fetch_32(&schMgmt.jobNum, 1); + if (jobNum == 0) { + schCloseJobRef(); + } } qDebug("QID:0x%" PRIx64 " sch job freed, refId:0x%" PRIx64 ", pointer:%p", queryId, refId, pJob); @@ -861,10 +890,10 @@ int32_t schInitJob(int64_t *pJobId, SSchedulerReq *pReq) { } } - pJob->taskList = taosHashInit(pReq->pDag->numOfSubplans, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, + pJob->taskList = taosHashInit(SCH_GET_TASK_CAPACITY(pReq->pDag->numOfSubplans), taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_ENTRY_LOCK); if (NULL == pJob->taskList) { - SCH_JOB_ELOG("taosHashInit %d taskList failed", pReq->pDag->numOfSubplans); + SCH_JOB_ELOG("taosHashInit %d taskList failed", SCH_GET_TASK_CAPACITY(pReq->pDag->numOfSubplans)); SCH_ERR_JRET(terrno); } @@ -904,7 +933,7 @@ _return: if (NULL == pJob) { qDestroyQueryPlan(pReq->pDag); - } else if (pJob->refId < 0) { + } else if (pJob->refId <= 0) { schFreeJobImpl(pJob); } else { code = taosRemoveRef(schMgmt.jobRef, pJob->refId); diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index e6b68051f9..fe24633c12 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -831,7 +831,7 @@ int32_t schSetTaskCandidateAddrs(SSchJob *pJob, SSchTask *pTask) { if (SCH_IS_DATA_BIND_TASK(pTask)) { SCH_TASK_ELOG("no execNode specifed for data src task, numOfEps:%d", pTask->plan->execNode.epSet.numOfEps); - SCH_ERR_RET(TSDB_CODE_MND_INVALID_SCHEMA_VER); + SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); } SCH_ERR_RET(schSetAddrsFromNodeList(pJob, pTask)); diff --git a/source/libs/scheduler/src/schUtil.c b/source/libs/scheduler/src/schUtil.c index b68f665200..4697de6f28 100644 --- a/source/libs/scheduler/src/schUtil.c +++ b/source/libs/scheduler/src/schUtil.c @@ -360,3 +360,50 @@ void schGetTaskFromList(SHashObj *pTaskList, uint64_t taskId, SSchTask **pTask) *pTask = *task; } + +int32_t schValidateSubplan(SSchJob *pJob, SSubplan* pSubplan, int32_t level, int32_t idx, int32_t taskNum) { + if (NULL == pSubplan) { + SCH_JOB_ELOG("fail to get the %dth subplan, taskNum: %d, level: %d", idx, taskNum, level); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (QUERY_NODE_PHYSICAL_SUBPLAN != nodeType(pSubplan)) { + SCH_JOB_ELOG("invalid subplan type, level:%d, subplanNodeType:%d", level, nodeType(pSubplan)); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (pSubplan->subplanType < SUBPLAN_TYPE_MERGE || pSubplan->subplanType > SUBPLAN_TYPE_COMPUTE) { + SCH_JOB_ELOG("invalid subplanType %d, level:%d, subplan idx:%d", pSubplan->subplanType, level, idx); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (pSubplan->level != level) { + SCH_JOB_ELOG("plan level %d mis-match with current level %d", pSubplan->level, level); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (SCH_IS_DATA_BIND_PLAN(pSubplan)) { + if (pSubplan->execNode.epSet.numOfEps <= 0) { + SCH_JOB_ELOG("no execNode specifed for data src plan %d, numOfEps:%d", pSubplan->subplanType, pSubplan->execNode.epSet.numOfEps); + SCH_ERR_RET(TSDB_CODE_SCH_DATA_SRC_EP_MISS); + } + if (pSubplan->execNode.epSet.inUse >= pSubplan->execNode.epSet.numOfEps) { + SCH_JOB_ELOG("invalid epset inUse %d for data src plan %d, numOfEps:%d", pSubplan->execNode.epSet.inUse, pSubplan->subplanType, pSubplan->execNode.epSet.numOfEps); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + } + + if (NULL == pSubplan->pNode && pSubplan->subplanType != SUBPLAN_TYPE_MODIFY) { + SCH_JOB_ELOG("empty plan root node, level:%d, subplan idx:%d, subplanType:%d", level, idx, pSubplan->subplanType); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + if (NULL == pSubplan->pDataSink) { + SCH_JOB_ELOG("empty plan dataSink, level:%d, subplan idx:%d", level, idx); + SCH_ERR_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + return TSDB_CODE_SUCCESS; +} + + diff --git a/source/libs/scheduler/src/scheduler.c b/source/libs/scheduler/src/scheduler.c index 091de5c048..db9ecd6025 100644 --- a/source/libs/scheduler/src/scheduler.c +++ b/source/libs/scheduler/src/scheduler.c @@ -224,3 +224,33 @@ void schedulerDestroy(void) { qWorkerDestroy(&schMgmt.queryMgmt); schMgmt.queryMgmt = NULL; } + +int32_t schedulerValidatePlan(SQueryPlan* pPlan) { + int32_t code = TSDB_CODE_SUCCESS; + SSchJob *pJob = taosMemoryCalloc(1, sizeof(SSchJob)); + if (NULL == pJob) { + qError("QID:0x%" PRIx64 " calloc %d failed", pPlan->queryId, (int32_t)sizeof(SSchJob)); + SCH_ERR_RET(terrno); + } + + pJob->taskList = taosHashInit(100, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, + HASH_ENTRY_LOCK); + if (NULL == pJob->taskList) { + SCH_JOB_ELOG("taosHashInit %d taskList failed", 100); + SCH_ERR_JRET(terrno); + } + + SCH_ERR_JRET(schValidateAndBuildJob(pPlan, pJob)); + + if (SCH_IS_EXPLAIN_JOB(pJob)) { + SCH_ERR_JRET(qExecExplainBegin(pPlan, &pJob->explainCtx, 0)); + } + +_return: + + schFreeJobImpl(pJob); + + return code; +} + + diff --git a/source/libs/scheduler/test/schedulerTests.cpp b/source/libs/scheduler/test/schedulerTests.cpp index 44d32b9480..6e13e37e88 100644 --- a/source/libs/scheduler/test/schedulerTests.cpp +++ b/source/libs/scheduler/test/schedulerTests.cpp @@ -203,6 +203,10 @@ void schtBuildQueryDag(SQueryPlan *dag) { return; } scanPlan->msgType = TDMT_SCH_QUERY; + code = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DISPATCH, (SNode**)&scanPlan->pDataSink); + if (NULL == scanPlan->pDataSink) { + return; + } mergePlan->id.queryId = qId; mergePlan->id.groupId = schtMergeTemplateId; @@ -223,6 +227,10 @@ void schtBuildQueryDag(SQueryPlan *dag) { return; } mergePlan->msgType = TDMT_SCH_QUERY; + code = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DISPATCH, (SNode**)&mergePlan->pDataSink); + if (NULL == mergePlan->pDataSink) { + return; + } merge->pNodeList = NULL; code = nodesMakeList(&merge->pNodeList); @@ -235,6 +243,7 @@ void schtBuildQueryDag(SQueryPlan *dag) { return; } + (void)nodesListAppend(merge->pNodeList, (SNode *)mergePlan); (void)nodesListAppend(scan->pNodeList, (SNode *)scanPlan); @@ -250,7 +259,7 @@ void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) { int32_t scanPlanNum = 20; dag->queryId = qId; - dag->numOfSubplans = 2; + dag->numOfSubplans = scanPlanNum + 1; dag->pSubplans = NULL; int32_t code = nodesMakeList(&dag->pSubplans); if (NULL == dag->pSubplans) { @@ -289,6 +298,10 @@ void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) { if (NULL == mergePlan->pChildren) { return; } + code = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DISPATCH, (SNode**)&mergePlan->pDataSink); + if (NULL == mergePlan->pDataSink) { + return; + } for (int32_t i = 0; i < scanPlanNum; ++i) { SSubplan *scanPlan = NULL; @@ -322,6 +335,10 @@ void schtBuildQueryFlowCtrlDag(SQueryPlan *dag) { return; } scanPlan->msgType = TDMT_SCH_QUERY; + code = nodesMakeNode(QUERY_NODE_PHYSICAL_PLAN_DISPATCH, (SNode**)&scanPlan->pDataSink); + if (NULL == scanPlan->pDataSink) { + return; + } (void)nodesListAppend(scanPlan->pParents, (SNode *)mergePlan); (void)nodesListAppend(mergePlan->pChildren, (SNode *)scanPlan); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 52a3be120d..4d8b3627ef 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -618,6 +618,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SCH_INTERNAL_ERROR, "scheduler internal er TAOS_DEFINE_ERROR(TSDB_CODE_SCH_TIMEOUT_ERROR, "Task timeout") TAOS_DEFINE_ERROR(TSDB_CODE_SCH_JOB_IS_DROPPING, "Job is dropping") TAOS_DEFINE_ERROR(TSDB_CODE_SCH_JOB_NOT_EXISTS, "Job no longer exist") +TAOS_DEFINE_ERROR(TSDB_CODE_SCH_DATA_SRC_EP_MISS, "No valid epSet for data source node") // parser TAOS_DEFINE_ERROR(TSDB_CODE_PAR_SYNTAX_ERROR, "syntax error near")