diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 4bf0663def..49370876d8 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -214,6 +214,7 @@ typedef struct SRealTableNode { double ratio; SArray* pSmaIndexes; int8_t cacheLastMode; + int8_t stbRewrite; SArray* pTsmas; SArray* tsmaTargetTbVgInfo; // SArray, used for child table or normal table only SArray* tsmaTargetTbInfo; // SArray, used for child table or normal table only diff --git a/source/libs/parser/src/parAstParser.c b/source/libs/parser/src/parAstParser.c index 49be0b8d90..d323d45c81 100644 --- a/source/libs/parser/src/parAstParser.c +++ b/source/libs/parser/src/parAstParser.c @@ -107,6 +107,7 @@ typedef struct SCollectMetaKeyCxt { typedef struct SCollectMetaKeyFromExprCxt { SCollectMetaKeyCxt* pComCxt; bool hasLastRowOrLast; + bool tbnameCollect; int32_t errCode; } SCollectMetaKeyFromExprCxt; @@ -204,6 +205,45 @@ static EDealRes collectMetaKeyFromTempTable(SCollectMetaKeyFromExprCxt* pCxt, ST return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } +static int32_t isTbnameEqCondOperator(SOperatorNode* pOperator, char** ppTableName) { + if (pOperator->opType != OP_TYPE_EQUAL) { + return TSDB_CODE_SUCCESS; + } + + SValueNode* pValueNode = NULL; + if (nodeType(pOperator->pLeft) == QUERY_NODE_FUNCTION && + 0 == strcasecmp(((SFunctionNode*)(pOperator->pLeft))->functionName, "tbname") && + nodeType(pOperator->pRight) == QUERY_NODE_VALUE) { + pValueNode = (SValueNode*)pOperator->pRight; + } else if (nodeType(pOperator->pRight) == QUERY_NODE_FUNCTION && + 0 == strcasecmp(((SFunctionNode*)(pOperator->pRight))->functionName, "tbname") && + nodeType(pOperator->pLeft) == QUERY_NODE_VALUE) { + pValueNode = (SValueNode*)pOperator->pLeft; + } else { + return TSDB_CODE_SUCCESS; + } + + *ppTableName = pValueNode->literal; + + return TSDB_CODE_SUCCESS; +} + +static EDealRes collectMetaKeyFromOperator(SCollectMetaKeyFromExprCxt* pCxt, SOperatorNode* pOpNode) { + if (!pCxt->tbnameCollect) { + return DEAL_RES_CONTINUE; + } + + char* pTableName = NULL; + int32_t code = isTbnameEqCondOperator((SOperatorNode*)pOpNode, &pTableName); + if (TSDB_CODE_SUCCESS != code) return DEAL_RES_CONTINUE; + if (pTableName) { + SSelectStmt* pSelect = (SSelectStmt*)pCxt->pComCxt->pStmt; + pCxt->errCode = collectMetaKeyFromRealTableImpl(pCxt->pComCxt, ((SRealTableNode*)pSelect->pFromTable)->table.dbName, pTableName, AUTH_TYPE_READ); + } + + return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; +} + static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) { SCollectMetaKeyFromExprCxt* pCxt = pContext; switch (nodeType(pNode)) { @@ -213,6 +253,8 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) { return collectMetaKeyFromRealTable(pCxt, (SRealTableNode*)pNode); case QUERY_NODE_TEMP_TABLE: return collectMetaKeyFromTempTable(pCxt, (STempTableNode*)pNode); + case QUERY_NODE_OPERATOR: + return collectMetaKeyFromOperator(pCxt, (SOperatorNode*)pNode); default: break; } @@ -220,7 +262,7 @@ static EDealRes collectMetaKeyFromExprImpl(SNode* pNode, void* pContext) { } static int32_t collectMetaKeyFromExprs(SCollectMetaKeyCxt* pCxt, SNodeList* pList) { - SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .errCode = TSDB_CODE_SUCCESS}; + SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .errCode = TSDB_CODE_SUCCESS, .tbnameCollect = false}; nodesWalkExprs(pList, collectMetaKeyFromExprImpl, &cxt); return cxt.errCode; } @@ -245,6 +287,9 @@ static int32_t reserveDbCfgForLastRow(SCollectMetaKeyCxt* pCxt, SNode* pTable) { static int32_t collectMetaKeyFromSelect(SCollectMetaKeyCxt* pCxt, SSelectStmt* pStmt) { SCollectMetaKeyFromExprCxt cxt = {.pComCxt = pCxt, .hasLastRowOrLast = false, .errCode = TSDB_CODE_SUCCESS}; + if (pStmt->pFromTable && QUERY_NODE_REAL_TABLE == nodeType(pStmt->pFromTable)) { + cxt.tbnameCollect = true; + } nodesWalkSelectStmt(pStmt, SQL_CLAUSE_FROM, collectMetaKeyFromExprImpl, &cxt); if (TSDB_CODE_SUCCESS == cxt.errCode && cxt.hasLastRowOrLast) { cxt.errCode = reserveDbCfgForLastRow(pCxt, pStmt->pFromTable); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index e5e47a6c9b..5587fd656f 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1275,7 +1275,7 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; int32_t nums = pMeta->tableInfo.numOfColumns + - (igTags ? 0 : ((TSDB_SUPER_TABLE == pMeta->tableType) ? pMeta->tableInfo.numOfTags : 0)); + (igTags ? 0 : ((TSDB_SUPER_TABLE == pMeta->tableType || ((SRealTableNode*)pTable)->stbRewrite) ? pMeta->tableInfo.numOfTags : 0)); for (int32_t i = 0; i < nums; ++i) { if (invisibleColumn(pCxt->pParseCxt->enableSysInfo, pMeta->tableType, pMeta->schema[i].flags)) { pCxt->pParseCxt->hasInvisibleCol = true; @@ -5964,6 +5964,7 @@ static int32_t isOperatorEqTbnameCond(STranslateContext* pCxt, SOperatorNode* pO *pRet = false; return TSDB_CODE_SUCCESS; } + SFunctionNode* pTbnameFunc = NULL; SValueNode* pValueNode = NULL; if (nodeType(pOperator->pLeft) == QUERY_NODE_FUNCTION && @@ -6041,7 +6042,6 @@ static int32_t isOperatorTbnameInCond(STranslateContext* pCxt, SOperatorNode* pO static int32_t findEqCondTbNameInOperatorNode(STranslateContext* pCxt, SNode* pWhere, SEqCondTbNameTableInfo* pInfo, bool* pRet) { int32_t code = TSDB_CODE_SUCCESS; char* pTableAlias = NULL; - char* pTbNameVal = NULL; bool eqTbnameCond = false, tbnameInCond = false; code = isOperatorEqTbnameCond(pCxt, (SOperatorNode*)pWhere, &pTableAlias, &pInfo->aTbnames, &eqTbnameCond); if (TSDB_CODE_SUCCESS == code) { @@ -6222,12 +6222,40 @@ static void findVgroupsFromEqualTbname(STranslateContext* pCxt, SArray* aTbnames } } +static int32_t replaceToChildTableQuery(STranslateContext* pCxt, SEqCondTbNameTableInfo* pInfo) { + SName snameTb; + char* tbName = taosArrayGetP(pInfo->aTbnames, 0); + (void)toName(pCxt->pParseCxt->acctId, pInfo->pRealTable->table.dbName, tbName, &snameTb); + + STableMeta* pMeta = NULL; + TAOS_CHECK_RETURN(catalogGetCachedTableMeta(pCxt->pParseCxt->pCatalog, &snameTb, &pMeta)); + if (NULL == pMeta || TSDB_CHILD_TABLE != pMeta->tableType || pMeta->suid != pInfo->pRealTable->pMeta->suid) { + goto _return; + } + + pInfo->pRealTable->pMeta->uid = pMeta->uid; + pInfo->pRealTable->pMeta->vgId = pMeta->vgId; + pInfo->pRealTable->pMeta->tableType = pMeta->tableType; + tstrncpy(pInfo->pRealTable->table.tableName, tbName, sizeof(pInfo->pRealTable->table.tableName)); + + pInfo->pRealTable->stbRewrite = true; + +_return: + + taosMemoryFree(pMeta); + return TSDB_CODE_SUCCESS; +} + static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* pSelect, SArray* aTables) { int32_t code = TSDB_CODE_SUCCESS; - for (int i = 0; i < taosArrayGetSize(aTables); ++i) { - SEqCondTbNameTableInfo* pInfo = taosArrayGet(aTables, i); - int32_t nTbls = taosArrayGetSize(pInfo->aTbnames); + int32_t aTableNum = taosArrayGetSize(aTables); + int32_t nTbls = 0; + bool stableQuery = false; + SEqCondTbNameTableInfo* pInfo = NULL; + for (int i = 0; i < aTableNum; ++i) { + pInfo = taosArrayGet(aTables, i); int32_t numOfVgs = pInfo->pRealTable->pVgroupList->numOfVgroups; + nTbls = taosArrayGetSize(pInfo->aTbnames); SVgroupsInfo* vgsInfo = taosMemoryMalloc(sizeof(SVgroupsInfo) + nTbls * sizeof(SVgroupInfo)); findVgroupsFromEqualTbname(pCxt, pInfo->aTbnames, pInfo->pRealTable->table.dbName, numOfVgs, vgsInfo); @@ -6237,6 +6265,7 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* } else { taosMemoryFree(vgsInfo); } + stableQuery = pInfo->pRealTable->pMeta->tableType == TSDB_SUPER_TABLE; vgsInfo = NULL; if (pInfo->pRealTable->pTsmas) { @@ -6276,7 +6305,12 @@ static int32_t setEqualTbnameTableVgroups(STranslateContext* pCxt, SSelectStmt* } } } - return TSDB_CODE_SUCCESS; + + if (TSDB_CODE_SUCCESS == code && 1 == aTableNum && 1 == nTbls && stableQuery) { + code = replaceToChildTableQuery(pCxt, pInfo); + } + + return code; } static int32_t setTableVgroupsFromEqualTbnameCond(STranslateContext* pCxt, SSelectStmt* pSelect) {