Merge pull request #15716 from taosdata/fix/TD-18010
fix(query): add interp param check
This commit is contained in:
commit
a646bba398
|
@ -19,6 +19,7 @@
|
||||||
#include "querynodes.h"
|
#include "querynodes.h"
|
||||||
#include "scalar.h"
|
#include "scalar.h"
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
|
#include "ttime.h"
|
||||||
|
|
||||||
static int32_t buildFuncErrMsg(char* pErrBuf, int32_t len, int32_t errCode, const char* pFormat, ...) {
|
static int32_t buildFuncErrMsg(char* pErrBuf, int32_t len, int32_t errCode, const char* pFormat, ...) {
|
||||||
va_list vArgList;
|
va_list vArgList;
|
||||||
|
@ -1442,6 +1443,58 @@ static int32_t translateIrate(SFunctionNode* pFunc, char* pErrBuf, int32_t len)
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t translateInterp(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
uint8_t dbPrec = pFunc->node.resType.precision;
|
||||||
|
|
||||||
|
if (1 != numOfParams && 3 != numOfParams && 4 != numOfParams) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (3 <= numOfParams) {
|
||||||
|
int64_t timeVal[2] = {0};
|
||||||
|
for (int32_t i = 1; i < 3; ++i) {
|
||||||
|
uint8_t nodeType = nodeType(nodesListGetNode(pFunc->pParameterList, i));
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, i))->resType.type;
|
||||||
|
if (!IS_VAR_DATA_TYPE(paraType) || QUERY_NODE_VALUE != nodeType) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, i);
|
||||||
|
int32_t ret = convertStringToTimestamp(paraType, pValue->datum.p, dbPrec, &timeVal[i - 1]);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeVal[0] > timeVal[1]) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
||||||
|
"INTERP function invalid time range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (4 == numOfParams) {
|
||||||
|
uint8_t nodeType = nodeType(nodesListGetNode(pFunc->pParameterList, 3));
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 3))->resType.type;
|
||||||
|
if (!IS_INTEGER_TYPE(paraType) || QUERY_NODE_VALUE != nodeType) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ret = validateTimeUnitParam(dbPrec, (SValueNode*)nodesListGetNode(pFunc->pParameterList, 3));
|
||||||
|
if (ret == TIME_UNIT_TOO_SMALL) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
||||||
|
"INTERP function time interval parameter should be greater than db precision");
|
||||||
|
} else if (ret == TIME_UNIT_INVALID) {
|
||||||
|
return buildFuncErrMsg(
|
||||||
|
pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR,
|
||||||
|
"INTERP function time interval parameter should be one of the following: [1b, 1u, 1a, 1s, 1m, 1h, 1d, 1w]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
// forbid null as first/last input, since first(c0, null, 1) may have different number of input
|
// forbid null as first/last input, since first(c0, null, 1) may have different number of input
|
||||||
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
@ -2237,7 +2290,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "interp",
|
.name = "interp",
|
||||||
.type = FUNCTION_TYPE_INTERP,
|
.type = FUNCTION_TYPE_INTERP,
|
||||||
.classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
|
.classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | FUNC_MGT_FORBID_STREAM_FUNC,
|
||||||
.translateFunc = translateFirstLast,
|
.translateFunc = translateInterp,
|
||||||
.getEnvFunc = getSelectivityFuncEnv,
|
.getEnvFunc = getSelectivityFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
.processFunc = NULL,
|
.processFunc = NULL,
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#define HISTOGRAM_MAX_BINS_NUM 1000
|
#define HISTOGRAM_MAX_BINS_NUM 1000
|
||||||
#define MAVG_MAX_POINTS_NUM 1000
|
#define MAVG_MAX_POINTS_NUM 1000
|
||||||
#define SAMPLE_MAX_POINTS_NUM 1000
|
|
||||||
#define TAIL_MAX_POINTS_NUM 100
|
#define TAIL_MAX_POINTS_NUM 100
|
||||||
#define TAIL_MAX_OFFSET 100
|
#define TAIL_MAX_OFFSET 100
|
||||||
|
|
||||||
|
@ -4898,9 +4897,7 @@ bool sampleFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo)
|
||||||
pInfo->numSampled = 0;
|
pInfo->numSampled = 0;
|
||||||
pInfo->colType = pCtx->resDataInfo.type;
|
pInfo->colType = pCtx->resDataInfo.type;
|
||||||
pInfo->colBytes = pCtx->resDataInfo.bytes;
|
pInfo->colBytes = pCtx->resDataInfo.bytes;
|
||||||
if (pInfo->samples < 1 || pInfo->samples > SAMPLE_MAX_POINTS_NUM) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
|
pInfo->data = (char*)pInfo + sizeof(SSampleInfo);
|
||||||
pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
|
pInfo->tuplePos = (STuplePos*)((char*)pInfo + sizeof(SSampleInfo) + pInfo->samples * pInfo->colBytes);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue