feat: sql commadn 'select max(c1), c2 from t2'
This commit is contained in:
parent
f99c01e66e
commit
3b4f9b91cf
|
@ -113,6 +113,9 @@ typedef enum EFunctionType {
|
|||
FUNCTION_TYPE_WENDTS,
|
||||
FUNCTION_TYPE_WDURATION,
|
||||
|
||||
// internal function
|
||||
FUNCTION_TYPE_SELECT_VALUE,
|
||||
|
||||
// user defined funcion
|
||||
FUNCTION_TYPE_UDF = 10000
|
||||
} EFunctionType;
|
||||
|
@ -141,6 +144,7 @@ bool fmIsScalarFunc(int32_t funcId);
|
|||
bool fmIsNonstandardSQLFunc(int32_t funcId);
|
||||
bool fmIsStringFunc(int32_t funcId);
|
||||
bool fmIsDatetimeFunc(int32_t funcId);
|
||||
bool fmIsSelectFunc(int32_t funcId);
|
||||
bool fmIsTimelineFunc(int32_t funcId);
|
||||
bool fmIsTimeorderFunc(int32_t funcId);
|
||||
bool fmIsPseudoColumnFunc(int32_t funcId);
|
||||
|
|
|
@ -39,6 +39,7 @@ extern "C" {
|
|||
#define FUNC_MGT_DYNAMIC_SCAN_OPTIMIZED FUNC_MGT_FUNC_CLASSIFICATION_MASK(10)
|
||||
#define FUNC_MGT_MULTI_RES_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(11)
|
||||
#define FUNC_MGT_SCAN_PC_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(12)
|
||||
#define FUNC_MGT_SELECT_FUNC FUNC_MGT_FUNC_CLASSIFICATION_MASK(13)
|
||||
|
||||
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
||||
|
||||
|
|
|
@ -438,6 +438,11 @@ static int32_t translateToJson(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t translateSelectValue(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||
pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||
{
|
||||
|
@ -465,7 +470,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "min",
|
||||
.type = FUNCTION_TYPE_MIN,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED | FUNC_MGT_SELECT_FUNC,
|
||||
.translateFunc = translateInOutNum,
|
||||
.dataRequiredFunc = statisDataRequired,
|
||||
.getEnvFunc = getMinmaxFuncEnv,
|
||||
|
@ -476,7 +481,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
{
|
||||
.name = "max",
|
||||
.type = FUNCTION_TYPE_MAX,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED | FUNC_MGT_SELECT_FUNC,
|
||||
.translateFunc = translateInOutNum,
|
||||
.dataRequiredFunc = statisDataRequired,
|
||||
.getEnvFunc = getMinmaxFuncEnv,
|
||||
|
@ -974,6 +979,16 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
|||
.initFunc = NULL,
|
||||
.sprocessFunc = toJsonFunction,
|
||||
.finalizeFunc = NULL
|
||||
},
|
||||
{
|
||||
.name = "_select_value",
|
||||
.type = FUNCTION_TYPE_SELECT_VALUE,
|
||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SELECT_FUNC,
|
||||
.translateFunc = translateSelectValue,
|
||||
.getEnvFunc = NULL,
|
||||
.initFunc = NULL,
|
||||
.sprocessFunc = NULL,
|
||||
.finalizeFunc = NULL
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
|
|
@ -145,6 +145,8 @@ bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MG
|
|||
|
||||
bool fmIsScalarFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCALAR_FUNC); }
|
||||
|
||||
bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SELECT_FUNC); }
|
||||
|
||||
bool fmIsTimelineFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_TIMELINE_FUNC); }
|
||||
|
||||
bool fmIsPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_PSEUDO_COLUMN_FUNC); }
|
||||
|
|
|
@ -256,6 +256,22 @@ static void destroyTranslateContext(STranslateContext* pCxt) {
|
|||
taosHashCleanup(pCxt->pTables);
|
||||
}
|
||||
|
||||
static bool isAliasColumn(const SNode* pNode) {
|
||||
return (QUERY_NODE_COLUMN == nodeType(pNode) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]));
|
||||
}
|
||||
|
||||
static bool isAggFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isSelectFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsSelectFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isDistinctOrderBy(STranslateContext* pCxt) {
|
||||
return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct);
|
||||
}
|
||||
|
||||
static bool belongTable(const char* currentDb, const SColumnNode* pCol, const STableNode* pTable) {
|
||||
int cmp = 0;
|
||||
if ('\0' != pCol->dbName[0]) {
|
||||
|
@ -617,7 +633,7 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
|||
}
|
||||
|
||||
static EDealRes haveAggFunction(SNode* pNode, void* pContext) {
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) {
|
||||
if (isAggFunc(pNode)) {
|
||||
*((bool*)pContext) = true;
|
||||
return DEAL_RES_END;
|
||||
}
|
||||
|
@ -758,18 +774,6 @@ static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) {
|
|||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
static bool isAliasColumn(const SNode* pNode) {
|
||||
return (QUERY_NODE_COLUMN == nodeType(pNode) && ('\0' == ((SColumnNode*)pNode)->tableAlias[0]));
|
||||
}
|
||||
|
||||
static bool isAggFunc(const SNode* pNode) {
|
||||
return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId));
|
||||
}
|
||||
|
||||
static bool isDistinctOrderBy(STranslateContext* pCxt) {
|
||||
return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct);
|
||||
}
|
||||
|
||||
static SNodeList* getGroupByList(STranslateContext* pCxt) {
|
||||
if (isDistinctOrderBy(pCxt)) {
|
||||
return pCxt->pCurrStmt->pProjectionList;
|
||||
|
@ -791,28 +795,71 @@ static int32_t getGroupByErrorCode(STranslateContext* pCxt) {
|
|||
return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION;
|
||||
}
|
||||
|
||||
static EDealRes doCheckExprForGroupBy(SNode* pNode, void* pContext) {
|
||||
STranslateContext* pCxt = (STranslateContext*)pContext;
|
||||
if (!nodesIsExprNode(pNode) || isAliasColumn(pNode)) {
|
||||
typedef struct SCheckExprForGroupByCxt {
|
||||
STranslateContext* pTranslateCxt;
|
||||
int32_t selectFuncNum;
|
||||
bool hasSelectValFunc;
|
||||
} SCheckExprForGroupByCxt;
|
||||
|
||||
static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSelectValFunc, SNode** pNode) {
|
||||
SFunctionNode* pFunc = nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||
if (NULL == pFunc) {
|
||||
pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return DEAL_RES_ERROR;
|
||||
}
|
||||
strcpy(pFunc->functionName, "_select_value");
|
||||
pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
translateFunction(pCxt, pFunc);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode) {
|
||||
*pNode = (SNode*)pFunc;
|
||||
if (NULL != pHasSelectValFunc) {
|
||||
*pHasSelectValFunc = true;
|
||||
}
|
||||
} else {
|
||||
nodesDestroyNode(pFunc);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR;
|
||||
}
|
||||
|
||||
static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
|
||||
SCheckExprForGroupByCxt* pCxt = (SCheckExprForGroupByCxt*)pContext;
|
||||
if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) {
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
if (isAggFunc(pNode) && !isDistinctOrderBy(pCxt)) {
|
||||
pCxt->selectFuncNum += isSelectFunc(*pNode) ? 1 : 0;
|
||||
if (pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) {
|
||||
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
|
||||
}
|
||||
if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
SNode* pGroupNode;
|
||||
FOREACH(pGroupNode, getGroupByList(pCxt)) {
|
||||
if (nodesEqualNode(getGroupByNode(pGroupNode), pNode)) {
|
||||
FOREACH(pGroupNode, getGroupByList(pCxt->pTranslateCxt)) {
|
||||
if (nodesEqualNode(getGroupByNode(pGroupNode), *pNode)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
}
|
||||
if (QUERY_NODE_COLUMN == nodeType(pNode) || (isAggFunc(pNode) && isDistinctOrderBy(pCxt))) {
|
||||
return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt));
|
||||
if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
if (pCxt->selectFuncNum > 1) {
|
||||
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
|
||||
} else {
|
||||
return rewriteColToSelectValFunc(pCxt->pTranslateCxt, &pCxt->hasSelectValFunc, pNode);
|
||||
}
|
||||
}
|
||||
if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) {
|
||||
return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt));
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode* pNode) {
|
||||
nodesWalkExpr(pNode, doCheckExprForGroupBy, pCxt);
|
||||
static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) {
|
||||
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false};
|
||||
nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
}
|
||||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
|
@ -820,7 +867,29 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
|
|||
if (NULL == getGroupByList(pCxt)) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
nodesWalkExprs(pList, doCheckExprForGroupBy, pCxt);
|
||||
SCheckExprForGroupByCxt cxt = {.pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false};
|
||||
nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt);
|
||||
if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt));
|
||||
}
|
||||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
|
||||
if (isAggFunc(*pNode)) {
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
if (QUERY_NODE_COLUMN == nodeType(*pNode)) {
|
||||
return rewriteColToSelectValFunc((STranslateContext*)pContext, NULL, pNode);
|
||||
}
|
||||
return DEAL_RES_CONTINUE;
|
||||
}
|
||||
|
||||
static int32_t rewriteColsToSelectValFunc(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
nodesRewriteExprs(pSelect->pProjectionList, rewriteColsToSelectValFuncImpl, pCxt);
|
||||
if (TSDB_CODE_SUCCESS == pCxt->errCode && !pSelect->isDistinct) {
|
||||
nodesRewriteExprs(pSelect->pOrderByList, rewriteColsToSelectValFuncImpl, pCxt);
|
||||
}
|
||||
return pCxt->errCode;
|
||||
}
|
||||
|
||||
|
@ -828,11 +897,13 @@ typedef struct CheckAggColCoexistCxt {
|
|||
STranslateContext* pTranslateCxt;
|
||||
bool existAggFunc;
|
||||
bool existCol;
|
||||
int32_t selectFuncNum;
|
||||
} CheckAggColCoexistCxt;
|
||||
|
||||
static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) {
|
||||
CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext;
|
||||
if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) {
|
||||
pCxt->selectFuncNum += isSelectFunc(pNode) ? 1 : 0;
|
||||
if (isAggFunc(pNode)) {
|
||||
pCxt->existAggFunc = true;
|
||||
return DEAL_RES_IGNORE_CHILD;
|
||||
}
|
||||
|
@ -851,7 +922,9 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
|
|||
if (!pSelect->isDistinct) {
|
||||
nodesWalkExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt);
|
||||
}
|
||||
if ((cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
|
||||
if (1 == cxt.selectFuncNum) {
|
||||
return rewriteColsToSelectValFunc(pCxt, pSelect);
|
||||
} else if ((cxt.selectFuncNum > 1 || cxt.existAggFunc || NULL != pSelect->pWindow) && cxt.existCol) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SINGLE_GROUP);
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -1285,7 +1358,7 @@ static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
pCxt->currClause = SQL_CLAUSE_HAVING;
|
||||
int32_t code = translateExpr(pCxt, pSelect->pHaving);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = checkExprForGroupBy(pCxt, pSelect->pHaving);
|
||||
code = checkExprForGroupBy(pCxt, &pSelect->pHaving);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,6 @@ class MockCatalogServiceImpl {
|
|||
const char* tname = tNameGetTableName(pTableName);
|
||||
int32_t code = copyTableSchemaMeta(db, tname, &table);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
std::cout << "db : " << db << ", table :" << tname << std::endl;
|
||||
return code;
|
||||
}
|
||||
*pTableMeta = table.release();
|
||||
|
|
|
@ -94,6 +94,7 @@ TEST_F(ParserSelectTest, timelineFunc) {
|
|||
|
||||
TEST_F(ParserSelectTest, selectFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
// select function
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1");
|
||||
// select function for GROUP BY clause
|
||||
|
@ -102,8 +103,14 @@ TEST_F(ParserSelectTest, selectFunc) {
|
|||
run("SELECT MAX(c1), MIN(c1) FROM t1 INTERVAL(10s)");
|
||||
// select function along with the columns of select row
|
||||
run("SELECT MAX(c1), c2 FROM t1");
|
||||
run("SELECT MAX(c1), * FROM t1");
|
||||
run("SELECT MAX(c1), t1.* FROM t1");
|
||||
// select function along with the columns of select row, and with GROUP BY clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 GROUP BY c3");
|
||||
run("SELECT MAX(c1), t1.* FROM t1 GROUP BY c3");
|
||||
// select function along with the columns of select row, and with window clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 INTERVAL(10s)");
|
||||
run("SELECT MAX(c1), c2 FROM t1 SESSION(ts, 10s)");
|
||||
run("SELECT MAX(c1), c2 FROM t1 STATE_WINDOW(c3)");
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, clause) {
|
||||
|
@ -154,7 +161,7 @@ TEST_F(ParserSelectTest, interval) {
|
|||
TEST_F(ParserSelectTest, intervalSemanticCheck) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("SELECT c1 FROM t1 INTERVAL(10s)");
|
||||
run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NOT_SINGLE_GROUP, PARSER_STAGE_TRANSLATE);
|
||||
}
|
||||
|
||||
TEST_F(ParserSelectTest, semanticError) {
|
||||
|
|
|
@ -23,30 +23,45 @@ class PlanGroupByTest : public PlannerTestBase {};
|
|||
TEST_F(PlanGroupByTest, basic) {
|
||||
useDb("root", "test");
|
||||
|
||||
run("select count(*) from t1");
|
||||
run("SELECT COUNT(*) FROM t1");
|
||||
|
||||
run("select c1, max(c3), min(c3), count(*) from t1 group by c1");
|
||||
run("SELECT c1, MAX(c3), MIN(c3), COUNT(*) FROM t1 GROUP BY c1");
|
||||
|
||||
run("select c1 + c3, c1 + count(*) from t1 where c2 = 'abc' group by c1, c3");
|
||||
run("SELECT c1 + c3, c1 + COUNT(*) FROM t1 WHERE c2 = 'abc' GROUP BY c1, c3");
|
||||
|
||||
run("select c1 + c3, sum(c4 * c5) from t1 where concat(c2, 'wwww') = 'abcwww' group by c1 + c3");
|
||||
run("SELECT c1 + c3, SUM(c4 * c5) FROM t1 WHERE CONCAT(c2, 'wwww') = 'abcwww' GROUP BY c1 + c3");
|
||||
|
||||
run("select sum(ceil(c1)) from t1 group by ceil(c1)");
|
||||
run("SELECT SUM(CEIL(c1)) FROM t1 GROUP BY CEIL(c1)");
|
||||
}
|
||||
|
||||
TEST_F(PlanGroupByTest, withOrderBy) {
|
||||
useDb("root", "test");
|
||||
|
||||
// order by aggfunc
|
||||
run("select count(*), sum(c1) from t1 order by sum(c1)");
|
||||
// order by alias of aggfunc
|
||||
// run("select count(*), sum(c1) a from t1 order by a");
|
||||
// ORDER BY aggfunc
|
||||
run("SELECT COUNT(*), SUM(c1) FROM t1 ORDER BY SUM(c1)");
|
||||
// ORDER BY alias of aggfunc
|
||||
// run("SELECT COUNT(*), SUM(c1) a FROM t1 ORDER BY a");
|
||||
}
|
||||
|
||||
TEST_F(PlanGroupByTest, aggFunc) {
|
||||
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 LAST(*), FIRST(*) FROM t1 GROUP BY c1");
|
||||
}
|
||||
|
||||
TEST_F(PlanGroupByTest, selectFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
// select function
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1");
|
||||
// select function for GROUP BY clause
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1 GROUP BY c1");
|
||||
// select function along with the columns of select row
|
||||
run("SELECT MAX(c1), c2 FROM t1");
|
||||
run("SELECT MAX(c1), t1.* FROM t1");
|
||||
// select function along with the columns of select row, and with GROUP BY clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 GROUP BY c3");
|
||||
run("SELECT MAX(c1), t1.* FROM t1 GROUP BY c3");
|
||||
}
|
||||
|
|
|
@ -42,3 +42,12 @@ TEST_F(PlanIntervalTest, fill) {
|
|||
"WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' "
|
||||
"INTERVAL(10s) FILL(VALUE, 10, 20)");
|
||||
}
|
||||
|
||||
TEST_F(PlanIntervalTest, selectFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
// select function for INTERVAL clause
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1 INTERVAL(10s)");
|
||||
// select function along with the columns of select row, and with INTERVAL clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 INTERVAL(10s)");
|
||||
}
|
|
@ -25,3 +25,12 @@ TEST_F(PlanSessionTest, basic) {
|
|||
|
||||
run("select count(*) from t1 session(ts, 10s)");
|
||||
}
|
||||
|
||||
TEST_F(PlanSessionTest, selectFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
// select function for SESSION clause
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1 SESSION(ts, 10s)");
|
||||
// select function along with the columns of select row, and with SESSION clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 SESSION(ts, 10s)");
|
||||
}
|
||||
|
|
|
@ -31,3 +31,12 @@ TEST_F(PlanStateTest, stateExpr) {
|
|||
|
||||
run("select count(*) from t1 state_window(c1 + 10)");
|
||||
}
|
||||
|
||||
TEST_F(PlanStateTest, selectFunc) {
|
||||
useDb("root", "test");
|
||||
|
||||
// select function for STATE_WINDOW clause
|
||||
run("SELECT MAX(c1), MIN(c1) FROM t1 STATE_WINDOW(c3)");
|
||||
// select function along with the columns of select row, and with STATE_WINDOW clause
|
||||
run("SELECT MAX(c1), c2 FROM t1 STATE_WINDOW(c3)");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue