diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index e7a821ddf4643e78ae521eaf534ee8881a8974c4..5f0551b109450e7720b50218d6c9851ec74385c6 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -2157,7 +2157,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col const char* msg6 = "function applied to tags not allowed"; const char* msg7 = "normal table can not apply this function"; const char* msg8 = "multi-columns selection does not support alias column name"; - const char* msg9 = "diff can no be applied to unsigned numeric type"; + const char* msg9 = "diff/derivative can no be applied to unsigned numeric type"; + const char* msg10 = "derivative duration should be greater than 1 Second"; switch (functionId) { case TSDB_FUNC_COUNT: { @@ -2340,12 +2341,23 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col tickPerSec /= 1000; } + if (tickPerSec <= 0 || tickPerSec < TSDB_TICK_PER_SECOND(info.precision)) { + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg10); + } + tscExprAddParams(&pExpr->base, (char*) &tickPerSec, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); memset(val, 0, tListLen(val)); + if (tVariantDump(&pParamElem[2].pNode->value, val, TSDB_DATA_TYPE_BIGINT, true) < 0) { return TSDB_CODE_TSC_INVALID_OPERATION; } + int64_t v = *(int64_t*) val; + if (v != 0 && v != 1) { + const char* msg10 = "third parameter in derivative should be 0 or 1"; + return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg10); + } + tscExprAddParams(&pExpr->base, val, TSDB_DATA_TYPE_BIGINT, LONG_BYTES); } @@ -5645,7 +5657,7 @@ int32_t validateSqlFunctionInStreamSql(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) { bool isProjectionFunction = false; - const char* msg1 = "column projection is not compatible with interval"; + const char* msg1 = "functions not compatible with interval"; // multi-output set/ todo refactor size_t size = taosArrayGetSize(pQueryInfo->exprList); @@ -5669,8 +5681,8 @@ int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQu } } - if ((pExpr->base.functionId == TSDB_FUNC_PRJ && pExpr->base.numOfParams == 0) || pExpr->base.functionId == TSDB_FUNC_DIFF || - pExpr->base.functionId == TSDB_FUNC_ARITHM) { + int32_t f = pExpr->base.functionId; + if ((f == TSDB_FUNC_PRJ && pExpr->base.numOfParams == 0) || f == TSDB_FUNC_DIFF || f == TSDB_FUNC_ARITHM || f == TSDB_FUNC_DERIVATIVE) { isProjectionFunction = true; } } @@ -7789,7 +7801,7 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf if (validateIntervalNode(pSql, pQueryInfo, pSqlNode) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; } else { - if (isTimeWindowQuery(pQueryInfo)) { + if (isTimeWindowQuery(pQueryInfo) || pQueryInfo->sessionWindow.gap > 0) { // check if the first column of the nest query result is timestamp column SColumn* pCol = taosArrayGetP(pQueryInfo->colList, 0); if (pCol->info.type != TSDB_DATA_TYPE_TIMESTAMP) { @@ -7872,11 +7884,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf // set interval value if (validateIntervalNode(pSql, pQueryInfo, pSqlNode) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_OPERATION; - } else { - if (isTimeWindowQuery(pQueryInfo) && - (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) { - return TSDB_CODE_TSC_INVALID_OPERATION; - } } if (tscQueryTags(pQueryInfo)) { @@ -7907,6 +7914,11 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf return TSDB_CODE_TSC_INVALID_OPERATION; } + if ((isTimeWindowQuery(pQueryInfo) || pQueryInfo->sessionWindow.gap > 0) && + (validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) { + return TSDB_CODE_TSC_INVALID_OPERATION; + } + if (isSTable) { tscTansformFuncForSTableQuery(pQueryInfo); if (hasUnsupportFunctionsForSTableQuery(pCmd, pQueryInfo)) { diff --git a/src/query/src/qAggMain.c b/src/query/src/qAggMain.c index 62be49c3dfd7d5a490ecb04b604d18a95fad0b3e..96eaeb48cffb332f76fd44d5a4c0f3a560b986d7 100644 --- a/src/query/src/qAggMain.c +++ b/src/query/src/qAggMain.c @@ -3428,7 +3428,7 @@ static bool deriv_function_setup(SQLFunctionCtx *pCtx) { SResultRowCellInfo *pResInfo = GET_RES_INFO(pCtx); SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo); - pDerivInfo->ignoreNegative = pCtx->param[2].i64; + pDerivInfo->ignoreNegative = pCtx->param[1].i64; pDerivInfo->prevTs = -1; pDerivInfo->tsWindow = pCtx->param[0].i64; pDerivInfo->valueSet = false; @@ -3440,10 +3440,8 @@ static void deriv_function(SQLFunctionCtx *pCtx) { SDerivInfo* pDerivInfo = GET_ROWCELL_INTERBUF(pResInfo); void *data = GET_INPUT_DATA_LIST(pCtx); - bool isFirstBlock = (pDerivInfo->valueSet == false); int32_t notNullElems = 0; - int32_t step = GET_FORWARD_DIRECTION_FACTOR(pCtx->order); int32_t i = (pCtx->order == TSDB_ORDER_ASC) ? 0 : pCtx->size - 1; @@ -3469,12 +3467,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { *pTimestamp = tsList[i]; pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; @@ -3496,12 +3494,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { *pTimestamp = tsList[i]; pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = (double) pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; } @@ -3522,12 +3520,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { *pTimestamp = tsList[i]; pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; } @@ -3549,12 +3547,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { *pTimestamp = tsList[i]; pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; } @@ -3575,12 +3573,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { *pTimestamp = tsList[i]; pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; } @@ -3602,12 +3600,12 @@ static void deriv_function(SQLFunctionCtx *pCtx) { pOutput += 1; pTimestamp += 1; + notNullElems++; } } pDerivInfo->prevValue = pData[i]; pDerivInfo->prevTs = tsList[i]; - notNullElems++; } break; } @@ -3623,8 +3621,7 @@ static void deriv_function(SQLFunctionCtx *pCtx) { */ assert(pCtx->hasNull); } else { - int32_t forwardStep = (isFirstBlock) ? notNullElems - 1 : notNullElems; - GET_RES_INFO(pCtx)->numOfRes += forwardStep; + GET_RES_INFO(pCtx)->numOfRes += notNullElems; } } diff --git a/tests/script/general/parser/function.sim b/tests/script/general/parser/function.sim index 591d5d15351c5b110470287d05127f630d7d1979..bec4267b8b0bc1907c0215469d4a935e6aa38747 100644 --- a/tests/script/general/parser/function.sim +++ b/tests/script/general/parser/function.sim @@ -932,3 +932,125 @@ if $data32 != 0.000144445 then return -1 endi +print ===========================> derivative +sql drop table t1 +sql drop table tx; +sql drop table m1; +sql drop table if exists tm0; +sql drop table if exists tm1; +sql create table tm0(ts timestamp, k double) +sql insert into tm0 values('2015-08-18T00:00:00Z', 2.064) ('2015-08-18T00:06:00Z', 2.116) ('2015-08-18T00:12:00Z', 2.028) +sql insert into tm0 values('2015-08-18T00:18:00Z', 2.126) ('2015-08-18T00:24:00Z', 2.041) ('2015-08-18T00:30:00Z', 2.051) + +sql_error select derivative(ts) from tm0; +sql_error select derivative(k) from tm0; +sql_error select derivative(k, 0, 0) from tm0; +sql_error select derivative(k, 1, 911) from tm0; +sql_error select derivative(kx, 1s, 1) from tm0; +sql_error select derivative(k, -20s, 1) from tm0; +sql_error select derivative(k, 20a, 0) from tm0; +sql_error select derivative(k, 200a, 0) from tm0; +sql_error select derivative(k, 999a, 0) from tm0; +sql_error select derivative(k, 20s, -12) from tm0; + +sql select derivative(k, 1s, 0) from tm0 +if $rows != 5 then + return -1 +endi + +if $data00 != @15-08-18 08:06:00.000@ then + return -1 +endi + +if $data01 != 0.000144444 then + print expect 0.000144444, actual: $data01 + return -1 +endi + +if $data10 != @15-08-18 08:12:00.000@ then + return -1 +endi + +if $data11 != -0.000244444 then + return -1 +endi + +if $data20 != @15-08-18 08:18:00.000@ then + return -1 +endi + +if $data21 != 0.000272222 then + print expect 0.000272222, actual: $data21 + return -1 +endi + +if $data30 != @15-08-18 08:24:00.000@ then + return -1 +endi + +if $data31 != -0.000236111 then + print expect 0.000236111, actual: $data31 + return -1 +endi + +sql select derivative(k, 6m, 0) from tm0; +if $rows != 5 then + return -1 +endi + +if $data00 != @15-08-18 08:06:00.000@ then + return -1 +endi + +if $data01 != 0.052000000 then + print expect 0.052000000, actual: $data01 + return -1 +endi + +if $data10 != @15-08-18 08:12:00.000@ then + return -1 +endi + +if $data11 != -0.088000000 then + return -1 +endi + +if $data20 != @15-08-18 08:18:00.000@ then + return -1 +endi + +if $data21 != 0.098000000 then + return -1 +endi + +if $data30 != @15-08-18 08:24:00.000@ then + return -1 +endi + +if $data31 != -0.085000000 then + return -1 +endi + +sql select derivative(k, 12m, 0) from tm0; +if $rows != 5 then + return -1 +endi + +if $data00 != @15-08-18 08:06:00.000@ then + return -1 +endi + +if $data01 != 0.104000000 then + print expect 0.104000000, actual: $data01 + return -1 +endi + +sql select derivative(k, 6m, 1) from tm0; +if $rows != 3 then + return -1 +endi + +sql_error select derivative(k, 6m, 1) from tm0 interval(1s); +sql_error select derivative(k, 6m, 1) from tm0 session(ts, 1s); +sql_error select derivative(k, 6m, 1) from tm0 group by k; +sql_error select derivative(k, 6m, 1) from \ No newline at end of file