diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index eebb765889a52c87628a91e3555a823cf5a69d82..227095fc033837000a3ceade0e0f1cea728523e4 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -1482,7 +1482,9 @@ static void first_function_f(SQLFunctionCtx *pCtx, int32_t index) { SET_VAL(pCtx, 1, 1); memcpy(pCtx->aOutputBuf, pData, pCtx->inputBytes); - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + + TSKEY ts = pCtx->ptsList[index]; + DO_UPDATE_TAG_COLUMNS(pCtx, ts); SResultInfo *pInfo = GET_RES_INFO(pCtx); pInfo->hasResult = DATA_SET_FLAG; @@ -1575,7 +1577,7 @@ static void first_dist_func_merge(SQLFunctionCtx *pCtx) { SFirstLastInfo *pOutput = (SFirstLastInfo *)(pCtx->aOutputBuf + pCtx->inputBytes); if (pOutput->hasResult != DATA_SET_FLAG || pInput->ts < pOutput->ts) { memcpy(pCtx->aOutputBuf, pData, pCtx->inputBytes + sizeof(SFirstLastInfo)); - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } } @@ -1623,7 +1625,9 @@ static void last_function(SQLFunctionCtx *pCtx) { } memcpy(pCtx->aOutputBuf, data, pCtx->inputBytes); - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + + TSKEY ts = pCtx->ptsList[i]; + DO_UPDATE_TAG_COLUMNS(pCtx, ts); SResultInfo *pInfo = GET_RES_INFO(pCtx); pInfo->hasResult = DATA_SET_FLAG; @@ -1648,7 +1652,9 @@ static void last_function_f(SQLFunctionCtx *pCtx, int32_t index) { SET_VAL(pCtx, 1, 1); memcpy(pCtx->aOutputBuf, pData, pCtx->inputBytes); - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + + TSKEY ts = pCtx->ptsList[index]; + DO_UPDATE_TAG_COLUMNS(pCtx, ts); SResultInfo *pResInfo = GET_RES_INFO(pCtx); pResInfo->hasResult = DATA_SET_FLAG; @@ -1745,7 +1751,7 @@ static void last_dist_func_merge(SQLFunctionCtx *pCtx) { if (pOutput->hasResult != DATA_SET_FLAG || pOutput->ts < pInput->ts) { memcpy(pCtx->aOutputBuf, pData, pCtx->inputBytes + sizeof(SFirstLastInfo)); - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + DO_UPDATE_TAG_COLUMNS(pCtx, pInput->ts); } } @@ -1800,7 +1806,7 @@ static void last_row_function(SQLFunctionCtx *pCtx) { pInfo1->ts = pCtx->param[0].i64Key; pInfo1->hasResult = DATA_SET_FLAG; - DO_UPDATE_TAG_COLUMNS(pCtx, 0); + DO_UPDATE_TAG_COLUMNS(pCtx, pInfo1->ts); } SET_VAL(pCtx, pCtx->size, 1); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 9ee8ea76303a16cf54a92fcb19419f0bb2f5a268..c66d524fee1912f8bcb963a7d009efea0c87da80 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -2806,59 +2806,6 @@ static bool functionCompatibleCheck(SSqlCmd* pCmd) { } } - // additional check for select aggfuntion(column), column1 from table_name group by(column1); - if ((pCmd->type & TSDB_QUERY_TYPE_PROJECTION_QUERY) == TSDB_QUERY_TYPE_PROJECTION_QUERY) { - bool isAggFunc = false; - for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { - int16_t functionId = tscSqlExprGet(pCmd, i)->functionId; - - if (functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_TS || - functionId == TSDB_FUNC_ARITHM) { - continue; - } - - if ((aAggs[functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) == 0) { - isAggFunc = true; - break; - } - } - - // TODO change the type, the type is not correct - if (isAggFunc) { - pCmd->type &= (~TSDB_QUERY_TYPE_PROJECTION_QUERY); - - // agg function mixed up with project query without group by exists - if (pCmd->groupbyExpr.numOfGroupCols == 0) { - return false; - } - - // get the project column - int32_t numOfPrjColumn = 0; - for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { - SSqlExpr* pExpr = tscSqlExprGet(pCmd, i); - if (pExpr->functionId == TSDB_FUNC_PRJ) { - numOfPrjColumn += 1; - - bool qualifiedCol = false; - for (int32_t j = 0; j < pCmd->groupbyExpr.numOfGroupCols; ++j) { - if (pExpr->colInfo.colId == pCmd->groupbyExpr.columnInfo[j].colId) { - qualifiedCol = true; - - pExpr->param[0].i64Key = 1; // limit the output to be 1 for each state value - pExpr->numOfParams = 1; - break; - } - } - - if (!qualifiedCol) { - setErrMsg(pCmd, msg1); - return false; - } - } - } - } - } - return true; } @@ -5416,6 +5363,27 @@ static void doUpdateSqlFunctionForTagPrj(SSqlCmd* pCmd) { } } +static void doUpdateSqlFunctionForColPrj(SSqlCmd* pCmd) { + for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { + SSqlExpr *pExpr = tscSqlExprGet(pCmd, i); + if (pExpr->functionId == TSDB_FUNC_PRJ) { + + bool qualifiedCol = false; + for (int32_t j = 0; j < pCmd->groupbyExpr.numOfGroupCols; ++j) { + if (pExpr->colInfo.colId == pCmd->groupbyExpr.columnInfo[j].colId) { + qualifiedCol = true; + + pExpr->param[0].i64Key = 1; // limit the output to be 1 for each state value + pExpr->numOfParams = 1; + break; + } + } + + assert(qualifiedCol); + } + } +} + static bool tagColumnInGroupby(SSqlGroupbyExpr* pGroupbyExpr, int16_t columnId) { for (int32_t j = 0; j < pGroupbyExpr->numOfGroupCols; ++j) { if (columnId == pGroupbyExpr->columnInfo[j].colId && pGroupbyExpr->columnInfo[j].flag == TSDB_COL_TAG) { @@ -5480,7 +5448,8 @@ static void updateTagPrjFunction(SSqlCmd* pCmd) { static int32_t checkUpdateTagPrjFunctions(SSqlCmd* pCmd) { const char* msg1 = "only one selectivity function allowed in presence of tags function"; const char* msg2 = "functions not allowed"; - + const char* msg3 = "aggregation function should not be mixed up with projection"; + bool tagColExists = false; int16_t numOfTimestamp = 0; // primary timestamp column int16_t numOfSelectivity = 0; @@ -5494,21 +5463,21 @@ static int32_t checkUpdateTagPrjFunctions(SSqlCmd* pCmd) { break; } } - - if (tagColExists) { // check if the selectivity function exists - for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { - int16_t functionId = tscSqlExprGet(pCmd, i)->functionId; - if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TS) { - continue; - } - - if ((aAggs[functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) != 0) { - numOfSelectivity++; - } else { - numOfAggregation++; - } + + for (int32_t i = 0; i < pCmd->fieldsInfo.numOfOutputCols; ++i) { + int16_t functionId = tscSqlExprGet(pCmd, i)->functionId; + if (functionId == TSDB_FUNC_TAGPRJ || functionId == TSDB_FUNC_PRJ || functionId == TSDB_FUNC_TS) { + continue; } - + + if ((aAggs[functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) != 0) { + numOfSelectivity++; + } else { + numOfAggregation++; + } + } + + if (tagColExists) { // check if the selectivity function exists // When the tag projection function on tag column that is not in the group by clause, aggregation function and // selectivity function exist in select clause is not allowed. if (numOfAggregation > 0) { @@ -5521,6 +5490,7 @@ static int32_t checkUpdateTagPrjFunctions(SSqlCmd* pCmd) { */ if (numOfSelectivity == 1) { doUpdateSqlFunctionForTagPrj(pCmd); + doUpdateSqlFunctionForColPrj(pCmd); } else if (numOfSelectivity > 1) { /* * If more than one selectivity functions exist, all the selectivity functions must be last_row. @@ -5539,6 +5509,20 @@ static int32_t checkUpdateTagPrjFunctions(SSqlCmd* pCmd) { } doUpdateSqlFunctionForTagPrj(pCmd); + doUpdateSqlFunctionForColPrj(pCmd); + } + } else { + if ((pCmd->type & TSDB_QUERY_TYPE_PROJECTION_QUERY) == TSDB_QUERY_TYPE_PROJECTION_QUERY) { + if (numOfAggregation > 0 && pCmd->groupbyExpr.numOfGroupCols == 0) { + setErrMsg(pCmd, msg3); + return TSDB_CODE_INVALID_SQL; + } + + if (numOfAggregation > 0 || numOfSelectivity > 0) { + // clear the projection type flag + pCmd->type &= (~TSDB_QUERY_TYPE_PROJECTION_QUERY); + doUpdateSqlFunctionForColPrj(pCmd); + } } } diff --git a/src/os/linux/inc/os.h b/src/os/linux/inc/os.h index 80557776225a5ede9561bb2c51787cdceeaa550b..6ecb64eda5b173acd205080318ab95527af9547b 100644 --- a/src/os/linux/inc/os.h +++ b/src/os/linux/inc/os.h @@ -28,6 +28,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/src/system/detail/src/vnodeQueryImpl.c b/src/system/detail/src/vnodeQueryImpl.c index 9967094a2680d55259c9e00c1accb2ec87796196..f7f456ec531fee2eac41cd30ae47f6724d6f6a7f 100644 --- a/src/system/detail/src/vnodeQueryImpl.c +++ b/src/system/detail/src/vnodeQueryImpl.c @@ -1840,7 +1840,7 @@ static void setCtxTagColumnInfo(SQuery* pQuery, SQueryRuntimeEnv* pRuntimeEnv) { // ts may be the required primary timestamp column continue; } else { - assert(0); + // the column may be the normal column, group by normal_column, the functionId is TSDB_FUNC_PRJ } }