TD-14383 limit/slimit plan implement, and sort plan bugfix
This commit is contained in:
parent
a5af4547d9
commit
0f60e644e9
|
@ -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,
|
||||
|
||||
|
|
|
@ -67,6 +67,10 @@ typedef struct SProjectLogicNode {
|
|||
SLogicNode node;
|
||||
SNodeList* pProjections;
|
||||
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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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}};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue