enh: cols in having clause
This commit is contained in:
parent
01518aae39
commit
4a3343a667
|
@ -272,7 +272,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_SUBSCRIBE_KEY_LEN (TSDB_CGROUP_LEN + TSDB_TOPIC_FNAME_LEN + 2)
|
||||
#define TSDB_PARTITION_KEY_LEN (TSDB_SUBSCRIBE_KEY_LEN + 20)
|
||||
#define TSDB_COL_NAME_LEN 65
|
||||
#define TSDB_COL_NAME_EXLEN 4
|
||||
#define TSDB_COL_NAME_EXLEN 8
|
||||
#define TSDB_COL_FNAME_LEN (TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN + TSDB_NAME_DELIMITER_LEN)
|
||||
#define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 64
|
||||
#define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE
|
||||
|
|
|
@ -4111,7 +4111,7 @@ static int32_t checkWinJoinAggColCoexist(STranslateContext* pCxt, SSelectStmt* p
|
|||
}
|
||||
|
||||
static int32_t checkHavingGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (NULL == getGroupByList(pCxt) && NULL == pSelect->pPartitionByList && NULL == pSelect->pWindow &&
|
||||
!isWindowJoinStmt(pSelect)) {
|
||||
return code;
|
||||
|
@ -5473,22 +5473,26 @@ static int32_t translateClausePosition(STranslateContext* pCxt, SNodeList* pProj
|
|||
}
|
||||
|
||||
static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList, SNodeList** selectFuncList);
|
||||
static int32_t rewriteHavingColsNode(STranslateContext* pCxt, SNode** pNode, SNodeList** selectFuncList);
|
||||
|
||||
static int32_t prepareColumnExpansion(STranslateContext* pCxt, ESqlClause clause, SSelectStmt* pSelect) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t len = LIST_LENGTH(pSelect->pProjectionBindList);
|
||||
if (clause == SQL_CLAUSE_SELECT) {
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &pSelect->pProjectionBindList);
|
||||
} else if (clause == SQL_CLAUSE_HAVING) {
|
||||
code = rewriteHavingColsNode(pCxt, &pSelect->pHaving, &pSelect->pProjectionBindList);
|
||||
} else if (clause == SQL_CLAUSE_ORDER_BY) {
|
||||
code = rewriteColsFunction(pCxt, &pSelect->pOrderByList, &pSelect->pProjectionBindList);
|
||||
} else {
|
||||
code =
|
||||
generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, "Invalid clause for column expansion");
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
if (TSDB_CODE_SUCCESS == code && LIST_LENGTH(pSelect->pProjectionBindList) > len) {
|
||||
code = translateExprList(pCxt, pSelect->pProjectionBindList);
|
||||
}
|
||||
if (pSelect->pProjectionBindList != NULL) {
|
||||
pSelect->hasAggFuncs = true;
|
||||
pSelect->hasAggFuncs = true;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
@ -5745,10 +5749,18 @@ static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect
|
|||
}
|
||||
|
||||
static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (NULL == pSelect->pGroupByList && NULL == pSelect->pPartitionByList && NULL == pSelect->pWindow &&
|
||||
!isWindowJoinStmt(pSelect) && NULL != pSelect->pHaving) {
|
||||
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION);
|
||||
}
|
||||
pCxt->currClause = SQL_CLAUSE_HAVING;
|
||||
if (NULL != pSelect->pHaving) {
|
||||
code = prepareColumnExpansion(pCxt, SQL_CLAUSE_HAVING, pSelect);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
if (isWindowJoinStmt(pSelect)) {
|
||||
if (NULL != pSelect->pHaving) {
|
||||
bool hasFunc = false;
|
||||
|
@ -5758,9 +5770,7 @@ static int32_t translateHaving(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
|||
}
|
||||
}
|
||||
}
|
||||
pCxt->currClause = SQL_CLAUSE_HAVING;
|
||||
int32_t code = translateExpr(pCxt, &pSelect->pHaving);
|
||||
return code;
|
||||
return translateExpr(pCxt, &pSelect->pHaving);
|
||||
}
|
||||
|
||||
static int32_t translateGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||
|
@ -7554,6 +7564,22 @@ _end:
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t rewriteHavingColsNode(STranslateContext* pCxt, SNode** pNode, SNodeList** selectFuncList) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if(!pNode || *pNode == NULL) return code;
|
||||
if (isMultiColsFuncNode(*pNode)) {
|
||||
parserWarn("%s Invalid using multi cols func in having.", __func__);
|
||||
return TSDB_CODE_PAR_INVALID_COLS_FUNCTION;
|
||||
} else {
|
||||
SCheckColsFuncCxt pSelectFuncCxt = {false, selectFuncList, TSDB_CODE_SUCCESS};
|
||||
nodesRewriteExpr(pNode, rewriteSingleColsFunc, &pSelectFuncCxt);
|
||||
if (pSelectFuncCxt.status != TSDB_CODE_SUCCESS) {
|
||||
return pSelectFuncCxt.status;
|
||||
}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList, SNodeList** selectFuncList) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
bool needRewrite = false;
|
||||
|
|
|
@ -1113,6 +1113,47 @@ class TDTestCase:
|
|||
tdSql.checkData(2, 2, "2022-09-29 15:15:03")
|
||||
tdSql.checkData(3, 1, "2022-09-30 15:15:04")
|
||||
tdSql.checkData(3, 2, "2022-09-30 15:15:03")
|
||||
|
||||
def having_test(self, table_name, is_subquery):
|
||||
tdLog.info("having_test")
|
||||
t1 = f"from {table_name} "
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) > 1734574929000')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd0')
|
||||
tdSql.checkData(0, 1, 1734574929014)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) = 1734574929000')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd1')
|
||||
tdSql.checkData(0, 1, 1734574929000)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) < 1734574929000')
|
||||
tdSql.checkRows(0)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) != 1734574929000')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd0')
|
||||
tdSql.checkData(0, 1, 1734574929014)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) >= 1734574929000')
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd1')
|
||||
tdSql.checkData(0, 1, 1734574929000)
|
||||
tdSql.checkData(1, 0, 'd0')
|
||||
tdSql.checkData(1, 1, 1734574929014)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(ts), ts) <= 1734574929000')
|
||||
tdSql.checkRows(1)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd1')
|
||||
tdSql.checkData(0, 1, 1734574929000)
|
||||
tdSql.query(f'select tbname, cols(last(ts), ts) {t1} group by tbname having cols(last(c0), ts) between 1734574929000 and 1734574929014')
|
||||
tdSql.checkRows(2)
|
||||
tdSql.checkCols(2)
|
||||
tdSql.checkData(0, 0, 'd1')
|
||||
tdSql.checkData(0, 1, 1734574929000)
|
||||
tdSql.checkData(1, 0, 'd0')
|
||||
tdSql.checkData(1, 1, 1734574929014)
|
||||
|
||||
|
||||
def run(self):
|
||||
self.funcNestTest()
|
||||
|
@ -1128,6 +1169,8 @@ class TDTestCase:
|
|||
self.include_null_test()
|
||||
self.long_column_name_test()
|
||||
self.test1()
|
||||
self.having_test("test.meters", False)
|
||||
self.having_test("(select tbname, * from test.meters)", True)
|
||||
|
||||
|
||||
def stop(self):
|
||||
|
|
Loading…
Reference in New Issue