fix: plan problem caused by project eliminate optimize
This commit is contained in:
parent
f9bc29d149
commit
c54daccf2d
|
@ -29,7 +29,8 @@ extern "C" {
|
|||
typedef enum EDataOrderLevel {
|
||||
DATA_ORDER_LEVEL_NONE = 1,
|
||||
DATA_ORDER_LEVEL_IN_BLOCK,
|
||||
DATA_ORDER_LEVEL_IN_GROUP
|
||||
DATA_ORDER_LEVEL_IN_GROUP,
|
||||
DATA_ORDER_LEVEL_GLOBAL
|
||||
} EDataOrderLevel;
|
||||
|
||||
typedef struct SLogicNode {
|
||||
|
|
|
@ -735,11 +735,12 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, SParsedDataColInfo*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void buildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid, const char* sname, SArray* tagName) {
|
||||
static void buildCreateTbReq(SVCreateTbReq* pTbReq, const char* tname, STag* pTag, int64_t suid, const char* sname,
|
||||
SArray* tagName) {
|
||||
pTbReq->type = TD_CHILD_TABLE;
|
||||
pTbReq->name = strdup(tname);
|
||||
pTbReq->ctb.suid = suid;
|
||||
if(sname) pTbReq->ctb.name = strdup(sname);
|
||||
if (sname) pTbReq->ctb.name = strdup(sname);
|
||||
pTbReq->ctb.pTag = (uint8_t*)pTag;
|
||||
pTbReq->ctb.tagName = taosArrayDup(tagName);
|
||||
pTbReq->commentLen = -1;
|
||||
|
@ -761,7 +762,7 @@ static int32_t parseTagToken(char** end, SToken* pToken, SSchema* pSchema, int16
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// strcpy(val->colName, pSchema->name);
|
||||
// strcpy(val->colName, pSchema->name);
|
||||
val->cid = pSchema->colId;
|
||||
val->type = pSchema->type;
|
||||
|
||||
|
@ -1321,7 +1322,11 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, TdFilePtr fp, STableDataB
|
|||
|
||||
static int32_t parseDataFromFile(SInsertParseContext* pCxt, SToken filePath, STableDataBlocks* dataBuf) {
|
||||
char filePathStr[TSDB_FILENAME_LEN] = {0};
|
||||
strncpy(filePathStr, filePath.z, filePath.n);
|
||||
if (TK_NK_STRING == filePath.type) {
|
||||
trimString(filePath.z, filePath.n, filePathStr, sizeof(filePathStr));
|
||||
} else {
|
||||
strncpy(filePathStr, filePath.z, filePath.n);
|
||||
}
|
||||
TdFilePtr fp = taosOpenFile(filePathStr, TD_FILE_READ | TD_FILE_STREAM);
|
||||
if (NULL == fp) {
|
||||
return TAOS_SYSTEM_ERROR(errno);
|
||||
|
@ -1802,8 +1807,8 @@ int32_t qBuildStmtOutput(SQuery* pQuery, SHashObj* pVgHash, SHashObj* pBlockHash
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName, TAOS_MULTI_BIND* bind,
|
||||
char* msgBuf, int32_t msgBufLen) {
|
||||
int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const char* sTableName, char* tName,
|
||||
TAOS_MULTI_BIND* bind, char* msgBuf, int32_t msgBufLen) {
|
||||
STableDataBlocks* pDataBlock = (STableDataBlocks*)pBlock;
|
||||
SMsgBuf pBuf = {.buf = msgBuf, .len = msgBufLen};
|
||||
SParsedDataColInfo* tags = (SParsedDataColInfo*)boundTags;
|
||||
|
@ -1854,7 +1859,7 @@ int32_t qBindStmtTagsValue(void* pBlock, void* boundTags, int64_t suid, const ch
|
|||
}
|
||||
} else {
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
|
||||
val.pData = (uint8_t*)bind[c].buffer;
|
||||
val.nData = colLen;
|
||||
|
@ -2245,7 +2250,8 @@ static int32_t smlBoundColumnData(SArray* cols, SParsedDataColInfo* pColList, SS
|
|||
* @param msg
|
||||
* @return int32_t
|
||||
*/
|
||||
static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* pSchema, STag** ppTag, SArray** tagName, SMsgBuf* msg) {
|
||||
static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* pSchema, STag** ppTag, SArray** tagName,
|
||||
SMsgBuf* msg) {
|
||||
SArray* pTagArray = taosArrayInit(tags->numOfBound, sizeof(STagVal));
|
||||
if (!pTagArray) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -2262,7 +2268,7 @@ static int32_t smlBuildTagRow(SArray* cols, SParsedDataColInfo* tags, SSchema* p
|
|||
|
||||
taosArrayPush(*tagName, pTagSchema->name);
|
||||
STagVal val = {.cid = pTagSchema->colId, .type = pTagSchema->type};
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
// strcpy(val.colName, pTagSchema->name);
|
||||
if (pTagSchema->type == TSDB_DATA_TYPE_BINARY) {
|
||||
val.pData = (uint8_t*)kv->value;
|
||||
val.nData = kv->length;
|
||||
|
@ -2318,7 +2324,7 @@ int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols
|
|||
buildInvalidOperationMsg(&pBuf, "bound tags error");
|
||||
return ret;
|
||||
}
|
||||
STag* pTag = NULL;
|
||||
STag* pTag = NULL;
|
||||
SArray* tagName = NULL;
|
||||
ret = smlBuildTagRow(tags, &smlHandle->tableExecHandle.tags, pTagsSchema, &pTag, &tagName, &pBuf);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
|
@ -2402,9 +2408,9 @@ int32_t smlBindData(void* handle, SArray* tags, SArray* colsSchema, SArray* cols
|
|||
} else {
|
||||
int32_t colLen = kv->length;
|
||||
if (pColSchema->type == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
// uError("SML:data before:%ld, precision:%d", kv->i, pTableMeta->tableInfo.precision);
|
||||
// uError("SML:data before:%ld, precision:%d", kv->i, pTableMeta->tableInfo.precision);
|
||||
kv->i = convertTimePrecision(kv->i, TSDB_TIME_PRECISION_NANO, pTableMeta->tableInfo.precision);
|
||||
// uError("SML:data after:%ld, precision:%d", kv->i, pTableMeta->tableInfo.precision);
|
||||
// uError("SML:data after:%ld, precision:%d", kv->i, pTableMeta->tableInfo.precision);
|
||||
}
|
||||
|
||||
if (IS_VAR_DATA_TYPE(kv->type)) {
|
||||
|
|
|
@ -1089,7 +1089,7 @@ static int32_t translateScanPseudoColumnFunc(STranslateContext* pCxt, SFunctionN
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
if (0 == LIST_LENGTH(pFunc->pParameterList)) {
|
||||
if (!isSelectStmt(pCxt->pCurrStmt) ||
|
||||
if (!isSelectStmt(pCxt->pCurrStmt) || NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable ||
|
||||
QUERY_NODE_REAL_TABLE != nodeType(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_TBNAME);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ bool qIsInsertValuesSql(const char* pStr, size_t length) {
|
|||
pStr += index;
|
||||
index = 0;
|
||||
t = tStrGetToken((char*)pStr, &index, false);
|
||||
if (TK_USING == t.type || TK_VALUES == t.type) {
|
||||
if (TK_USING == t.type || TK_VALUES == t.type || TK_FILE == t.type) {
|
||||
return true;
|
||||
} else if (TK_SELECT == t.type) {
|
||||
return false;
|
||||
|
|
|
@ -444,4 +444,11 @@ TEST_F(ParserSelectTest, withoutFrom) {
|
|||
run("SELECT USER()");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, withoutFromSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT c1", TSDB_CODE_PAR_INVALID_COLUMN);
|
||||
run("SELECT TBNAME", TSDB_CODE_PAR_INVALID_TBNAME);
|
||||
}
|
||||
|
||||
} // namespace ParserTest
|
||||
|
|
|
@ -818,6 +818,8 @@ static int32_t createProjectLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSel
|
|||
|
||||
TSWAP(pProject->node.pLimit, pSelect->pLimit);
|
||||
TSWAP(pProject->node.pSlimit, pSelect->pSlimit);
|
||||
pProject->node.requireDataOrder = DATA_ORDER_LEVEL_NONE;
|
||||
pProject->node.resultDataOrder = DATA_ORDER_LEVEL_NONE;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
|
@ -1346,6 +1348,31 @@ static void setLogicSubplanType(bool hasScan, SLogicSubplan* pSubplan) {
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t adjustLogicNodeDataRequirementImpl(SLogicNode* pNode, EDataOrderLevel requirement) {
|
||||
switch (nodeType(pNode)) {
|
||||
case QUERY_NODE_LOGIC_PLAN_SCAN:
|
||||
case QUERY_NODE_LOGIC_PLAN_JOIN:
|
||||
case QUERY_NODE_LOGIC_PLAN_AGG:
|
||||
case QUERY_NODE_LOGIC_PLAN_PROJECT:
|
||||
case QUERY_NODE_LOGIC_PLAN_VNODE_MODIFY:
|
||||
case QUERY_NODE_LOGIC_PLAN_EXCHANGE:
|
||||
case QUERY_NODE_LOGIC_PLAN_MERGE:
|
||||
case QUERY_NODE_LOGIC_PLAN_WINDOW:
|
||||
case QUERY_NODE_LOGIC_PLAN_FILL:
|
||||
case QUERY_NODE_LOGIC_PLAN_SORT:
|
||||
case QUERY_NODE_LOGIC_PLAN_PARTITION:
|
||||
case QUERY_NODE_LOGIC_PLAN_INDEF_ROWS_FUNC:
|
||||
case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t adjustLogicNodeDataRequirement(SLogicNode* pNode) {
|
||||
return adjustLogicNodeDataRequirementImpl(pNode, DATA_ORDER_LEVEL_NONE);
|
||||
}
|
||||
|
||||
int32_t createLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
|
||||
SLogicPlanContext cxt = {.pPlanCxt = pCxt, .pCurrRoot = NULL, .hasScan = false};
|
||||
|
||||
|
@ -1361,6 +1388,7 @@ int32_t createLogicPlan(SPlanContext* pCxt, SLogicSubplan** pLogicSubplan) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
setLogicNodeParent(pSubplan->pNode);
|
||||
setLogicSubplanType(cxt.hasScan, pSubplan);
|
||||
code = adjustLogicNodeDataRequirement(pSubplan->pNode);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
|
|
@ -1579,6 +1579,34 @@ static bool eliminateProjOptMayBeOptimized(SLogicNode* pNode) {
|
|||
return eliminateProjOptCheckProjColumnNames(pProjectNode);
|
||||
}
|
||||
|
||||
typedef struct CheckNewChildTargetsCxt {
|
||||
SNodeList* pNewChildTargets;
|
||||
bool canUse;
|
||||
} CheckNewChildTargetsCxt;
|
||||
|
||||
static EDealRes eliminateProjOptCanUseNewChildTargetsImpl(SNode* pNode, void* pContext) {
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode)) {
|
||||
CheckNewChildTargetsCxt* pCxt = pContext;
|
||||
SNode* pTarget = NULL;
|
||||
FOREACH(pTarget, pCxt->pNewChildTargets) {
|
||||
if (!nodesEqualNode(pTarget, pNode)) {
|
||||
pCxt->canUse = false;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static bool eliminateProjOptCanUseNewChildTargets(SLogicNode* pChild, SNodeList* pNewChildTargets) {
|
||||
if (NULL == pChild->pConditions) {
|
||||
return true;
|
||||
}
|
||||
CheckNewChildTargetsCxt cxt = {.pNewChildTargets = pNewChildTargets, .canUse = true};
|
||||
nodesWalkExpr(pChild->pConditions, eliminateProjOptCanUseNewChildTargetsImpl, &cxt);
|
||||
return cxt.canUse;
|
||||
}
|
||||
|
||||
static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan,
|
||||
SProjectLogicNode* pProjectNode) {
|
||||
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pProjectNode->node.pChildren, 0);
|
||||
|
@ -1594,8 +1622,13 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
|
|||
}
|
||||
}
|
||||
}
|
||||
nodesDestroyList(pChild->pTargets);
|
||||
pChild->pTargets = pNewChildTargets;
|
||||
if (eliminateProjOptCanUseNewChildTargets(pChild, pNewChildTargets)) {
|
||||
nodesDestroyList(pChild->pTargets);
|
||||
pChild->pTargets = pNewChildTargets;
|
||||
} else {
|
||||
nodesDestroyList(pNewChildTargets);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t code = replaceLogicNode(pLogicSubplan, (SLogicNode*)pProjectNode, pChild);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
@ -2145,8 +2178,8 @@ static bool tagScanMayBeOptimized(SLogicNode* pNode) {
|
|||
}
|
||||
|
||||
SAggLogicNode* pAgg = (SAggLogicNode*)(pNode->pParent);
|
||||
if (NULL == pAgg->pGroupKeys || NULL != pAgg->pAggFuncs ||
|
||||
planOptNodeListHasCol(pAgg->pGroupKeys) || !planOptNodeListHasTbname(pAgg->pGroupKeys)) {
|
||||
if (NULL == pAgg->pGroupKeys || NULL != pAgg->pAggFuncs || planOptNodeListHasCol(pAgg->pGroupKeys) ||
|
||||
!planOptNodeListHasTbname(pAgg->pGroupKeys)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2162,16 +2195,16 @@ static int32_t tagScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubp
|
|||
pScanNode->scanType = SCAN_TYPE_TAG;
|
||||
SNode* pTarget = NULL;
|
||||
FOREACH(pTarget, pScanNode->node.pTargets) {
|
||||
if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)(pTarget))->colId) {
|
||||
ERASE_NODE(pScanNode->node.pTargets);
|
||||
break;
|
||||
}
|
||||
if (PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)(pTarget))->colId) {
|
||||
ERASE_NODE(pScanNode->node.pTargets);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NODES_DESTORY_LIST(pScanNode->pScanCols);
|
||||
|
||||
SLogicNode* pAgg = pScanNode->node.pParent;
|
||||
int32_t code = replaceLogicNode(pLogicSubplan, pAgg, (SLogicNode*)pScanNode);
|
||||
int32_t code = replaceLogicNode(pLogicSubplan, pAgg, (SLogicNode*)pScanNode);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
NODES_CLEAR_LIST(pAgg->pChildren);
|
||||
}
|
||||
|
|
|
@ -974,6 +974,17 @@ static int32_t createInterpFuncPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pCh
|
|||
return code;
|
||||
}
|
||||
|
||||
static bool projectCanMergeDataBlock(SProjectLogicNode* pProject) {
|
||||
if (DATA_ORDER_LEVEL_NONE == pProject->node.resultDataOrder) {
|
||||
return true;
|
||||
}
|
||||
if (1 != LIST_LENGTH(pProject->node.pChildren)) {
|
||||
return false;
|
||||
}
|
||||
SLogicNode* pChild = (SLogicNode*)nodesListGetNode(pProject->node.pChildren, 0);
|
||||
return DATA_ORDER_LEVEL_GLOBAL == pChild->resultDataOrder ? true : false;
|
||||
}
|
||||
|
||||
static int32_t createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren,
|
||||
SProjectLogicNode* pProjectLogicNode, SPhysiNode** pPhyNode) {
|
||||
SProjectPhysiNode* pProject =
|
||||
|
@ -982,6 +993,8 @@ static int32_t createProjectPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChild
|
|||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pProject->mergeDataBlock = projectCanMergeDataBlock(pProjectLogicNode);
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (0 == LIST_LENGTH(pChildren)) {
|
||||
pProject->pProjections = nodesCloneList(pProjectLogicNode->pProjections);
|
||||
|
|
|
@ -55,3 +55,11 @@ TEST_F(PlanSubqeuryTest, withSetOperator) {
|
|||
|
||||
run("SELECT c1 FROM (SELECT c1 FROM t1 UNION SELECT c1 FROM t1)");
|
||||
}
|
||||
|
||||
TEST_F(PlanSubqeuryTest, withFill) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT cnt FROM (SELECT _WSTART ts, COUNT(*) cnt FROM t1 "
|
||||
"WHERE ts > '2022-04-01 00:00:00' and ts < '2022-04-30 23:59:59' INTERVAL(10s) FILL(LINEAR)) "
|
||||
"WHERE ts > '2022-04-06 00:00:00'");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue