diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h index 960263a331..fb9f49889f 100644 --- a/include/libs/nodes/cmdnodes.h +++ b/include/libs/nodes/cmdnodes.h @@ -595,7 +595,7 @@ typedef struct STSMAOptions { SNodeList* pFuncs; SNodeList* pCols; SNode* pInterval; - uint8_t tsPrecision; + uint8_t tsPrecision; } STSMAOptions; typedef struct SCreateTSMAStmt { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 9e9183dee9..b41c753d58 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -7468,6 +7468,7 @@ typedef struct SSampleAstInfo { STableMeta* pRollupTableMeta; bool createSmaIndex; SNodeList* pTags; + SNode* pSubTable; } SSampleAstInfo; static int32_t buildTableForSampleAst(SSampleAstInfo* pInfo, SNode** pOutput) { @@ -7567,6 +7568,7 @@ static int32_t buildSampleAst(STranslateContext* pCxt, SSampleAstInfo* pInfo, ch code = buildProjectsForSampleAst(pInfo, &pSelect->pProjectionList); } if (TSDB_CODE_SUCCESS == code) { + TSWAP(pInfo->pSubTable, pSelect->pSubtable); TSWAP(pInfo->pTags, pSelect->pTags); TSWAP(pSelect->pPartitionByList, pInfo->pPartitionByList); code = buildIntervalForSampleAst(pInfo, &pSelect->pWindow); @@ -10432,6 +10434,35 @@ static int32_t buildTSMAAst(STranslateContext* pCxt, SCreateTSMAStmt* pStmt, SMC } else { code = TSDB_CODE_OUT_OF_MEMORY; } + if (code == TSDB_CODE_SUCCESS) { + SFunctionNode* pConcatFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); + SValueNode* pValue = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + if (!pConcatFunc || !pValue) code = TSDB_CODE_OUT_OF_MEMORY; + if (code == TSDB_CODE_SUCCESS) { + pValue->literal = taosMemoryCalloc(1, TSDB_TABLE_FNAME_LEN); + if (!pValue->literal) code = TSDB_CODE_OUT_OF_MEMORY; + } + if (code == TSDB_CODE_SUCCESS) { + strcpy(pValue->literal, pReq->name); + int32_t len = taosCreateMD5Hash(pValue->literal, strlen(pValue->literal)); + pValue->literal[len] = '_'; + snprintf(pConcatFunc->functionName, TSDB_FUNC_NAME_LEN, "concat"); + pValue->node.resType.type = TSDB_DATA_TYPE_VARCHAR; + pValue->node.resType.bytes = strlen(pValue->literal); + pValue->isDuration = false; + pValue->isNull = false; + code = nodesListMakeAppend(&pConcatFunc->pParameterList, (SNode*)pValue); + } + if (code == TSDB_CODE_SUCCESS) { + code = nodesListStrictAppend(pConcatFunc->pParameterList, nodesCloneNode((SNode*)pTbnameFunc)); + } + if (code) { + nodesDestroyNode((SNode*)pConcatFunc); + nodesDestroyNode((SNode*)pValue); + } else { + info.pSubTable = (SNode*)pConcatFunc; + } + } } if (TSDB_CODE_SUCCESS == code) { // append partition by tags diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 9ce404fd7a..6f797638b1 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -6139,7 +6139,7 @@ SNodeList* tsmaOptCreateTsmaScanCols(const STSMAOptUsefulTsma* pTsma, const SNod return pScanCols; } -static int32_t tsmaOptRewriteTag(STSMAOptCtx* pTsmaOptCtx, const STSMAOptUsefulTsma* pTsma, SColumnNode* pTagCol) { +static int32_t tsmaOptRewriteTag(const STSMAOptCtx* pTsmaOptCtx, const STSMAOptUsefulTsma* pTsma, SColumnNode* pTagCol) { bool found = false; if (pTagCol->colType != COLUMN_TYPE_TAG) return 0; for (int32_t i = 0; i < pTsma->pTsma->pTags->size; ++i) { @@ -6158,12 +6158,44 @@ static int32_t tsmaOptRewriteTag(STSMAOptCtx* pTsmaOptCtx, const STSMAOptUsefulT return 0; } -static int32_t tsmaOptRewriteTbname(STSMAOptCtx* pTsmaOptCtx, SFunctionNode* pTbNameNode) { +static int32_t tsmaOptRewriteTbname(const STSMAOptCtx* pTsmaOptCtx, SNode** pTbNameNode, bool withTsma) { int32_t code = 0; - + if (withTsma) { + // TODO test child tbname too long + // if with tsma, we replace func tbname with concat(tbname, '') + } else { + // if no tsma, we replace func tbname with concat('dbname_tsmaname', tbname) + } return code; } +struct TsmaOptRewriteCtx { + const STSMAOptCtx* pTsmaOptCtx; + const STSMAOptUsefulTsma* pTsma; + bool rewriteTag; + bool rewriteTbname; + int32_t code; +}; + +EDealRes tsmaOptRewriter(SNode** ppNode, void* ctx) { + SNode* pNode = *ppNode; + int32_t code = 0; + struct TsmaOptRewriteCtx* pCtx = ctx; + if (pCtx->rewriteTag && nodeType(pNode) == QUERY_NODE_COLUMN && ((SColumnNode*)pNode)->colType == COLUMN_TYPE_TAG) { + code = tsmaOptRewriteTag(pCtx->pTsmaOptCtx, pCtx->pTsma, (SColumnNode*)pNode); + } else if (pCtx->rewriteTbname && nodeType(pNode) == QUERY_NODE_FUNCTION){ + SFunctionNode* pFunc = (SFunctionNode*)pNode; + if (pFunc->funcType == FUNCTION_TYPE_TBNAME) { + code = tsmaOptRewriteTbname(pCtx->pTsmaOptCtx, ppNode, pCtx->pTsma); + } + } + if (code) { + pCtx->code = code; + return DEAL_RES_ERROR; + } + return DEAL_RES_CONTINUE; +} + static int32_t tsmaOptRewriteScan(STSMAOptCtx* pTsmaOptCtx, SScanLogicNode* pNewScan, const STSMAOptUsefulTsma* pTsma) { SNode* pNode; int32_t code = 0; @@ -6210,20 +6242,34 @@ static int32_t tsmaOptRewriteScan(STSMAOptCtx* pTsmaOptCtx, SScanLogicNode* pNew FOREACH(pNode, pNewScan->pScanPseudoCols) { if (nodeType(pNode) == QUERY_NODE_COLUMN) { code = tsmaOptRewriteTag(pTsmaOptCtx, pTsma, (SColumnNode*)pNode); - } else if (nodeType(pNode) == QUERY_NODE_FUNCTION) { - code = tsmaOptRewriteTbname(pTsmaOptCtx, (SFunctionNode*)pNode); } } } if (code == TSDB_CODE_SUCCESS) { FOREACH(pNode, pNewScan->pGroupTags) { - if (nodeType(pNode) == QUERY_NODE_COLUMN) { - code = tsmaOptRewriteTag(pTsmaOptCtx, pTsma, (SColumnNode*)pNode); - } else if (nodeType(pNode) == QUERY_NODE_FUNCTION) { - code = tsmaOptRewriteTbname(pTsmaOptCtx, (SFunctionNode*)pNode); + // TODO rewrite tag and tbname recursively + struct TsmaOptRewriteCtx ctx = { + .pTsmaOptCtx = pTsmaOptCtx, .pTsma = pTsma, .rewriteTag = true, .rewriteTbname = true, .code = 0}; + nodesRewriteExpr(&pNode, tsmaOptRewriter, &ctx); + if (ctx.code) { + code = ctx.code; + } else { + REPLACE_NODE(pNode); } } } + } else { + FOREACH(pNode, pNewScan->pGroupTags) { + // rewrite tbname recursively + struct TsmaOptRewriteCtx ctx = { + .pTsmaOptCtx = pTsmaOptCtx, .pTsma = NULL, .rewriteTag = false, .rewriteTbname = true, .code = 0}; + nodesRewriteExpr(&pNode, tsmaOptRewriter, &ctx); + if (ctx.code) { + code = ctx.code; + } else { + REPLACE_NODE(pNode); + } + } } return code; }