diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h index 9b8739a4f3d38e1af8d1d672097b4de236ad2f44..411d34063c63e822e478d32ac9c001a167190745 100644 --- a/include/libs/nodes/nodes.h +++ b/include/libs/nodes/nodes.h @@ -121,6 +121,7 @@ typedef enum ENodeType { QUERY_NODE_LOGIC_PLAN_EXCHANGE, QUERY_NODE_LOGIC_PLAN_WINDOW, QUERY_NODE_LOGIC_PLAN_SORT, + QUERY_NODE_LOGIC_PLAN_PARTITION, QUERY_NODE_LOGIC_SUBPLAN, QUERY_NODE_LOGIC_PLAN, diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index 08792b6f8fbb165a708492445df7580a1dd70f53..68e081cd1539f32d78aeec7cc676f5dcbfab59d0 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -66,7 +66,11 @@ typedef struct SAggLogicNode { typedef struct SProjectLogicNode { SLogicNode node; SNodeList* pProjections; - char stmtName[TSDB_TABLE_NAME_LEN]; + char stmtName[TSDB_TABLE_NAME_LEN]; + int64_t limit; + int64_t offset; + int64_t slimit; + int64_t soffset; } SProjectLogicNode; typedef struct SVnodeModifLogicNode { @@ -106,6 +110,11 @@ typedef struct SSortLogicNode { SNodeList* pSortKeys; } SSortLogicNode; +typedef struct SPartitionLogicNode { + SLogicNode node; + SNodeList* pPartitionKeys; +} SPartitionLogicNode; + typedef enum ESubplanType { SUBPLAN_TYPE_MERGE = 1, SUBPLAN_TYPE_PARTIAL, @@ -150,7 +159,8 @@ typedef struct SDataBlockDescNode { ENodeType type; int16_t dataBlockId; SNodeList* pSlots; - int32_t resultRowSize; + int32_t totalRowSize; + int32_t outputRowSize; int16_t precision; } SDataBlockDescNode; @@ -195,6 +205,10 @@ typedef STableScanPhysiNode STableSeqScanPhysiNode; typedef struct SProjectPhysiNode { SPhysiNode node; SNodeList* pProjections; + int64_t limit; + int64_t offset; + int64_t slimit; + int64_t soffset; } SProjectPhysiNode; typedef struct SJoinPhysiNode { @@ -283,10 +297,17 @@ typedef struct SSubplan { SDataSinkNode* pDataSink; // data of the subplan flow into the datasink } SSubplan; +typedef enum EQueryMode { + QUERY_MODE_NORMAL = 1, + QUERY_MODE_EXPLAIN, + QUERY_MODE_EXPLAIN_AN +} EQueryMode; + typedef struct SQueryPlan { ENodeType type; uint64_t queryId; int32_t numOfSubplans; + SNodeList* pSubplans; // Element is SNodeListNode. The execution level of subplan, starting from 0. } SQueryPlan; diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 66f60bde98c48f46e5a0bd9e3bfefb4399b170bc..5dc2cd35b75f7627d8b10474649185d63f695e20 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -180,8 +180,8 @@ typedef struct SOrderByExprNode { typedef struct SLimitNode { ENodeType type; // QUERY_NODE_LIMIT - uint64_t limit; - uint64_t offset; + int64_t limit; + int64_t offset; } SLimitNode; typedef struct SStateWindowNode { diff --git a/source/libs/executor/src/executorimpl.c b/source/libs/executor/src/executorimpl.c index f38888440cf9d6af09f9f6506e06f2372a36b00a..081c0aa6716127af366ea6ffcff4e6b1d6c159ab 100644 --- a/source/libs/executor/src/executorimpl.c +++ b/source/libs/executor/src/executorimpl.c @@ -350,7 +350,7 @@ SSDataBlock* createOutputBuf_rv1(SDataBlockDescNode* pNode) { pBlock->pDataBlock = taosArrayInit(numOfCols, sizeof(SColumnInfoData)); pBlock->info.blockId = pNode->dataBlockId; - pBlock->info.rowSize = pNode->resultRowSize; + pBlock->info.rowSize = pNode->totalRowSize; for(int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData idata = {{0}}; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 9d0b79ca80eea9bea35f92d575392c89237c6062..e728078a38bdd28a3e25acd78ad56a593fbb35ca 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -260,9 +260,9 @@ static SNode* logicAggCopy(const SAggLogicNode* pSrc, SAggLogicNode* pDst) { } static SNode* logicProjectCopy(const SProjectLogicNode* pSrc, SProjectLogicNode* pDst) { + COPY_ALL_SCALAR_FIELDS; COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); CLONE_NODE_LIST_FIELD(pProjections); - COPY_CHAR_ARRAY_FIELD(stmtName); return (SNode*)pDst; } @@ -307,10 +307,8 @@ static SNode* logicSubplanCopy(const SLogicSubplan* pSrc, SLogicSubplan* pDst) { } static SNode* dataBlockDescCopy(const SDataBlockDescNode* pSrc, SDataBlockDescNode* pDst) { - COPY_SCALAR_FIELD(dataBlockId); + COPY_ALL_SCALAR_FIELDS; CLONE_NODE_LIST_FIELD(pSlots); - COPY_SCALAR_FIELD(resultRowSize); - COPY_SCALAR_FIELD(precision); return (SNode*)pDst; } diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index 15e03b9891574ac10322f33f5e9277ace2740181..01d49cb3641234b421cd255418e77faeaf96f7f0 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -475,6 +475,10 @@ static int32_t jsonToLogicScanNode(const SJson* pJson, void* pObj) { } static const char* jkProjectLogicPlanProjections = "Projections"; +static const char* jkProjectLogicPlanLimit = "Limit"; +static const char* jkProjectLogicPlanOffset = "Offset"; +static const char* jkProjectLogicPlanSlimit = "SLimit"; +static const char* jkProjectLogicPlanSoffset = "SOffset"; static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) { const SProjectLogicNode* pNode = (const SProjectLogicNode*)pObj; @@ -483,6 +487,18 @@ static int32_t logicProjectNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = nodeListToJson(pJson, jkProjectLogicPlanProjections, pNode->pProjections); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanLimit, pNode->limit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanOffset, pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectLogicPlanSlimit, pNode->slimit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkScanLogicPlanTableMetaSize, pNode->soffset); + } return code; } @@ -494,6 +510,18 @@ static int32_t jsonToLogicProjectNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeList(pJson, jkProjectLogicPlanProjections, &pNode->pProjections); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanLimit, &pNode->limit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanOffset, &pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectLogicPlanSlimit, &pNode->slimit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkScanLogicPlanTableMetaSize, &pNode->soffset); + } return code; } @@ -802,6 +830,10 @@ static int32_t jsonToPhysiSysTableScanNode(const SJson* pJson, void* pObj) { } static const char* jkProjectPhysiPlanProjections = "Projections"; +static const char* jkProjectPhysiPlanLimit = "Limit"; +static const char* jkProjectPhysiPlanOffset = "Offset"; +static const char* jkProjectPhysiPlanSlimit = "SLimit"; +static const char* jkProjectPhysiPlanSoffset = "SOffset"; static int32_t physiProjectNodeToJson(const void* pObj, SJson* pJson) { const SProjectPhysiNode* pNode = (const SProjectPhysiNode*)pObj; @@ -810,6 +842,18 @@ static int32_t physiProjectNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = nodeListToJson(pJson, jkProjectPhysiPlanProjections, pNode->pProjections); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanLimit, pNode->limit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanOffset, pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanSlimit, pNode->slimit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkProjectPhysiPlanSoffset, pNode->soffset); + } return code; } @@ -821,6 +865,18 @@ static int32_t jsonToPhysiProjectNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeList(pJson, jkProjectPhysiPlanProjections, &pNode->pProjections); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanLimit, &pNode->limit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanOffset, &pNode->offset); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanSlimit, &pNode->slimit); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetBigIntValue(pJson, jkProjectPhysiPlanSoffset, &pNode->soffset); + } return code; } @@ -2057,19 +2113,26 @@ static int32_t jsonToDownstreamSourceNode(const SJson* pJson, void* pObj) { static const char* jkDataBlockDescDataBlockId = "DataBlockId"; static const char* jkDataBlockDescSlots = "Slots"; -static const char* jkDataBlockResultRowSize = "ResultRowSize"; +static const char* jkDataBlockTotalRowSize = "TotalRowSize"; +static const char* jkDataBlockOutputRowSize = "OutputRowSize"; +static const char* jkDataBlockPrecision = "Precision"; static int32_t dataBlockDescNodeToJson(const void* pObj, SJson* pJson) { const SDataBlockDescNode* pNode = (const SDataBlockDescNode*)pObj; int32_t code = tjsonAddIntegerToObject(pJson, jkDataBlockDescDataBlockId, pNode->dataBlockId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonAddIntegerToObject(pJson, jkDataBlockResultRowSize, pNode->resultRowSize); + code = tjsonAddIntegerToObject(pJson, jkDataBlockTotalRowSize, pNode->totalRowSize); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDataBlockOutputRowSize, pNode->outputRowSize); } - if (TSDB_CODE_SUCCESS == code) { code = nodeListToJson(pJson, jkDataBlockDescSlots, pNode->pSlots); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddIntegerToObject(pJson, jkDataBlockPrecision, pNode->precision); + } return code; } @@ -2079,12 +2142,17 @@ static int32_t jsonToDataBlockDescNode(const SJson* pJson, void* pObj) { int32_t code = tjsonGetSmallIntValue(pJson, jkDataBlockDescDataBlockId, &pNode->dataBlockId); if (TSDB_CODE_SUCCESS == code) { - code = tjsonGetIntValue(pJson, jkDataBlockResultRowSize, &pNode->resultRowSize); + code = tjsonGetIntValue(pJson, jkDataBlockTotalRowSize, &pNode->totalRowSize); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetIntValue(pJson, jkDataBlockOutputRowSize, &pNode->outputRowSize); } - if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeList(pJson, jkDataBlockDescSlots, &pNode->pSlots); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonGetSmallIntValue(pJson, jkDataBlockPrecision, &pNode->precision); + } return code; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 035a2f1caab65aba3614b3485d953529fe469d01..bd8e9a7518c63805d6ad04c7de7acb5c27568dec 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -582,11 +582,11 @@ int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, const char* nodesWalkSelectStmt(pSelect, clause, collectColumns, &cxt); taosHashCleanup(cxt.pColIdHash); if (TSDB_CODE_SUCCESS != cxt.errCode) { - nodesDestroyList(cxt.pCols); + nodesClearList(cxt.pCols); return cxt.errCode; } if (0 == LIST_LENGTH(cxt.pCols)) { - nodesDestroyList(cxt.pCols); + nodesClearList(cxt.pCols); cxt.pCols = NULL; } *pCols = cxt.pCols; diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index c5a632482c19cac095423c189286b6ccf1fc1236..0a533ecd2cbfec62d4ee728a5c0f8f0866abf0d1 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -717,8 +717,10 @@ SNode* createJoinTableNode(SAstCreateContext* pCxt, EJoinType type, SNode* pLeft SNode* createLimitNode(SAstCreateContext* pCxt, const SToken* pLimit, const SToken* pOffset) { SLimitNode* limitNode = (SLimitNode*)nodesMakeNode(QUERY_NODE_LIMIT); CHECK_OUT_OF_MEM(limitNode); - // limitNode->limit = limit; - // limitNode->offset = offset; + limitNode->limit = strtol(pLimit->z, NULL, 10); + if (NULL != pOffset) { + limitNode->offset = strtol(pOffset->z, NULL, 10); + } return (SNode*)limitNode; } diff --git a/source/libs/parser/src/parTokenizer.c b/source/libs/parser/src/parTokenizer.c index adf5523db3c35a45b44ed0a01a839a59f44752e9..3751041ef7db619aa0a9e3dbfc3c62b455fde1cf 100644 --- a/source/libs/parser/src/parTokenizer.c +++ b/source/libs/parser/src/parTokenizer.c @@ -99,6 +99,7 @@ static SKeyword keywordTable[] = { {"ON", TK_ON}, {"OR", TK_OR}, {"ORDER", TK_ORDER}, + {"PARTITION", TK_PARTITION}, {"PASS", TK_PASS}, {"PORT", TK_PORT}, {"PRECISION", TK_PRECISION}, diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 6771eafa0905d49e847156d0d5db560ab0e345de..0f26bec9b22aff319a2a21f7c28fc3fdc01a684a 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -235,6 +235,8 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); if (NULL != pTable) { strcpy(pCol->tableAlias, pTable->tableAlias); + } else if (QUERY_NODE_COLUMN == nodeType(pExpr)) { + strcpy(pCol->tableAlias, ((SColumnNode*)pExpr)->tableAlias); } strcpy(pCol->colName, pExpr->aliasName); pCol->node.resType = pExpr->resType; @@ -617,7 +619,6 @@ static int32_t toVgroupsInfo(SArray* pVgs, SVgroupsInfo** pVgsInfo) { } static int32_t setSysTableVgroupList(STranslateContext* pCxt, SName* pName, SRealTableNode* pRealTable) { - // todo release if (0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_USER_TABLES)) { return TSDB_CODE_SUCCESS; } @@ -631,11 +632,6 @@ static int32_t setSysTableVgroupList(STranslateContext* pCxt, SName* pName, SRea } if (TSDB_CODE_SUCCESS == code) { - // todo remove - //if (NULL != vgroupList && taosArrayGetSize(vgroupList) > 0 && 0 != strcmp(pRealTable->table.tableName, TSDB_INS_TABLE_USER_TABLES)) { - // taosArrayPopTailBatch(vgroupList, taosArrayGetSize(vgroupList) - 1); - //} - code = toVgroupsInfo(vgroupList, &pRealTable->pVgroupList); } taosArrayDestroy(vgroupList); @@ -1488,12 +1484,6 @@ static int32_t nodeTypeToShowType(ENodeType nt) { static int32_t translateShow(STranslateContext* pCxt, SShowStmt* pStmt) { SShowReq showReq = { .type = nodeTypeToShowType(nodeType(pStmt)) }; - // if ('\0' != pStmt->dbName[0]) { - // SName name = {0}; - // tNameSetDbName(&name, pCxt->pParseCxt->acctId, pStmt->dbName, strlen(pStmt->dbName)); - // char dbFname[TSDB_DB_FNAME_LEN] = {0}; - // tNameGetFullDbName(&name, showReq.db); - // } pCxt->pCmdMsg = taosMemoryMalloc(sizeof(SCmdMsgInfo)); if (NULL == pCxt->pCmdMsg) { diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index 915c8bff83727f967a310f1462a73ba40359640b..bd4b6481f14878b8cc5597c7c575f3db563546d4 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -142,6 +142,46 @@ static EScanType getScanType(SLogicPlanContext* pCxt, SNodeList* pScanCols, STab return SCAN_TYPE_TAG; } +static SNodeptr createPrimaryKeyCol(uint64_t tableId) { + SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + return NULL; + } + pCol->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; + pCol->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; + pCol->tableId = tableId; + pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; + pCol->colType = COLUMN_TYPE_COLUMN; + strcpy(pCol->colName, "#primarykey"); + return pCol; +} + +static int32_t addPrimaryKeyCol(uint64_t tableId, SNodeList** pCols) { + if (NULL == *pCols) { + *pCols = nodesMakeList(); + if (NULL == *pCols) { + return TSDB_CODE_OUT_OF_MEMORY; + } + } + + bool found = false; + SNode* pCol = NULL; + FOREACH(pCol, *pCols) { + if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pCol)->colId) { + found = true; + break; + } + } + + if (!found) { + if (TSDB_CODE_SUCCESS != nodesListStrictAppend(*pCols, createPrimaryKeyCol(tableId))) { + nodesDestroyList(*pCols); + return TSDB_CODE_OUT_OF_MEMORY; + } + } + return TSDB_CODE_SUCCESS; +} + static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable, SLogicNode** pLogicNode) { SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN); if (NULL == pScan) { @@ -161,7 +201,11 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect // set columns to scan SNodeList* pCols = NULL; int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pRealTable->table.tableAlias, &pCols); - if (TSDB_CODE_SUCCESS == code && NULL != pCols) { + if (TSDB_CODE_SUCCESS == code) { + code = addPrimaryKeyCol(pScan->pMeta->uid, &pCols); + } + + if (TSDB_CODE_SUCCESS == code) { pScan->pScanCols = nodesCloneList(pCols); if (NULL == pScan) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -171,13 +215,15 @@ static int32_t createScanLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect pScan->scanType = getScanType(pCxt, pCols, pScan->pMeta); // set output - if (TSDB_CODE_SUCCESS == code && NULL != pCols) { + if (TSDB_CODE_SUCCESS == code) { pScan->node.pTargets = nodesCloneList(pCols); if (NULL == pScan) { code = TSDB_CODE_OUT_OF_MEMORY; } } + nodesClearList(pCols); + if (TSDB_CODE_SUCCESS == code) { *pLogicNode = (SLogicNode*)pScan; } else { @@ -548,6 +594,22 @@ static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSel return TSDB_CODE_OUT_OF_MEMORY; } + if (NULL != pSelect->pLimit) { + pProject->limit = ((SLimitNode*)pSelect->pLimit)->limit; + pProject->offset = ((SLimitNode*)pSelect->pLimit)->offset; + } else { + pProject->limit = -1; + pProject->offset = -1; + } + + if (NULL != pSelect->pSlimit) { + pProject->slimit = ((SLimitNode*)pSelect->pSlimit)->limit; + pProject->soffset = ((SLimitNode*)pSelect->pSlimit)->offset; + } else { + pProject->slimit = -1; + pProject->soffset = -1; + } + int32_t code = TSDB_CODE_SUCCESS; pProject->pProjections = nodesCloneList(pSelect->pProjectionList); @@ -569,15 +631,42 @@ static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSel return code; } +static int32_t createPartitionLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { + if (NULL == pSelect->pPartitionByList) { + return TSDB_CODE_SUCCESS; + } + + SPartitionLogicNode* pPartition = nodesMakeNode(QUERY_NODE_LOGIC_PLAN_PARTITION); + if (NULL == pPartition) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + return TSDB_CODE_SUCCESS; +} + +static int32_t createDistinctLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { + if (!pSelect->isDistinct) { + return TSDB_CODE_SUCCESS; + } + + return TSDB_CODE_SUCCESS; +} + static int32_t createSelectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { SLogicNode* pRoot = NULL; int32_t code = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable, &pRoot); if (TSDB_CODE_SUCCESS == code) { code = createChildLogicNode(pCxt, pSelect, createWindowLogicNode, &pRoot); } + if (TSDB_CODE_SUCCESS == code) { + code = createChildLogicNode(pCxt, pSelect, createPartitionLogicNode, &pRoot); + } if (TSDB_CODE_SUCCESS == code) { code = createChildLogicNode(pCxt, pSelect, createAggLogicNode, &pRoot); } + if (TSDB_CODE_SUCCESS == code) { + code = createChildLogicNode(pCxt, pSelect, createDistinctLogicNode, &pRoot); + } if (TSDB_CODE_SUCCESS == code) { code = createChildLogicNode(pCxt, pSelect, createSortLogicNode, &pRoot); } diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index b8226eb9493e842acc8d4910621b5e061141cae4..db0201bc81a35a02e2efd0884205cecd664002b3 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -131,7 +131,8 @@ static int32_t buildDataBlockSlots(SPhysiPlanContext* pCxt, SNodeList* pList, SD code = putSlotToHash(pDataBlockDesc->dataBlockId, slotId, pNode, pHash); } if (TSDB_CODE_SUCCESS == code) { - pDataBlockDesc->resultRowSize += ((SExprNode*)pNode)->resType.bytes; + pDataBlockDesc->totalRowSize += ((SExprNode*)pNode)->resType.bytes; + pDataBlockDesc->outputRowSize += ((SExprNode*)pNode)->resType.bytes; ++slotId; } else { break; @@ -189,7 +190,10 @@ static int32_t addDataBlockSlotsImpl(SPhysiPlanContext* pCxt, SNodeList* pList, if (TSDB_CODE_SUCCESS == code) { code = putSlotToHashImpl(pDataBlockDesc->dataBlockId, nextSlotId, name, len, pHash); } - pDataBlockDesc->resultRowSize += ((SExprNode*)pExpr)->resType.bytes; + pDataBlockDesc->totalRowSize += ((SExprNode*)pExpr)->resType.bytes; + if (output) { + pDataBlockDesc->outputRowSize += ((SExprNode*)pExpr)->resType.bytes; + } slotId = nextSlotId; ++nextSlotId; } else { @@ -311,20 +315,6 @@ static int32_t setConditionsSlotId(SPhysiPlanContext* pCxt, const SLogicNode* pL return TSDB_CODE_SUCCESS; } -static SNodeptr createPrimaryKeyCol(SPhysiPlanContext* pCxt, uint64_t tableId) { - SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return NULL; - } - pCol->node.resType.type = TSDB_DATA_TYPE_TIMESTAMP; - pCol->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes; - pCol->tableId = tableId; - pCol->colId = PRIMARYKEY_TIMESTAMP_COL_ID; - pCol->colType = COLUMN_TYPE_COLUMN; - strcpy(pCol->colName, "#primarykey"); - return pCol; -} - static int32_t colIdCompare(const void* pLeft, const void* pRight) { SColumnNode* pLeftCol = *(SColumnNode**)pLeft; SColumnNode* pRightCol = *(SColumnNode**)pRight; @@ -353,35 +343,10 @@ static int32_t sortScanCols(SNodeList* pScanCols) { } static int32_t createScanCols(SPhysiPlanContext* pCxt, SScanPhysiNode* pScanPhysiNode, SNodeList* pScanCols) { - if (QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN == nodeType(pScanPhysiNode) - || QUERY_NODE_PHYSICAL_PLAN_TABLE_SEQ_SCAN == nodeType(pScanPhysiNode)) { - pScanPhysiNode->pScanCols = nodesMakeList(); - if (NULL == pScanPhysiNode->pScanCols) { - return TSDB_CODE_OUT_OF_MEMORY; - } - if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pScanPhysiNode->pScanCols, createPrimaryKeyCol(pCxt, pScanPhysiNode->uid))) { - return TSDB_CODE_OUT_OF_MEMORY; - } - - SNode* pNode; - FOREACH(pNode, pScanCols) { - if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pNode)->colId) { - SColumnNode* pCol = nodesListGetNode(pScanPhysiNode->pScanCols, 0); - strcpy(pCol->tableAlias, ((SColumnNode*)pNode)->tableAlias); - strcpy(pCol->colName, ((SColumnNode*)pNode)->colName); - continue; - } - if (TSDB_CODE_SUCCESS != nodesListStrictAppend(pScanPhysiNode->pScanCols, nodesCloneNode(pNode))) { - return TSDB_CODE_OUT_OF_MEMORY; - } - } - } else { - pScanPhysiNode->pScanCols = nodesCloneList(pScanCols); - if (NULL == pScanPhysiNode->pScanCols) { - return TSDB_CODE_OUT_OF_MEMORY; - } + pScanPhysiNode->pScanCols = nodesCloneList(pScanCols); + if (NULL == pScanPhysiNode->pScanCols) { + return TSDB_CODE_OUT_OF_MEMORY; } - return sortScanCols(pScanPhysiNode->pScanCols); } @@ -708,6 +673,11 @@ static int32_t createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChild return TSDB_CODE_OUT_OF_MEMORY; } + pProject->limit = pProjectLogicNode->limit; + pProject->offset = pProjectLogicNode->offset; + pProject->slimit = pProjectLogicNode->slimit; + pProject->soffset = pProjectLogicNode->soffset; + int32_t code = setListSlotId(pCxt, ((SPhysiNode*)nodesListGetNode(pChildren, 0))->pOutputDataBlockDesc->dataBlockId, -1, pProjectLogicNode->pProjections, &pProject->pProjections); if (TSDB_CODE_SUCCESS == code) { code = addDataBlockSlotsForProject(pCxt, pProjectLogicNode->stmtName, pProject->pProjections, pProject->node.pOutputDataBlockDesc); diff --git a/source/libs/planner/test/plannerTest.cpp b/source/libs/planner/test/plannerTest.cpp index 1de5e963351419d712437687286417020b955dcb..ea6498c0c88e0e1d8a198dec1f44e429d55d4b5e 100644 --- a/source/libs/planner/test/plannerTest.cpp +++ b/source/libs/planner/test/plannerTest.cpp @@ -207,7 +207,7 @@ TEST_F(PlannerTest, sessionWindow) { TEST_F(PlannerTest, orderBy) { setDatabase("root", "test"); - bind("SELECT * FROM t1 order by c1"); + bind("SELECT c1 FROM t1 order by c1"); ASSERT_TRUE(run()); bind("SELECT c1 FROM t1 order by c2"); @@ -217,6 +217,32 @@ TEST_F(PlannerTest, orderBy) { ASSERT_TRUE(run()); } +TEST_F(PlannerTest, limit) { + setDatabase("root", "test"); + + bind("SELECT * FROM t1 limit 2"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM t1 limit 5 offset 2"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM t1 limit 2, 5"); + ASSERT_TRUE(run()); +} + +TEST_F(PlannerTest, slimit) { + setDatabase("root", "test"); + + bind("SELECT * FROM t1 partition by c1 slimit 2"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM t1 partition by c1 slimit 5 soffset 2"); + ASSERT_TRUE(run()); + + bind("SELECT * FROM t1 partition by c1 slimit 2, 5"); + ASSERT_TRUE(run()); +} + TEST_F(PlannerTest, showTables) { setDatabase("root", "test");