enh(query): increase the validity check of function parameters
This commit is contained in:
parent
4473d23633
commit
8118a20649
|
@ -181,48 +181,49 @@
|
||||||
#define TK_NULL 163
|
#define TK_NULL 163
|
||||||
#define TK_FIRST 164
|
#define TK_FIRST 164
|
||||||
#define TK_LAST 165
|
#define TK_LAST 165
|
||||||
#define TK_NOW 166
|
#define TK_CAST 166
|
||||||
#define TK_ROWTS 167
|
#define TK_NOW 167
|
||||||
#define TK_TBNAME 168
|
#define TK_ROWTS 168
|
||||||
#define TK_QSTARTTS 169
|
#define TK_TBNAME 169
|
||||||
#define TK_QENDTS 170
|
#define TK_QSTARTTS 170
|
||||||
#define TK_WSTARTTS 171
|
#define TK_QENDTS 171
|
||||||
#define TK_WENDTS 172
|
#define TK_WSTARTTS 172
|
||||||
#define TK_WDURATION 173
|
#define TK_WENDTS 173
|
||||||
#define TK_BETWEEN 174
|
#define TK_WDURATION 174
|
||||||
#define TK_IS 175
|
#define TK_BETWEEN 175
|
||||||
#define TK_NK_LT 176
|
#define TK_IS 176
|
||||||
#define TK_NK_GT 177
|
#define TK_NK_LT 177
|
||||||
#define TK_NK_LE 178
|
#define TK_NK_GT 178
|
||||||
#define TK_NK_GE 179
|
#define TK_NK_LE 179
|
||||||
#define TK_NK_NE 180
|
#define TK_NK_GE 180
|
||||||
#define TK_MATCH 181
|
#define TK_NK_NE 181
|
||||||
#define TK_NMATCH 182
|
#define TK_MATCH 182
|
||||||
#define TK_JOIN 183
|
#define TK_NMATCH 183
|
||||||
#define TK_INNER 184
|
#define TK_JOIN 184
|
||||||
#define TK_SELECT 185
|
#define TK_INNER 185
|
||||||
#define TK_DISTINCT 186
|
#define TK_SELECT 186
|
||||||
#define TK_WHERE 187
|
#define TK_DISTINCT 187
|
||||||
#define TK_PARTITION 188
|
#define TK_WHERE 188
|
||||||
#define TK_BY 189
|
#define TK_PARTITION 189
|
||||||
#define TK_SESSION 190
|
#define TK_BY 190
|
||||||
#define TK_STATE_WINDOW 191
|
#define TK_SESSION 191
|
||||||
#define TK_SLIDING 192
|
#define TK_STATE_WINDOW 192
|
||||||
#define TK_FILL 193
|
#define TK_SLIDING 193
|
||||||
#define TK_VALUE 194
|
#define TK_FILL 194
|
||||||
#define TK_NONE 195
|
#define TK_VALUE 195
|
||||||
#define TK_PREV 196
|
#define TK_NONE 196
|
||||||
#define TK_LINEAR 197
|
#define TK_PREV 197
|
||||||
#define TK_NEXT 198
|
#define TK_LINEAR 198
|
||||||
#define TK_GROUP 199
|
#define TK_NEXT 199
|
||||||
#define TK_HAVING 200
|
#define TK_GROUP 200
|
||||||
#define TK_ORDER 201
|
#define TK_HAVING 201
|
||||||
#define TK_SLIMIT 202
|
#define TK_ORDER 202
|
||||||
#define TK_SOFFSET 203
|
#define TK_SLIMIT 203
|
||||||
#define TK_LIMIT 204
|
#define TK_SOFFSET 204
|
||||||
#define TK_OFFSET 205
|
#define TK_LIMIT 205
|
||||||
#define TK_ASC 206
|
#define TK_OFFSET 206
|
||||||
#define TK_NULLS 207
|
#define TK_ASC 207
|
||||||
|
#define TK_NULLS 208
|
||||||
|
|
||||||
#define TK_NK_SPACE 300
|
#define TK_NK_SPACE 300
|
||||||
#define TK_NK_COMMENT 301
|
#define TK_NK_COMMENT 301
|
||||||
|
|
|
@ -182,6 +182,7 @@ typedef struct {
|
||||||
#define IS_SIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_TINYINT && (_t) <= TSDB_DATA_TYPE_BIGINT)
|
#define IS_SIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_TINYINT && (_t) <= TSDB_DATA_TYPE_BIGINT)
|
||||||
#define IS_UNSIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_UTINYINT && (_t) <= TSDB_DATA_TYPE_UBIGINT)
|
#define IS_UNSIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_UTINYINT && (_t) <= TSDB_DATA_TYPE_UBIGINT)
|
||||||
#define IS_FLOAT_TYPE(_t) ((_t) == TSDB_DATA_TYPE_FLOAT || (_t) == TSDB_DATA_TYPE_DOUBLE)
|
#define IS_FLOAT_TYPE(_t) ((_t) == TSDB_DATA_TYPE_FLOAT || (_t) == TSDB_DATA_TYPE_DOUBLE)
|
||||||
|
#define IS_INTEGER_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)))
|
||||||
|
|
||||||
#define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t)))
|
#define IS_NUMERIC_TYPE(_t) ((IS_SIGNED_NUMERIC_TYPE(_t)) || (IS_UNSIGNED_NUMERIC_TYPE(_t)) || (IS_FLOAT_TYPE(_t)))
|
||||||
#define IS_MATHABLE_TYPE(_t) (IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
#define IS_MATHABLE_TYPE(_t) (IS_NUMERIC_TYPE(_t) || (_t) == (TSDB_DATA_TYPE_BOOL) || (_t) == (TSDB_DATA_TYPE_TIMESTAMP))
|
||||||
|
|
|
@ -123,7 +123,7 @@ void fmFuncMgtDestroy();
|
||||||
|
|
||||||
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
||||||
|
|
||||||
int32_t fmGetFuncResultType(SFunctionNode* pFunc);
|
int32_t fmGetFuncResultType(SFunctionNode* pFunc, char* pErrBuf, int32_t len);
|
||||||
|
|
||||||
bool fmIsAggFunc(int32_t funcId);
|
bool fmIsAggFunc(int32_t funcId);
|
||||||
bool fmIsScalarFunc(int32_t funcId);
|
bool fmIsScalarFunc(int32_t funcId);
|
||||||
|
|
|
@ -566,8 +566,6 @@ int32_t* taosGetErrno();
|
||||||
#define TSDB_CODE_PAR_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603)
|
#define TSDB_CODE_PAR_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603)
|
||||||
#define TSDB_CODE_PAR_WRONG_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x2604)
|
#define TSDB_CODE_PAR_WRONG_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x2604)
|
||||||
#define TSDB_CODE_PAR_INVALID_FUNTION TAOS_DEF_ERROR_CODE(0, 0x2605)
|
#define TSDB_CODE_PAR_INVALID_FUNTION TAOS_DEF_ERROR_CODE(0, 0x2605)
|
||||||
#define TSDB_CODE_PAR_FUNTION_PARA_NUM TAOS_DEF_ERROR_CODE(0, 0x2606)
|
|
||||||
#define TSDB_CODE_PAR_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2607)
|
|
||||||
#define TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION TAOS_DEF_ERROR_CODE(0, 0x2608)
|
#define TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION TAOS_DEF_ERROR_CODE(0, 0x2608)
|
||||||
#define TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT TAOS_DEF_ERROR_CODE(0, 0x2609)
|
#define TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT TAOS_DEF_ERROR_CODE(0, 0x2609)
|
||||||
#define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A)
|
#define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A)
|
||||||
|
@ -601,7 +599,12 @@ int32_t* taosGetErrno();
|
||||||
#define TSDB_CODE_PAR_INVALID_KEEP_UNIT TAOS_DEF_ERROR_CODE(0, 0x2626)
|
#define TSDB_CODE_PAR_INVALID_KEEP_UNIT TAOS_DEF_ERROR_CODE(0, 0x2626)
|
||||||
|
|
||||||
//planner
|
//planner
|
||||||
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
#define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700)
|
||||||
|
|
||||||
|
//function
|
||||||
|
#define TSDB_CODE_FUNC_FUNTION_ERROR TAOS_DEF_ERROR_CODE(0, 0x2800)
|
||||||
|
#define TSDB_CODE_FUNC_FUNTION_PARA_NUM TAOS_DEF_ERROR_CODE(0, 0x2801)
|
||||||
|
#define TSDB_CODE_FUNC_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2802)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,14 +40,14 @@ extern "C" {
|
||||||
|
|
||||||
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
#define FUNC_MGT_TEST_MASK(val, mask) (((val) & (mask)) != 0)
|
||||||
|
|
||||||
typedef int32_t (*FCheckAndGetResultType)(SFunctionNode* pFunc);
|
typedef int32_t (*FTranslateFunc)(SFunctionNode* pFunc, char* pErrBuf, int32_t len);
|
||||||
typedef EFuncDataRequired (*FFuncDataRequired)(SFunctionNode* pFunc, STimeWindow* pTimeWindow);
|
typedef EFuncDataRequired (*FFuncDataRequired)(SFunctionNode* pFunc, STimeWindow* pTimeWindow);
|
||||||
|
|
||||||
typedef struct SBuiltinFuncDefinition {
|
typedef struct SBuiltinFuncDefinition {
|
||||||
char name[FUNCTION_NAME_MAX_LENGTH];
|
char name[FUNCTION_NAME_MAX_LENGTH];
|
||||||
EFunctionType type;
|
EFunctionType type;
|
||||||
uint64_t classification;
|
uint64_t classification;
|
||||||
FCheckAndGetResultType checkFunc;
|
FTranslateFunc translateFunc;
|
||||||
FFuncDataRequired dataRequiredFunc;
|
FFuncDataRequired dataRequiredFunc;
|
||||||
FExecGetEnv getEnvFunc;
|
FExecGetEnv getEnvFunc;
|
||||||
FExecInit initFunc;
|
FExecInit initFunc;
|
||||||
|
|
|
@ -19,14 +19,349 @@
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
#include "tdatablock.h"
|
#include "tdatablock.h"
|
||||||
|
|
||||||
int32_t checkAndGetResultType(SFunctionNode* pFunc);
|
static int32_t buildFuncErrMsg(char* pErrBuf, int32_t len, int32_t errCode, const char* pFormat, ...) {
|
||||||
|
va_list vArgList;
|
||||||
|
va_start(vArgList, pFormat);
|
||||||
|
vsnprintf(pErrBuf, len, pFormat, vArgList);
|
||||||
|
va_end(vArgList);
|
||||||
|
return errCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t invaildFuncParaNumErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_NUM, "Invalid number of arguments : %s", pFuncName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t invaildFuncParaTypeErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_TYPE, "Inconsistent datatypes : %s", pFuncName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is only one parameter of numeric type, and the return type is parameter type
|
||||||
|
static int32_t translateInOutNum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(paraType)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[paraType].bytes, .type = paraType };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is only one parameter of numeric type, and the return type is double type
|
||||||
|
static int32_t translateInNumOutDou(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(paraType)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are two parameters of numeric type, and the return type is double type
|
||||||
|
static int32_t translateIn2NumOutDou(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (2 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(para1Type) || !IS_NUMERIC_TYPE(para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is only one parameter of string type, and the return type is parameter type
|
||||||
|
static int32_t translateInOutStr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (!IS_VAR_DATA_TYPE(pPara1->resType.type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = pPara1->resType.bytes, .type = pPara1->resType.type };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateCount(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateSum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(paraType)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t resType = 0;
|
||||||
|
if (IS_SIGNED_NUMERIC_TYPE(paraType) || paraType == TSDB_DATA_TYPE_BOOL) {
|
||||||
|
resType = TSDB_DATA_TYPE_BIGINT;
|
||||||
|
} else if (IS_UNSIGNED_NUMERIC_TYPE(paraType)) {
|
||||||
|
resType = TSDB_DATA_TYPE_UBIGINT;
|
||||||
|
} else if (IS_FLOAT_TYPE(paraType)) {
|
||||||
|
resType = TSDB_DATA_TYPE_DOUBLE;
|
||||||
|
}
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[resType].bytes, .type = resType };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateWduration(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// pseudo column do not need to check parameters
|
||||||
|
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateTimePseudoColumn(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// pseudo column do not need to check parameters
|
||||||
|
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translatePercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (2 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(para1Type) || (!IS_SIGNED_NUMERIC_TYPE(para2Type) && !IS_UNSIGNED_NUMERIC_TYPE(para2Type))) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool validAperventileAlgo(const SValueNode* pVal) {
|
||||||
|
if (TSDB_DATA_TYPE_BINARY != pVal->node.resType.type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (0 == strcasecmp(varDataVal(pVal->datum.p), "default") || 0 == strcasecmp(varDataVal(pVal->datum.p), "t-digest"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateApercentile(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
int32_t paraNum = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
if (2 != paraNum && 3 != paraNum) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if (!IS_NUMERIC_TYPE(para1Type) || !IS_INTEGER_TYPE(para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
if (3 == paraNum) {
|
||||||
|
SNode* pPara3 = nodesListGetNode(pFunc->pParameterList, 2);
|
||||||
|
if (QUERY_NODE_VALUE != nodeType(pPara3) || !validAperventileAlgo((SValueNode*)pPara3)) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "Third parameter algorithm of apercentile must be 'default' or 't-digest'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateTop(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// todo
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateBottom(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// todo
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateSpread(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// todo
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateLastRow(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// todo
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateFirstLast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// first(*)/first(col_list) has been rewritten as first(col)
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* pPara = nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
if (QUERY_NODE_COLUMN != nodeType(pPara)) {
|
||||||
|
return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_ERROR, "The parameters of first/last can only be columns");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paraType = ((SExprNode*)pPara)->resType.type;
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[paraType].bytes, .type = paraType };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateLength(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_VAR_DATA_TYPE(((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_INT].bytes, .type = TSDB_DATA_TYPE_INT };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateConcatImpl(
|
||||||
|
SFunctionNode* pFunc, char* pErrBuf, int32_t len, int32_t minParaNum, int32_t maxParaNum, int32_t primaryParaNo) {
|
||||||
|
int32_t paraNum = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
if (paraNum < minParaNum || paraNum > maxParaNum) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
SNode* pPara = NULL;
|
||||||
|
FOREACH(pPara, pFunc->pParameterList) {
|
||||||
|
if (!IS_VAR_DATA_TYPE(((SExprNode*)pPara)->resType.type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, primaryParaNo);
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = pPara1->resType.bytes, .type = pPara1->resType.type };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateConcat(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
return translateConcatImpl(pFunc, pErrBuf, len, 2, 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateConcatWs(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
return translateConcatImpl(pFunc, pErrBuf, len, 3, 9, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
int32_t paraNum = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
if (2 != paraNum && 3 != paraNum) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if (!IS_VAR_DATA_TYPE(pPara1->resType.type) || !IS_INTEGER_TYPE(para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
if (3 == paraNum) {
|
||||||
|
uint8_t para3Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if (!IS_INTEGER_TYPE(para3Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = pPara1->resType.bytes, .type = pPara1->resType.type };
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
// The number of parameters has been limited by the syntax definition
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
// The function return type has been set during syntax parsing
|
||||||
|
uint8_t para2Type = pFunc->node.resType.type;
|
||||||
|
if ((TSDB_DATA_TYPE_JSON == para1Type || TSDB_DATA_TYPE_BLOB == para1Type || TSDB_DATA_TYPE_MEDIUMBLOB == para1Type) ||
|
||||||
|
(TSDB_DATA_TYPE_JSON == para2Type || TSDB_DATA_TYPE_BLOB == para2Type || TSDB_DATA_TYPE_MEDIUMBLOB == para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
if (!IS_VAR_DATA_TYPE(paraType) && TSDB_DATA_TYPE_TIMESTAMP != paraType) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = 64, .type = TSDB_DATA_TYPE_BINARY};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateToUnixtimestamp(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (1 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_VAR_DATA_TYPE(((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateTimeTruncate(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
if (2 != LIST_LENGTH(pFunc->pParameterList)) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if ((!IS_VAR_DATA_TYPE(para1Type) && TSDB_DATA_TYPE_TIMESTAMP != para1Type) || !IS_INTEGER_TYPE(para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, .type = TSDB_DATA_TYPE_TIMESTAMP};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t translateTimeDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
|
int32_t paraNum = LIST_LENGTH(pFunc->pParameterList);
|
||||||
|
if (2 != paraNum && 3 != paraNum) {
|
||||||
|
return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type;
|
||||||
|
uint8_t para2Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 1))->resType.type;
|
||||||
|
if ((!IS_VAR_DATA_TYPE(para1Type) && TSDB_DATA_TYPE_TIMESTAMP != para1Type) ||
|
||||||
|
(!IS_VAR_DATA_TYPE(para2Type) && TSDB_DATA_TYPE_TIMESTAMP != para2Type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
if (3 == paraNum) {
|
||||||
|
if (!IS_INTEGER_TYPE(((SExprNode*)nodesListGetNode(pFunc->pParameterList, 2))->resType.type)) {
|
||||||
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
{
|
{
|
||||||
.name = "count",
|
.name = "count",
|
||||||
.type = FUNCTION_TYPE_COUNT,
|
.type = FUNCTION_TYPE_COUNT,
|
||||||
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED,
|
.classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateCount,
|
||||||
.dataRequiredFunc = countDataRequired,
|
.dataRequiredFunc = countDataRequired,
|
||||||
.getEnvFunc = getCountFuncEnv,
|
.getEnvFunc = getCountFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
|
@ -37,7 +372,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "sum",
|
.name = "sum",
|
||||||
.type = FUNCTION_TYPE_SUM,
|
.type = FUNCTION_TYPE_SUM,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateSum,
|
||||||
.getEnvFunc = getSumFuncEnv,
|
.getEnvFunc = getSumFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
.processFunc = sumFunction,
|
.processFunc = sumFunction,
|
||||||
|
@ -47,7 +382,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "min",
|
.name = "min",
|
||||||
.type = FUNCTION_TYPE_MIN,
|
.type = FUNCTION_TYPE_MIN,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = minFunctionSetup,
|
.initFunc = minFunctionSetup,
|
||||||
.processFunc = minFunction,
|
.processFunc = minFunction,
|
||||||
|
@ -57,7 +392,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "max",
|
.name = "max",
|
||||||
.type = FUNCTION_TYPE_MAX,
|
.type = FUNCTION_TYPE_MAX,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -67,7 +402,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "stddev",
|
.name = "stddev",
|
||||||
.type = FUNCTION_TYPE_STDDEV,
|
.type = FUNCTION_TYPE_STDDEV,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = getStddevFuncEnv,
|
.getEnvFunc = getStddevFuncEnv,
|
||||||
.initFunc = stddevFunctionSetup,
|
.initFunc = stddevFunctionSetup,
|
||||||
.processFunc = stddevFunction,
|
.processFunc = stddevFunction,
|
||||||
|
@ -77,7 +412,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "percentile",
|
.name = "percentile",
|
||||||
.type = FUNCTION_TYPE_PERCENTILE,
|
.type = FUNCTION_TYPE_PERCENTILE,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translatePercentile,
|
||||||
.getEnvFunc = getPercentileFuncEnv,
|
.getEnvFunc = getPercentileFuncEnv,
|
||||||
.initFunc = percentileFunctionSetup,
|
.initFunc = percentileFunctionSetup,
|
||||||
.processFunc = percentileFunction,
|
.processFunc = percentileFunction,
|
||||||
|
@ -87,7 +422,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "apercentile",
|
.name = "apercentile",
|
||||||
.type = FUNCTION_TYPE_APERCENTILE,
|
.type = FUNCTION_TYPE_APERCENTILE,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateApercentile,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -97,7 +432,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "top",
|
.name = "top",
|
||||||
.type = FUNCTION_TYPE_TOP,
|
.type = FUNCTION_TYPE_TOP,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTop,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -107,7 +442,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "bottom",
|
.name = "bottom",
|
||||||
.type = FUNCTION_TYPE_BOTTOM,
|
.type = FUNCTION_TYPE_BOTTOM,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateBottom,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -117,7 +452,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "spread",
|
.name = "spread",
|
||||||
.type = FUNCTION_TYPE_SPREAD,
|
.type = FUNCTION_TYPE_SPREAD,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateSpread,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -127,7 +462,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "last_row",
|
.name = "last_row",
|
||||||
.type = FUNCTION_TYPE_LAST_ROW,
|
.type = FUNCTION_TYPE_LAST_ROW,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateLastRow,
|
||||||
.getEnvFunc = getMinmaxFuncEnv,
|
.getEnvFunc = getMinmaxFuncEnv,
|
||||||
.initFunc = maxFunctionSetup,
|
.initFunc = maxFunctionSetup,
|
||||||
.processFunc = maxFunction,
|
.processFunc = maxFunction,
|
||||||
|
@ -137,7 +472,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "first",
|
.name = "first",
|
||||||
.type = FUNCTION_TYPE_FIRST,
|
.type = FUNCTION_TYPE_FIRST,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateFirstLast,
|
||||||
.getEnvFunc = getFirstLastFuncEnv,
|
.getEnvFunc = getFirstLastFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
.processFunc = firstFunction,
|
.processFunc = firstFunction,
|
||||||
|
@ -147,7 +482,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "last",
|
.name = "last",
|
||||||
.type = FUNCTION_TYPE_LAST,
|
.type = FUNCTION_TYPE_LAST,
|
||||||
.classification = FUNC_MGT_AGG_FUNC,
|
.classification = FUNC_MGT_AGG_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateFirstLast,
|
||||||
.getEnvFunc = getFirstLastFuncEnv,
|
.getEnvFunc = getFirstLastFuncEnv,
|
||||||
.initFunc = functionSetup,
|
.initFunc = functionSetup,
|
||||||
.processFunc = lastFunction,
|
.processFunc = lastFunction,
|
||||||
|
@ -157,7 +492,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "diff",
|
.name = "diff",
|
||||||
.type = FUNCTION_TYPE_DIFF,
|
.type = FUNCTION_TYPE_DIFF,
|
||||||
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC,
|
.classification = FUNC_MGT_NONSTANDARD_SQL_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = getDiffFuncEnv,
|
.getEnvFunc = getDiffFuncEnv,
|
||||||
.initFunc = diffFunctionSetup,
|
.initFunc = diffFunctionSetup,
|
||||||
.processFunc = diffFunction,
|
.processFunc = diffFunction,
|
||||||
|
@ -167,7 +502,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "abs",
|
.name = "abs",
|
||||||
.type = FUNCTION_TYPE_ABS,
|
.type = FUNCTION_TYPE_ABS,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = absFunction,
|
.sprocessFunc = absFunction,
|
||||||
|
@ -177,7 +512,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "log",
|
.name = "log",
|
||||||
.type = FUNCTION_TYPE_LOG,
|
.type = FUNCTION_TYPE_LOG,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateIn2NumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = logFunction,
|
.sprocessFunc = logFunction,
|
||||||
|
@ -187,7 +522,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "pow",
|
.name = "pow",
|
||||||
.type = FUNCTION_TYPE_POW,
|
.type = FUNCTION_TYPE_POW,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateIn2NumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = powFunction,
|
.sprocessFunc = powFunction,
|
||||||
|
@ -197,7 +532,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "sqrt",
|
.name = "sqrt",
|
||||||
.type = FUNCTION_TYPE_SQRT,
|
.type = FUNCTION_TYPE_SQRT,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = sqrtFunction,
|
.sprocessFunc = sqrtFunction,
|
||||||
|
@ -207,7 +542,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "ceil",
|
.name = "ceil",
|
||||||
.type = FUNCTION_TYPE_CEIL,
|
.type = FUNCTION_TYPE_CEIL,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = ceilFunction,
|
.sprocessFunc = ceilFunction,
|
||||||
|
@ -217,7 +552,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "floor",
|
.name = "floor",
|
||||||
.type = FUNCTION_TYPE_FLOOR,
|
.type = FUNCTION_TYPE_FLOOR,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = floorFunction,
|
.sprocessFunc = floorFunction,
|
||||||
|
@ -227,7 +562,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "round",
|
.name = "round",
|
||||||
.type = FUNCTION_TYPE_ROUND,
|
.type = FUNCTION_TYPE_ROUND,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutNum,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = roundFunction,
|
.sprocessFunc = roundFunction,
|
||||||
|
@ -237,7 +572,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "sin",
|
.name = "sin",
|
||||||
.type = FUNCTION_TYPE_SIN,
|
.type = FUNCTION_TYPE_SIN,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = sinFunction,
|
.sprocessFunc = sinFunction,
|
||||||
|
@ -247,7 +582,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "cos",
|
.name = "cos",
|
||||||
.type = FUNCTION_TYPE_COS,
|
.type = FUNCTION_TYPE_COS,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = cosFunction,
|
.sprocessFunc = cosFunction,
|
||||||
|
@ -257,7 +592,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "tan",
|
.name = "tan",
|
||||||
.type = FUNCTION_TYPE_TAN,
|
.type = FUNCTION_TYPE_TAN,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = tanFunction,
|
.sprocessFunc = tanFunction,
|
||||||
|
@ -267,7 +602,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "asin",
|
.name = "asin",
|
||||||
.type = FUNCTION_TYPE_ASIN,
|
.type = FUNCTION_TYPE_ASIN,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = asinFunction,
|
.sprocessFunc = asinFunction,
|
||||||
|
@ -277,7 +612,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "acos",
|
.name = "acos",
|
||||||
.type = FUNCTION_TYPE_ACOS,
|
.type = FUNCTION_TYPE_ACOS,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = acosFunction,
|
.sprocessFunc = acosFunction,
|
||||||
|
@ -287,7 +622,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "atan",
|
.name = "atan",
|
||||||
.type = FUNCTION_TYPE_ATAN,
|
.type = FUNCTION_TYPE_ATAN,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInNumOutDou,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = atanFunction,
|
.sprocessFunc = atanFunction,
|
||||||
|
@ -297,7 +632,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "length",
|
.name = "length",
|
||||||
.type = FUNCTION_TYPE_LENGTH,
|
.type = FUNCTION_TYPE_LENGTH,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateLength,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = lengthFunction,
|
.sprocessFunc = lengthFunction,
|
||||||
|
@ -307,7 +642,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "char_length",
|
.name = "char_length",
|
||||||
.type = FUNCTION_TYPE_CHAR_LENGTH,
|
.type = FUNCTION_TYPE_CHAR_LENGTH,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateLength,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = charLengthFunction,
|
.sprocessFunc = charLengthFunction,
|
||||||
|
@ -317,7 +652,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "concat",
|
.name = "concat",
|
||||||
.type = FUNCTION_TYPE_CONCAT,
|
.type = FUNCTION_TYPE_CONCAT,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateConcat,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = concatFunction,
|
.sprocessFunc = concatFunction,
|
||||||
|
@ -327,7 +662,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "concat_ws",
|
.name = "concat_ws",
|
||||||
.type = FUNCTION_TYPE_CONCAT_WS,
|
.type = FUNCTION_TYPE_CONCAT_WS,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateConcatWs,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = concatWsFunction,
|
.sprocessFunc = concatWsFunction,
|
||||||
|
@ -337,7 +672,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "lower",
|
.name = "lower",
|
||||||
.type = FUNCTION_TYPE_LOWER,
|
.type = FUNCTION_TYPE_LOWER,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutStr,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = lowerFunction,
|
.sprocessFunc = lowerFunction,
|
||||||
|
@ -347,7 +682,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "upper",
|
.name = "upper",
|
||||||
.type = FUNCTION_TYPE_UPPER,
|
.type = FUNCTION_TYPE_UPPER,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutStr,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = upperFunction,
|
.sprocessFunc = upperFunction,
|
||||||
|
@ -357,7 +692,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "ltrim",
|
.name = "ltrim",
|
||||||
.type = FUNCTION_TYPE_LTRIM,
|
.type = FUNCTION_TYPE_LTRIM,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutStr,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = ltrimFunction,
|
.sprocessFunc = ltrimFunction,
|
||||||
|
@ -367,7 +702,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "rtrim",
|
.name = "rtrim",
|
||||||
.type = FUNCTION_TYPE_RTRIM,
|
.type = FUNCTION_TYPE_RTRIM,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateInOutStr,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = rtrimFunction,
|
.sprocessFunc = rtrimFunction,
|
||||||
|
@ -377,7 +712,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "substr",
|
.name = "substr",
|
||||||
.type = FUNCTION_TYPE_SUBSTR,
|
.type = FUNCTION_TYPE_SUBSTR,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_STRING_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateSubstr,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = substrFunction,
|
.sprocessFunc = substrFunction,
|
||||||
|
@ -387,7 +722,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "cast",
|
.name = "cast",
|
||||||
.type = FUNCTION_TYPE_CAST,
|
.type = FUNCTION_TYPE_CAST,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateCast,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = castFunction,
|
.sprocessFunc = castFunction,
|
||||||
|
@ -397,7 +732,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "to_iso8601",
|
.name = "to_iso8601",
|
||||||
.type = FUNCTION_TYPE_TO_ISO8601,
|
.type = FUNCTION_TYPE_TO_ISO8601,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateToIso8601,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = toISO8601Function,
|
.sprocessFunc = toISO8601Function,
|
||||||
|
@ -407,7 +742,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "to_unixtimestamp",
|
.name = "to_unixtimestamp",
|
||||||
.type = FUNCTION_TYPE_TO_UNIXTIMESTAMP,
|
.type = FUNCTION_TYPE_TO_UNIXTIMESTAMP,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateToUnixtimestamp,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = toUnixtimestampFunction,
|
.sprocessFunc = toUnixtimestampFunction,
|
||||||
|
@ -417,7 +752,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "timetruncate",
|
.name = "timetruncate",
|
||||||
.type = FUNCTION_TYPE_TIMETRUNCATE,
|
.type = FUNCTION_TYPE_TIMETRUNCATE,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimeTruncate,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = timeTruncateFunction,
|
.sprocessFunc = timeTruncateFunction,
|
||||||
|
@ -427,7 +762,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "timediff",
|
.name = "timediff",
|
||||||
.type = FUNCTION_TYPE_TIMEDIFF,
|
.type = FUNCTION_TYPE_TIMEDIFF,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimeDiff,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = timeDiffFunction,
|
.sprocessFunc = timeDiffFunction,
|
||||||
|
@ -437,7 +772,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_rowts",
|
.name = "_rowts",
|
||||||
.type = FUNCTION_TYPE_ROWTS,
|
.type = FUNCTION_TYPE_ROWTS,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = NULL,
|
.sprocessFunc = NULL,
|
||||||
|
@ -447,7 +782,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "tbname",
|
.name = "tbname",
|
||||||
.type = FUNCTION_TYPE_TBNAME,
|
.type = FUNCTION_TYPE_TBNAME,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = NULL,
|
||||||
.getEnvFunc = NULL,
|
.getEnvFunc = NULL,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = NULL,
|
.sprocessFunc = NULL,
|
||||||
|
@ -457,7 +792,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_qstartts",
|
.name = "_qstartts",
|
||||||
.type = FUNCTION_TYPE_QSTARTTS,
|
.type = FUNCTION_TYPE_QSTARTTS,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = qStartTsFunction,
|
.sprocessFunc = qStartTsFunction,
|
||||||
|
@ -467,7 +802,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_qendts",
|
.name = "_qendts",
|
||||||
.type = FUNCTION_TYPE_QENDTS,
|
.type = FUNCTION_TYPE_QENDTS,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = qEndTsFunction,
|
.sprocessFunc = qEndTsFunction,
|
||||||
|
@ -477,7 +812,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_wstartts",
|
.name = "_wstartts",
|
||||||
.type = FUNCTION_TYPE_WSTARTTS,
|
.type = FUNCTION_TYPE_WSTARTTS,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = winStartTsFunction,
|
.sprocessFunc = winStartTsFunction,
|
||||||
|
@ -487,7 +822,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_wendts",
|
.name = "_wendts",
|
||||||
.type = FUNCTION_TYPE_QENDTS,
|
.type = FUNCTION_TYPE_QENDTS,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = winEndTsFunction,
|
.sprocessFunc = winEndTsFunction,
|
||||||
|
@ -497,7 +832,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "_wduration",
|
.name = "_wduration",
|
||||||
.type = FUNCTION_TYPE_WDURATION,
|
.type = FUNCTION_TYPE_WDURATION,
|
||||||
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
.classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_WINDOW_PC_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateWduration,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = winDurFunction,
|
.sprocessFunc = winDurFunction,
|
||||||
|
@ -507,7 +842,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
.name = "now",
|
.name = "now",
|
||||||
.type = FUNCTION_TYPE_NOW,
|
.type = FUNCTION_TYPE_NOW,
|
||||||
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_DATETIME_FUNC,
|
.classification = FUNC_MGT_SCALAR_FUNC | FUNC_MGT_DATETIME_FUNC,
|
||||||
.checkFunc = checkAndGetResultType,
|
.translateFunc = translateTimePseudoColumn,
|
||||||
.getEnvFunc = getTimePseudoFuncEnv,
|
.getEnvFunc = getTimePseudoFuncEnv,
|
||||||
.initFunc = NULL,
|
.initFunc = NULL,
|
||||||
.sprocessFunc = winDurFunction,
|
.sprocessFunc = winDurFunction,
|
||||||
|
@ -516,167 +851,3 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const int32_t funcMgtBuiltinsNum = (sizeof(funcMgtBuiltins) / sizeof(SBuiltinFuncDefinition));
|
const int32_t funcMgtBuiltinsNum = (sizeof(funcMgtBuiltins) / sizeof(SBuiltinFuncDefinition));
|
||||||
|
|
||||||
int32_t checkAndGetResultType(SFunctionNode* pFunc) {
|
|
||||||
switch(pFunc->funcType) {
|
|
||||||
case FUNCTION_TYPE_WDURATION:
|
|
||||||
case FUNCTION_TYPE_COUNT: {
|
|
||||||
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_BIGINT};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_SUM: {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
int32_t paraType = pParam->node.resType.type;
|
|
||||||
|
|
||||||
int32_t resType = 0;
|
|
||||||
if (IS_SIGNED_NUMERIC_TYPE(paraType) || paraType == TSDB_DATA_TYPE_BOOL) {
|
|
||||||
resType = TSDB_DATA_TYPE_BIGINT;
|
|
||||||
} else if (IS_UNSIGNED_NUMERIC_TYPE(paraType)) {
|
|
||||||
resType = TSDB_DATA_TYPE_UBIGINT;
|
|
||||||
} else if (IS_FLOAT_TYPE(paraType)) {
|
|
||||||
resType = TSDB_DATA_TYPE_DOUBLE;
|
|
||||||
} else {
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[resType].bytes, .type = resType };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_DIFF:
|
|
||||||
case FUNCTION_TYPE_FIRST:
|
|
||||||
case FUNCTION_TYPE_LAST:
|
|
||||||
case FUNCTION_TYPE_MIN:
|
|
||||||
case FUNCTION_TYPE_MAX: {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
int32_t paraType = pParam->node.resType.type;
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[paraType].bytes, .type = paraType };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_ROWTS:
|
|
||||||
case FUNCTION_TYPE_QSTARTTS:
|
|
||||||
case FUNCTION_TYPE_QENDTS:
|
|
||||||
case FUNCTION_TYPE_WSTARTTS:
|
|
||||||
case FUNCTION_TYPE_WENDTS:{
|
|
||||||
pFunc->node.resType = (SDataType){.bytes = sizeof(int64_t), .type = TSDB_DATA_TYPE_TIMESTAMP};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_ABS:
|
|
||||||
case FUNCTION_TYPE_CEIL:
|
|
||||||
case FUNCTION_TYPE_FLOOR:
|
|
||||||
case FUNCTION_TYPE_ROUND: {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
int32_t paraType = pParam->node.resType.type;
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[paraType].bytes, .type = paraType };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_PERCENTILE:
|
|
||||||
case FUNCTION_TYPE_STDDEV:
|
|
||||||
case FUNCTION_TYPE_SIN:
|
|
||||||
case FUNCTION_TYPE_COS:
|
|
||||||
case FUNCTION_TYPE_TAN:
|
|
||||||
case FUNCTION_TYPE_ASIN:
|
|
||||||
case FUNCTION_TYPE_ACOS:
|
|
||||||
case FUNCTION_TYPE_ATAN:
|
|
||||||
case FUNCTION_TYPE_SQRT:
|
|
||||||
case FUNCTION_TYPE_LOG:
|
|
||||||
case FUNCTION_TYPE_POW: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes, .type = TSDB_DATA_TYPE_DOUBLE };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_LENGTH:
|
|
||||||
case FUNCTION_TYPE_CHAR_LENGTH: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_SMALLINT].bytes, .type = TSDB_DATA_TYPE_SMALLINT };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_CONCAT:
|
|
||||||
case FUNCTION_TYPE_CONCAT_WS: {
|
|
||||||
int32_t paraType, paraBytes = 0;
|
|
||||||
bool typeSet = false;
|
|
||||||
for (int32_t i = 0; i < pFunc->pParameterList->length; ++i) {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, i);
|
|
||||||
if (pParam->node.type == QUERY_NODE_COLUMN) {
|
|
||||||
if (typeSet == false) {
|
|
||||||
paraType = pParam->node.resType.type;
|
|
||||||
typeSet = true;
|
|
||||||
} else {
|
|
||||||
//columns have to be the same type
|
|
||||||
if (paraType != pParam->node.resType.type) {
|
|
||||||
return TSDB_CODE_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paraBytes += pParam->node.resType.bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < pFunc->pParameterList->length; ++i) {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, i);
|
|
||||||
if (pParam->node.type == QUERY_NODE_VALUE) {
|
|
||||||
if (paraType == TSDB_DATA_TYPE_NCHAR) {
|
|
||||||
paraBytes += pParam->node.resType.bytes * TSDB_NCHAR_SIZE;
|
|
||||||
} else {
|
|
||||||
paraBytes += pParam->node.resType.bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = paraBytes, .type = paraType };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_LOWER:
|
|
||||||
case FUNCTION_TYPE_UPPER:
|
|
||||||
case FUNCTION_TYPE_LTRIM:
|
|
||||||
case FUNCTION_TYPE_RTRIM:
|
|
||||||
case FUNCTION_TYPE_SUBSTR: {
|
|
||||||
SColumnNode* pParam = nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
int32_t paraType = pParam->node.resType.type;
|
|
||||||
int32_t paraBytes = pParam->node.resType.bytes;
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = paraBytes, .type = paraType };
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_CAST: {
|
|
||||||
//type
|
|
||||||
SValueNode* pParam = nodesListGetNode(pFunc->pParameterList, 1);
|
|
||||||
int32_t paraType = pParam->datum.i;
|
|
||||||
//bytes
|
|
||||||
pParam = nodesListGetNode(pFunc->pParameterList, 2);
|
|
||||||
int32_t paraBytes = pParam->datum.i;
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = paraBytes, .type = paraType};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_TO_ISO8601: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = 64, .type = TSDB_DATA_TYPE_BINARY};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_TO_UNIXTIMESTAMP: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_TIMETRUNCATE: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_TIMESTAMP].bytes, .type = TSDB_DATA_TYPE_TIMESTAMP};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FUNCTION_TYPE_TIMEDIFF: {
|
|
||||||
pFunc->node.resType = (SDataType) { .bytes = tDataTypes[TSDB_DATA_TYPE_BIGINT].bytes, .type = TSDB_DATA_TYPE_BIGINT};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_TBNAME: {
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FUNCTION_TYPE_NOW:
|
|
||||||
// todo
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(0); // to found the fault ASAP.
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
|
@ -69,11 +69,11 @@ int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncTyp
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fmGetFuncResultType(SFunctionNode* pFunc) {
|
int32_t fmGetFuncResultType(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
|
||||||
if (pFunc->funcId < 0 || pFunc->funcId >= funcMgtBuiltinsNum) {
|
if (pFunc->funcId < 0 || pFunc->funcId >= funcMgtBuiltinsNum) {
|
||||||
return TSDB_CODE_FAILED;
|
return TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
return funcMgtBuiltins[pFunc->funcId].checkFunc(pFunc);
|
return funcMgtBuiltins[pFunc->funcId].translateFunc(pFunc, pErrBuf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
|
EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) {
|
||||||
|
|
|
@ -81,7 +81,6 @@ SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode);
|
||||||
|
|
||||||
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode);
|
SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode);
|
||||||
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode);
|
SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode);
|
||||||
SNodeList* addValueNodeFromTypeToList(SAstCreateContext* pCxt, SDataType dataType, SNodeList* pList);
|
|
||||||
|
|
||||||
SNode* createColumnNode(SAstCreateContext* pCxt, SToken* pTableAlias, SToken* pColumnName);
|
SNode* createColumnNode(SAstCreateContext* pCxt, SToken* pTableAlias, SToken* pColumnName);
|
||||||
SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral);
|
SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral);
|
||||||
|
@ -93,6 +92,7 @@ SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pL
|
||||||
SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
|
SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
|
||||||
SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
|
SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
|
||||||
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList);
|
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList);
|
||||||
|
SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType dt);
|
||||||
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
|
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
|
||||||
SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2);
|
SNode* createNodeListNodeEx(SAstCreateContext* pCxt, SNode* p1, SNode* p2);
|
||||||
SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias);
|
SNode* createRealTableNode(SAstCreateContext* pCxt, SToken* pDbName, SToken* pTableName, SToken* pTableAlias);
|
||||||
|
|
|
@ -535,13 +535,7 @@ expression(A) ::= pseudo_column(B).
|
||||||
expression(A) ::= column_reference(B). { A = B; }
|
expression(A) ::= column_reference(B). { A = B; }
|
||||||
expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
|
||||||
expression(A) ::= function_name(B) NK_LP NK_STAR(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, createNodeList(pCxt, createColumnNode(pCxt, NULL, &C)))); }
|
expression(A) ::= function_name(B) NK_LP NK_STAR(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, createNodeList(pCxt, createColumnNode(pCxt, NULL, &C)))); }
|
||||||
//for CAST function CAST(expr AS type_name)
|
expression(A) ::= CAST(B) NK_LP expression(C) AS type_name(D) NK_RP(E). { A = createRawExprNodeExt(pCxt, &B, &E, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, C), D)); }
|
||||||
expression(A) ::= function_name(B) NK_LP expression(C) AS type_name(D) NK_RP(E). {
|
|
||||||
SNodeList *p = createNodeList(pCxt, releaseRawExprNode(pCxt, C));
|
|
||||||
p = addValueNodeFromTypeToList(pCxt, D, p);
|
|
||||||
A = createRawExprNodeExt(pCxt, &B, &E, createFunctionNode(pCxt, &B, p));
|
|
||||||
}
|
|
||||||
//expression(A) ::= cast_expression(B). { A = B; }
|
|
||||||
//expression(A) ::= case_expression(B). { A = B; }
|
//expression(A) ::= case_expression(B). { A = B; }
|
||||||
expression(A) ::= subquery(B). { A = B; }
|
expression(A) ::= subquery(B). { A = B; }
|
||||||
expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); }
|
expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); }
|
||||||
|
|
|
@ -208,7 +208,9 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
||||||
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
SRawExprNode* pRawExpr = (SRawExprNode*)pNode;
|
||||||
SNode* pExpr = pRawExpr->pNode;
|
SNode* pExpr = pRawExpr->pNode;
|
||||||
if (nodesIsExprNode(pExpr)) {
|
if (nodesIsExprNode(pExpr)) {
|
||||||
strncpy(((SExprNode*)pExpr)->aliasName, pRawExpr->p, pRawExpr->n);
|
int32_t len = TMIN(sizeof(((SExprNode*)pExpr)->aliasName) - 1, pRawExpr->n);
|
||||||
|
strncpy(((SExprNode*)pExpr)->aliasName, pRawExpr->p, len);
|
||||||
|
((SExprNode*)pExpr)->aliasName[len] = '\0';
|
||||||
}
|
}
|
||||||
taosMemoryFreeClear(pNode);
|
taosMemoryFreeClear(pNode);
|
||||||
return pExpr;
|
return pExpr;
|
||||||
|
@ -253,33 +255,6 @@ SNode* createColumnNode(SAstCreateContext* pCxt, SToken* pTableAlias, SToken* pC
|
||||||
return (SNode*)col;
|
return (SNode*)col;
|
||||||
}
|
}
|
||||||
|
|
||||||
SNodeList* addValueNodeFromTypeToList(SAstCreateContext* pCxt, SDataType dataType, SNodeList* pList) {
|
|
||||||
char buf[64] = {0};
|
|
||||||
//add value node for type
|
|
||||||
snprintf(buf, sizeof(buf), "%u", dataType.type);
|
|
||||||
SToken token = {.type = TSDB_DATA_TYPE_SMALLINT, .n = strlen(buf), .z = buf};
|
|
||||||
SNode* pNode = createValueNode(pCxt, token.type, &token);
|
|
||||||
addNodeToList(pCxt, pList, pNode);
|
|
||||||
|
|
||||||
//add value node for bytes
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
int32_t bytes;
|
|
||||||
if (IS_VAR_DATA_TYPE(dataType.type)) {
|
|
||||||
bytes = (dataType.type == TSDB_DATA_TYPE_NCHAR) ? dataType.bytes * TSDB_NCHAR_SIZE : dataType.bytes;
|
|
||||||
bytes += VARSTR_HEADER_SIZE;
|
|
||||||
} else {
|
|
||||||
bytes = dataType.bytes;
|
|
||||||
}
|
|
||||||
snprintf(buf, sizeof(buf), "%d", bytes);
|
|
||||||
token.type = TSDB_DATA_TYPE_BIGINT;
|
|
||||||
token.n = strlen(buf);
|
|
||||||
token.z = buf;
|
|
||||||
pNode = createValueNode(pCxt, token.type, &token);
|
|
||||||
addNodeToList(pCxt, pList, pNode);
|
|
||||||
|
|
||||||
return pList;
|
|
||||||
}
|
|
||||||
|
|
||||||
SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) {
|
SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) {
|
||||||
SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
|
SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE);
|
||||||
CHECK_OUT_OF_MEM(val);
|
CHECK_OUT_OF_MEM(val);
|
||||||
|
@ -385,6 +360,15 @@ SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNod
|
||||||
return (SNode*)func;
|
return (SNode*)func;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType dt) {
|
||||||
|
SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
|
CHECK_OUT_OF_MEM(func);
|
||||||
|
strcpy(func->functionName, "cast");
|
||||||
|
func->node.resType = dt;
|
||||||
|
nodesListMakeAppend(&func->pParameterList, pExpr);
|
||||||
|
return (SNode*)func;
|
||||||
|
}
|
||||||
|
|
||||||
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList) {
|
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList) {
|
||||||
SNodeListNode* list = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST);
|
SNodeListNode* list = (SNodeListNode*)nodesMakeNode(QUERY_NODE_NODE_LIST);
|
||||||
CHECK_OUT_OF_MEM(list);
|
CHECK_OUT_OF_MEM(list);
|
||||||
|
|
|
@ -485,9 +485,9 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc)
|
||||||
if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) {
|
if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) {
|
||||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName);
|
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName);
|
||||||
}
|
}
|
||||||
int32_t code = fmGetFuncResultType(pFunc);
|
pCxt->errCode = fmGetFuncResultType(pFunc, pCxt->msgBuf.buf, pCxt->msgBuf.len);
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != pCxt->errCode) {
|
||||||
return generateDealNodeErrMsg(pCxt, code, pFunc->functionName);
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
if (fmIsAggFunc(pFunc->funcId) && beforeHaving(pCxt->currClause)) {
|
if (fmIsAggFunc(pFunc->funcId) && beforeHaving(pCxt->currClause)) {
|
||||||
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
|
return generateDealNodeErrMsg(pCxt, TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION);
|
||||||
|
|
|
@ -31,10 +31,6 @@ static char* getSyntaxErrFormat(int32_t errCode) {
|
||||||
return "Invalid value type : %s";
|
return "Invalid value type : %s";
|
||||||
case TSDB_CODE_PAR_INVALID_FUNTION:
|
case TSDB_CODE_PAR_INVALID_FUNTION:
|
||||||
return "Invalid function name : %s";
|
return "Invalid function name : %s";
|
||||||
case TSDB_CODE_PAR_FUNTION_PARA_NUM:
|
|
||||||
return "Invalid number of arguments : %s";
|
|
||||||
case TSDB_CODE_PAR_FUNTION_PARA_TYPE:
|
|
||||||
return "Inconsistent datatypes : %s";
|
|
||||||
case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION:
|
case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION:
|
||||||
return "There mustn't be aggregation";
|
return "There mustn't be aggregation";
|
||||||
case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT:
|
case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT:
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue