diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 82f51f70c14bcf5dda8615d6ba2aa0ecd45fe6e2..4e2d75a79f0dd730939e8e15379eb1ebb506a4f9 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -268,6 +268,10 @@ static bool isSelectFunc(const SNode* pNode) { return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsSelectFunc(((SFunctionNode*)pNode)->funcId)); } +static bool isTimelineFunc(const SNode* pNode) { + return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId)); +} + static bool isDistinctOrderBy(STranslateContext* pCxt) { return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct); } @@ -672,38 +676,6 @@ static int32_t rewriteCountStar(STranslateContext* pCxt, SFunctionNode* pCount) return code; } -static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* pTable, SNode** pPrimaryKey) { - SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN); - if (NULL == pCol) { - return TSDB_CODE_OUT_OF_MEMORY; - } - if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { - setColumnInfoBySchema((SRealTableNode*)pTable, ((SRealTableNode*)pTable)->pMeta->schema, false, pCol); - } else { - // todo - } - *pPrimaryKey = (SNode*)pCol; - return TSDB_CODE_SUCCESS; -} - -static int32_t createPrimaryKeyCol(STranslateContext* pCxt, SNode** pPrimaryKey) { - STableNode* pTable = NULL; - int32_t code = findTable(pCxt, NULL, &pTable); - if (TSDB_CODE_SUCCESS == code) { - code = createPrimaryKeyColByTable(pCxt, pTable, pPrimaryKey); - } - return code; -} - -static int32_t rewriteTimelineFunc(STranslateContext* pCxt, SFunctionNode* pFunc) { - SNode* pPrimaryKey = NULL; - int32_t code = createPrimaryKeyCol(pCxt, &pPrimaryKey); - if (TSDB_CODE_SUCCESS == code) { - code = nodesListMakeStrictAppend(&pFunc->pParameterList, pPrimaryKey); - } - return code; -} - static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) { SFmGetFuncInfoParam param = {.pCtg = pCxt->pParseCxt->pCatalog, .pRpc = pCxt->pParseCxt->pTransporter, @@ -727,9 +699,6 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) pCxt->errCode = rewriteCountStar(pCxt, pFunc); } } - if (TSDB_CODE_SUCCESS == pCxt->errCode && fmIsTimelineFunc(pFunc->funcId)) { - pCxt->errCode = rewriteTimelineFunc(pCxt, pFunc); - } return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR; } @@ -1641,6 +1610,48 @@ static int32_t checkLimit(STranslateContext* pCxt, SSelectStmt* pSelect) { return TSDB_CODE_SUCCESS; } +static int32_t createPrimaryKeyColByTable(STranslateContext* pCxt, STableNode* pTable, SNode** pPrimaryKey) { + SColumnNode* pCol = nodesMakeNode(QUERY_NODE_COLUMN); + if (NULL == pCol) { + return TSDB_CODE_OUT_OF_MEMORY; + } + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + setColumnInfoBySchema((SRealTableNode*)pTable, ((SRealTableNode*)pTable)->pMeta->schema, false, pCol); + } else { + // todo + } + *pPrimaryKey = (SNode*)pCol; + return TSDB_CODE_SUCCESS; +} + +static int32_t createPrimaryKeyCol(STranslateContext* pCxt, SNode** pPrimaryKey) { + STableNode* pTable = NULL; + int32_t code = findTable(pCxt, NULL, &pTable); + if (TSDB_CODE_SUCCESS == code) { + code = createPrimaryKeyColByTable(pCxt, pTable, pPrimaryKey); + } + return code; +} + +static EDealRes rewriteTimelineFuncImpl(SNode* pNode, void* pContext) { + STranslateContext* pCxt = pContext; + if (isTimelineFunc(pNode)) { + SFunctionNode* pFunc = (SFunctionNode*)pNode; + SNode* pPrimaryKey = NULL; + pCxt->errCode = createPrimaryKeyCol(pCxt, &pPrimaryKey); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pCxt->errCode = nodesListMakeStrictAppend(&pFunc->pParameterList, pPrimaryKey); + } + return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR; + } + return DEAL_RES_CONTINUE; +} + +static int32_t rewriteTimelineFunc(STranslateContext* pCxt, SSelectStmt* pSelect) { + nodesWalkSelectStmt(pSelect, SQL_CLAUSE_FROM, rewriteTimelineFuncImpl, pCxt); + return pCxt->errCode; +} + static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) { pCxt->pCurrStmt = pSelect; int32_t code = translateFrom(pCxt, pSelect); @@ -1671,6 +1682,9 @@ static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) { if (TSDB_CODE_SUCCESS == code) { code = checkLimit(pCxt, pSelect); } + if (TSDB_CODE_SUCCESS == code) { + code = rewriteTimelineFunc(pCxt, pSelect); + } return code; } diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp index 4e0d2851f673abeb19f8d187c12cef1e8ad8987e..5a385ba25e10677f77d88fb74cbd440b2cb21a8a 100644 --- a/source/libs/parser/test/parSelectTest.cpp +++ b/source/libs/parser/test/parSelectTest.cpp @@ -67,27 +67,29 @@ TEST_F(ParserSelectTest, condition) { TEST_F(ParserSelectTest, pseudoColumn) { useDb("root", "test"); - run("SELECT _wstartts, _wendts, COUNT(*) FROM t1 INTERVAL(10s)"); + run("SELECT _WSTARTTS, _WENDTS, COUNT(*) FROM t1 INTERVAL(10s)"); } TEST_F(ParserSelectTest, multiResFunc) { useDb("root", "test"); - run("SELECT last(*), first(*), last_row(*) FROM t1"); + run("SELECT LAST(*), FIRST(*), LAST_ROW(*) FROM t1"); - run("SELECT last(c1, c2), first(t1.*), last_row(c3) FROM t1"); + run("SELECT LAST(c1, c2), FIRST(t1.*), LAST_ROW(c3) FROM t1"); - run("SELECT last(t2.*), first(t1.c1, t2.*), last_row(t1.*, t2.*) FROM st1s1 t1, st1s2 t2 WHERE t1.ts = t2.ts"); + run("SELECT LAST(t2.*), FIRST(t1.c1, t2.*), LAST_ROW(t1.*, t2.*) FROM st1s1 t1, st1s2 t2 WHERE t1.ts = t2.ts"); } TEST_F(ParserSelectTest, timelineFunc) { useDb("root", "test"); - run("SELECT last(*), first(*) FROM t1"); + run("SELECT LAST(*), FIRST(*) FROM t1"); - run("SELECT last(*), first(*) FROM t1 GROUP BY c1"); + run("SELECT FIRST(ts), FIRST(c1), FIRST(c2), FIRST(c3) FROM t1"); - run("SELECT last(*), first(*) FROM t1 INTERVAL(10s)"); + run("SELECT LAST(*), FIRST(*) FROM t1 GROUP BY c1"); + + run("SELECT LAST(*), FIRST(*) FROM t1 INTERVAL(10s)"); run("SELECT diff(c1) FROM t1"); } diff --git a/tests/system-test/2-query/distinct.py b/tests/system-test/2-query/distinct.py index a82f3a6f59f243ffc6eafe6f36b1bdcdb9b9e12f..8f27fe4db6e74f89482c6aa6858105f83f6b884f 100644 --- a/tests/system-test/2-query/distinct.py +++ b/tests/system-test/2-query/distinct.py @@ -109,9 +109,9 @@ class TDTestCase: # tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 interval(1d) ") tdSql.error("select distinct c1, c2 from t1 where c1 > 3 interval(1d) ") # tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 interval(1d) fill(next)") - tdSql.error("select distinct c1, c2 from t1 where c1 > 3 interval(1d) fill(next)") + # tdSql.error("select distinct c1, c2 from t1 where c1 > 3 interval(1d) fill(next)") # tdSql.error("select distinct c1, c2 from stb1 where ts > now-10d and ts < now interval(1d) fill(next)") - tdSql.error("select distinct c1, c2 from t1 where ts > now-10d and ts < now interval(1d) fill(next)") + # tdSql.error("select distinct c1, c2 from t1 where ts > now-10d and ts < now interval(1d) fill(next)") # tdSql.error("select distinct c1, c2 from stb1 where c1 > 3 slimit 1") # tdSql.error("select distinct c1, c2 from t1 where c1 > 3 slimit 1") # tdSql.query(f"select distinct c1, c2 from stb1 where c1 between {tbnum-2} and {tbnum} ")