diff --git a/include/libs/scalar/scalar.h b/include/libs/scalar/scalar.h index 4dbdb2e8bb8937849f24e15b9d7e08c67ea2e149..1902c11cc68097b63141d640ce7a8bdf4656d713 100644 --- a/include/libs/scalar/scalar.h +++ b/include/libs/scalar/scalar.h @@ -29,6 +29,7 @@ typedef struct SFilterInfo SFilterInfo; int32_t scalarCalculateConstants(SNode *pNode, SNode **pRes); int32_t scalarCalculate(SNode *pNode, SSDataBlock *pSrc, SScalarParam *pDst); int32_t scalarGetOperatorParamNum(EOperatorType type); +int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type); int32_t vectorGetConvertType(int32_t type1, int32_t type2); int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut); diff --git a/source/libs/function/inc/builtins.h b/source/libs/function/inc/builtins.h index 62f86de918036dff27ef7b1d43b9d2cace16da9b..598a28b2eb10afdbf38f58e57a7667b8d7eb5a99 100644 --- a/source/libs/function/inc/builtins.h +++ b/source/libs/function/inc/builtins.h @@ -46,6 +46,7 @@ typedef struct SBuiltinFuncDefinition { FExecGetEnv getEnvFunc; FExecInit initFunc; FExecProcess processFunc; + FScalarExecProcess sprocessFunc; FExecFinalize finalizeFunc; } SBuiltinFuncDefinition; diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 96e165f7886b866cee63db78c5bd4e2cf432dacf..73ce67bd2847b3f1b20769e1626514ad5a3646ee 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -36,7 +36,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .checkFunc = stubCheckAndGetResultType, .getEnvFunc = NULL, .initFunc = NULL, - .processFunc = NULL, + .sprocessFunc = NULL, .finalizeFunc = NULL } }; diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 887f65a6ea7ee4d56b976fc74bb8f801fe3d0677..c6330c6015b346c03e9477efa138f769f3c7ee8d 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -71,6 +71,14 @@ int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet) { return TSDB_CODE_SUCCESS; } +int32_t fmGetScalarFuncExecFuncs(int32_t funcId, SScalarFuncExecFuncs* pFpSet) { + if (funcId < 0 || funcId >= funcMgtBuiltinsNum) { + return TSDB_CODE_FAILED; + } + pFpSet->process = funcMgtBuiltins[funcId].sprocessFunc; + return TSDB_CODE_SUCCESS; +} + bool fmIsAggFunc(int32_t funcId) { if (funcId < 0 || funcId >= funcMgtBuiltinsNum) { return false; diff --git a/source/libs/scalar/inc/sclInt.h b/source/libs/scalar/inc/sclInt.h index 3cfea6890f20cdaf9c2cb2ab92affed68312ff2f..41ee90667e012dde68d9c7179a05b3595001182f 100644 --- a/source/libs/scalar/inc/sclInt.h +++ b/source/libs/scalar/inc/sclInt.h @@ -28,6 +28,8 @@ typedef struct SScalarCtx { SHashObj *pRes; /* element is SScalarParam */ } SScalarCtx; + +#define SCL_DATA_TYPE_DUMMY_HASH 9000 #define SCL_DEFAULT_OP_NUM 10 #define sclFatal(...) qFatal(__VA_ARGS__) diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 8f8fc25d180693201630db83e7d7d9d7b0a9f14c..6a59f27d1334766d899ed49cf84a9ecea5c896b4 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -1706,69 +1706,6 @@ int32_t filterHandleValueExtInfo(SFilterUnit* unit, char extInfo) { return TSDB_CODE_SUCCESS; } -int32_t fltGenerateSetFromList(void **data, void *pNode, uint32_t type) { - SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false); - if (NULL == pObj) { - fltError("taosHashInit failed, size:%d", 256); - FLT_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - - taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(type)); - - int32_t code = 0; - SNodeListNode *nodeList = (SNodeListNode *)pNode; - SListCell *cell = nodeList->pNodeList->pHead; - SScalarParam in = {.num = 1}, out = {.num = 1, .type = type}; - int8_t dummy = 0; - int32_t bufLen = 60; - out.data = malloc(bufLen); - int32_t len = 0; - void *buf = NULL; - - for (int32_t i = 0; i < nodeList->pNodeList->length; ++i) { - SValueNode *valueNode = (SValueNode *)cell->pNode; - - if (valueNode->node.resType.type != type) { - in.type = valueNode->node.resType.type; - in.bytes = valueNode->node.resType.bytes; - in.data = nodesGetValueFromNode(valueNode); - - code = vectorConvertImpl(&in, &out); - if (code) { - fltError("convert from %d to %d failed", in.type, out.type); - FLT_ERR_JRET(code); - } - - if (IS_VAR_DATA_TYPE(type)) { - len = varDataLen(out.data); - } else { - len = tDataTypes[type].bytes; - } - - buf = out.data; - } else { - buf = nodesGetValueFromNode(valueNode); - len = valueNode->node.resType.bytes; - } - - if (taosHashPut(pObj, buf, (size_t)len, &dummy, sizeof(dummy))) { - fltError("taosHashPut failed"); - FLT_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); - } - } - - tfree(out.data); - *data = pObj; - - return TSDB_CODE_SUCCESS; - -_return: - - tfree(out.data); - taosHashCleanup(pObj); - - FLT_RET(code); -} int32_t fltInitValFieldData(SFilterInfo *info) { for (uint32_t i = 0; i < info->unitNum; ++i) { @@ -1793,7 +1730,7 @@ int32_t fltInitValFieldData(SFilterInfo *info) { } if (unit->compare.optr == TSDB_RELATION_IN) { - FLT_ERR_RET(fltGenerateSetFromList((void **)&fi->data, fi->desc, type)); + FLT_ERR_RET(scalarGenerateSetFromList((void **)&fi->data, fi->desc, type)); if (fi->data == NULL) { fltError("failed to convert in param"); FLT_ERR_RET(TSDB_CODE_QRY_APP_ERROR); diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index aa29b0270997c142f1d85f1797691a5dd7765de9..daddaa6c2d28b9d5d14adbd09412fad8f3e96139 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -7,13 +7,79 @@ #include "sclInt.h" int32_t scalarGetOperatorParamNum(EOperatorType type) { - if (OP_TYPE_IS_NULL == type || OP_TYPE_IS_NOT_NULL == type) { + if (OP_TYPE_IS_NULL == type || OP_TYPE_IS_NOT_NULL == type || OP_TYPE_IS_TRUE == type || OP_TYPE_IS_NOT_TRUE == type + || OP_TYPE_IS_FALSE == type || OP_TYPE_IS_NOT_FALSE == type || OP_TYPE_IS_UNKNOWN == type || OP_TYPE_IS_NOT_UNKNOWN == type) { return 1; } return 2; } +int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type) { + SHashObj *pObj = taosHashInit(256, taosGetDefaultHashFunction(type), true, false); + if (NULL == pObj) { + sclError("taosHashInit failed, size:%d", 256); + SCL_ERR_RET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + + taosHashSetEqualFp(pObj, taosGetDefaultEqualFunction(type)); + + int32_t code = 0; + SNodeListNode *nodeList = (SNodeListNode *)pNode; + SListCell *cell = nodeList->pNodeList->pHead; + SScalarParam in = {.num = 1}, out = {.num = 1, .type = type}; + int8_t dummy = 0; + int32_t bufLen = 60; + out.data = malloc(bufLen); + int32_t len = 0; + void *buf = NULL; + + for (int32_t i = 0; i < nodeList->pNodeList->length; ++i) { + SValueNode *valueNode = (SValueNode *)cell->pNode; + + if (valueNode->node.resType.type != type) { + in.type = valueNode->node.resType.type; + in.bytes = valueNode->node.resType.bytes; + in.data = nodesGetValueFromNode(valueNode); + + code = vectorConvertImpl(&in, &out); + if (code) { + sclError("convert from %d to %d failed", in.type, out.type); + SCL_ERR_JRET(code); + } + + if (IS_VAR_DATA_TYPE(type)) { + len = varDataLen(out.data); + } else { + len = tDataTypes[type].bytes; + } + + buf = out.data; + } else { + buf = nodesGetValueFromNode(valueNode); + len = valueNode->node.resType.bytes; + } + + if (taosHashPut(pObj, buf, (size_t)len, &dummy, sizeof(dummy))) { + sclError("taosHashPut failed"); + SCL_ERR_JRET(TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } + + tfree(out.data); + *data = pObj; + + return TSDB_CODE_SUCCESS; + +_return: + + tfree(out.data); + taosHashCleanup(pObj); + + SCL_RET(code); +} + + void sclFreeRes(SHashObj *res) { SScalarParam *p = NULL; void *pIter = taosHashIterate(res, NULL); @@ -47,7 +113,15 @@ int32_t sclInitParam(SNode* node, SScalarParam *param, SScalarCtx *ctx, int32_t } case QUERY_NODE_NODE_LIST: { SNodeListNode *nodeList = (SNodeListNode *)node; - //TODO BUILD HASH + if (nodeList->pNodeList->length <= 0) { + sclError("invalid length in nodeList, length:%d", nodeList->pNodeList->length); + SCL_RET(TSDB_CODE_QRY_INVALID_INPUT); + } + + SCL_ERR_RET(scalarGenerateSetFromList(¶m->data, node, nodeList->dataType.type)); + param->num = 1; + param->type = SCL_DATA_TYPE_DUMMY_HASH; + break; } case QUERY_NODE_COLUMN_REF: { @@ -291,6 +365,7 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp SCL_ERR_RET(sclInitOperatorParams(¶ms, node, ctx, &rowNum)); output->type = node->node.resType.type; + output->num = rowNum; output->data = calloc(rowNum, tDataTypes[output->type].bytes); if (NULL == output->data) { sclError("calloc %d failed", (int32_t)rowNum * tDataTypes[output->type].bytes); @@ -303,17 +378,21 @@ int32_t sclExecOperator(SOperatorNode *node, SScalarCtx *ctx, SScalarParam *outp SScalarParam* pLeft = ¶ms[0]; SScalarParam* pRight = paramNum > 1 ? ¶ms[1] : NULL; + void *data = output->data; + for (int32_t i = 0; i < rowNum; ++i) { OperatorFn(pLeft, pRight, output->data, TSDB_ORDER_ASC); - sclParamMoveNext(output, 1); + sclParamMoveNext(output, 1); sclParamMoveNext(pLeft, 1); if (pRight) { sclParamMoveNext(pRight, 1); } } + output->data = data; + return TSDB_CODE_SUCCESS; _return: diff --git a/source/libs/scalar/src/sclvector.c b/source/libs/scalar/src/sclvector.c index 5b2ec7902ce4876a886ae604ad9786430c523780..a957788903fff2913e89bbac2e6245d11b0fda27 100644 --- a/source/libs/scalar/src/sclvector.c +++ b/source/libs/scalar/src/sclvector.c @@ -258,31 +258,7 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { switch (outType) { case TSDB_DATA_TYPE_BOOL: - if (inType == TSDB_DATA_TYPE_BINARY) { - for (int32_t i = 0; i < pIn->num; ++i) { - GET_TYPED_DATA(*(bool *)output, bool, TSDB_DATA_TYPE_USMALLINT, &varDataLen(input)); - - input += varDataLen(input) + VARSTR_HEADER_SIZE; - output += sizeof(bool); - } - } else if (inType == TSDB_DATA_TYPE_NCHAR) { - for (int32_t i = 0; i < pIn->num; ++i) { - GET_TYPED_DATA(*(bool *)output, bool, TSDB_DATA_TYPE_USMALLINT, &varDataLen(input)); - - input += varDataLen(input) + VARSTR_HEADER_SIZE; - output += tDataTypes[outType].bytes; - } - } else { - for (int32_t i = 0; i < pIn->num; ++i) { - uint64_t value = 0; - GET_TYPED_DATA(value, uint64_t, inType, input); - SET_TYPED_DATA(output, outType, value); - - input += tDataTypes[inType].bytes; - output += tDataTypes[outType].bytes; - } - } - break; + case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: case TSDB_DATA_TYPE_INT: case TSDB_DATA_TYPE_BIGINT: @@ -295,17 +271,21 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input) >= bufSize) { - bufSize = varDataLen(input) + 1; - tmp = realloc(tmp, bufSize); + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input) >= bufSize) { + bufSize = varDataLen(input) + 1; + tmp = realloc(tmp, bufSize); + } + + memcpy(tmp, varDataVal(input), varDataLen(input)); + tmp[varDataLen(input)] = 0; + + int64_t value = strtoll(tmp, NULL, 10); + SET_TYPED_DATA(output, outType, value); } - memcpy(tmp, varDataVal(input), varDataLen(input)); - tmp[varDataLen(input)] = 0; - - int64_t value = strtoll(tmp, NULL, 10); - SET_TYPED_DATA(output, outType, value); - input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; } @@ -319,21 +299,25 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { - bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; - tmp = realloc(tmp, bufSize); - } - - int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); - if (len < 0){ - qError("castConvert taosUcs4ToMbs error 1"); - tfree(tmp); - return TSDB_CODE_QRY_APP_ERROR; - } + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { + bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; + tmp = realloc(tmp, bufSize); + } - tmp[len] = 0; - int64_t value = strtoll(tmp, NULL, 10); - SET_TYPED_DATA(output, outType, value); + int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); + if (len < 0){ + qError("castConvert taosUcs4ToMbs error 1"); + tfree(tmp); + return TSDB_CODE_QRY_APP_ERROR; + } + + tmp[len] = 0; + int64_t value = strtoll(tmp, NULL, 10); + SET_TYPED_DATA(output, outType, value); + } input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; @@ -351,6 +335,7 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } } break; + case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_UBIGINT: @@ -362,16 +347,20 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input) >= bufSize) { - bufSize = varDataLen(input) + 1; - tmp = realloc(tmp, bufSize); + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input) >= bufSize) { + bufSize = varDataLen(input) + 1; + tmp = realloc(tmp, bufSize); + } + + memcpy(tmp, varDataVal(input), varDataLen(input)); + tmp[varDataLen(input)] = 0; + uint64_t value = strtoull(tmp, NULL, 10); + SET_TYPED_DATA(output, outType, value); } - memcpy(tmp, varDataVal(input), varDataLen(input)); - tmp[varDataLen(input)] = 0; - uint64_t value = strtoull(tmp, NULL, 10); - SET_TYPED_DATA(output, outType, value); - input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; } @@ -385,21 +374,25 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { - bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; - tmp = realloc(tmp, bufSize); - } - - int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); - if (len < 0){ - qError("castConvert taosUcs4ToMbs error 1"); - tfree(tmp); - return TSDB_CODE_QRY_APP_ERROR; - } + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { + bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; + tmp = realloc(tmp, bufSize); + } - tmp[len] = 0; - uint64_t value = strtoull(tmp, NULL, 10); - SET_TYPED_DATA(output, outType, value); + int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); + if (len < 0){ + qError("castConvert taosUcs4ToMbs error 1"); + tfree(tmp); + return TSDB_CODE_QRY_APP_ERROR; + } + + tmp[len] = 0; + uint64_t value = strtoull(tmp, NULL, 10); + SET_TYPED_DATA(output, outType, value); + } input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; @@ -408,9 +401,13 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { tfree(tmp); } else { for (int32_t i = 0; i < pIn->num; ++i) { - uint64_t value = 0; - GET_TYPED_DATA(value, uint64_t, inType, input); - SET_TYPED_DATA(output, outType, value); + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + uint64_t value = 0; + GET_TYPED_DATA(value, uint64_t, inType, input); + SET_TYPED_DATA(output, outType, value); + } input += tDataTypes[inType].bytes; output += tDataTypes[outType].bytes; @@ -427,17 +424,21 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input) >= bufSize) { - bufSize = varDataLen(input) + 1; - tmp = realloc(tmp, bufSize); + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input) >= bufSize) { + bufSize = varDataLen(input) + 1; + tmp = realloc(tmp, bufSize); + } + + memcpy(tmp, varDataVal(input), varDataLen(input)); + tmp[varDataLen(input)] = 0; + + double value = strtod(tmp, NULL); + SET_TYPED_DATA(output, outType, value); } - memcpy(tmp, varDataVal(input), varDataLen(input)); - tmp[varDataLen(input)] = 0; - - double value = strtod(tmp, NULL); - SET_TYPED_DATA(output, outType, value); - input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; } @@ -451,21 +452,25 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { } for (int32_t i = 0; i < pIn->num; ++i) { - if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { - bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; - tmp = realloc(tmp, bufSize); - } - - int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); - if (len < 0){ - qError("castConvert taosUcs4ToMbs error 1"); - tfree(tmp); - return TSDB_CODE_QRY_APP_ERROR; - } + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + if (varDataLen(input)* TSDB_NCHAR_SIZE >= bufSize) { + bufSize = varDataLen(input) * TSDB_NCHAR_SIZE + 1; + tmp = realloc(tmp, bufSize); + } - tmp[len] = 0; - double value = strtod(tmp, NULL); - SET_TYPED_DATA(output, outType, value); + int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), tmp); + if (len < 0){ + qError("castConvert taosUcs4ToMbs error 1"); + tfree(tmp); + return TSDB_CODE_QRY_APP_ERROR; + } + + tmp[len] = 0; + double value = strtod(tmp, NULL); + SET_TYPED_DATA(output, outType, value); + } input += varDataLen(input) + VARSTR_HEADER_SIZE; output += tDataTypes[outType].bytes; @@ -474,9 +479,13 @@ int32_t vectorConvertImpl(SScalarParam* pIn, SScalarParam* pOut) { tfree(tmp); } else { for (int32_t i = 0; i < pIn->num; ++i) { - int64_t value = 0; - GET_TYPED_DATA(value, int64_t, inType, input); - SET_TYPED_DATA(output, outType, value); + if (isNull(input, inType)) { + assignVal(output, getNullValue(outType), 0, outType); + } else { + int64_t value = 0; + GET_TYPED_DATA(value, int64_t, inType, input); + SET_TYPED_DATA(output, outType, value); + } input += tDataTypes[inType].bytes; output += tDataTypes[outType].bytes; @@ -1121,6 +1130,12 @@ void vectorNotNull(SScalarParam* pLeft, SScalarParam* pRight, void *out, int32_t } } +void vectorIsTrue(SScalarParam* pLeft, SScalarParam* pRight, void *out, int32_t _ord) { + SScalarParam output = {.data = out, .num = pLeft->num, .type = TSDB_DATA_TYPE_BOOL}; + + vectorConvertImpl(pLeft, &output); +} + _bin_scalar_fn_t getBinScalarOperatorFn(int32_t binFunctionId) { switch (binFunctionId) { @@ -1166,6 +1181,8 @@ _bin_scalar_fn_t getBinScalarOperatorFn(int32_t binFunctionId) { return vectorBitAnd; case OP_TYPE_BIT_OR: return vectorBitOr; + case OP_TYPE_IS_TRUE: + return vectorIsTrue; default: assert(0); return NULL; diff --git a/source/libs/scalar/test/CMakeLists.txt b/source/libs/scalar/test/CMakeLists.txt index a9af1ece30ac51a8059f03f4592b0a37cbc9724c..9dfbf3b5e882277e5568dbd7d0360964d75122ad 100644 --- a/source/libs/scalar/test/CMakeLists.txt +++ b/source/libs/scalar/test/CMakeLists.txt @@ -8,7 +8,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST) ADD_EXECUTABLE(scalarTest ${SOURCE_LIST}) TARGET_LINK_LIBRARIES( scalarTest - PUBLIC os util common gtest qcom function nodes + PUBLIC os util common gtest qcom function nodes scalar ) TARGET_INCLUDE_DIRECTORIES( diff --git a/source/libs/scalar/test/scalarTests.cpp b/source/libs/scalar/test/scalarTests.cpp index 38fe072f9e487583fcc55101acedf21ff42ea96b..66be5645f28812b999727962e71c0804e68cd2da 100644 --- a/source/libs/scalar/test/scalarTests.cpp +++ b/source/libs/scalar/test/scalarTests.cpp @@ -36,15 +36,220 @@ #include "stub.h" #include "addr_any.h" #include "scalar.h" +#include "nodes.h" namespace { +int64_t scltLeftV = 21, scltRightV = 10; +double scltLeftVd = 21.0, scltRightVd = 10.0; + +void scltMakeValueNode(SNode **pNode, int32_t dataType, void *value) { + SNode *node = nodesMakeNode(QUERY_NODE_VALUE); + SValueNode *vnode = (SValueNode *)node; + vnode->node.resType.type = dataType; + + if (IS_VAR_DATA_TYPE(dataType)) { + vnode->datum.p = (char *)malloc(varDataTLen(value)); + varDataCopy(vnode->datum.p, value); + vnode->node.resType.bytes = varDataLen(value); + } else { + vnode->node.resType.bytes = tDataTypes[dataType].bytes; + assignVal((char *)nodesGetValueFromNode(vnode), (const char *)value, 0, dataType); + } + + *pNode = (SNode *)vnode; +} + +void scltMakeOpNode(SNode **pNode, EOperatorType opType, int32_t resType, SNode *pLeft, SNode *pRight) { + SNode *node = nodesMakeNode(QUERY_NODE_OPERATOR); + SOperatorNode *onode = (SOperatorNode *)node; + onode->node.resType.type = resType; + onode->node.resType.bytes = tDataTypes[resType].bytes; + + onode->opType = opType; + onode->pLeft = pLeft; + onode->pRight = pRight; + + *pNode = (SNode *)onode; +} + +void scltMakeListNode(SNode **pNode, SNodeList *list, int32_t resType) { + SNode *node = nodesMakeNode(QUERY_NODE_NODE_LIST); + SNodeListNode *lnode = (SNodeListNode *)node; + lnode->dataType.type = resType; + lnode->pNodeList = list; + + *pNode = (SNode *)lnode; +} + + +} + +TEST(constantTest, bigint_add_bigint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_BIGINT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_BIGINT, &scltRightV); + scltMakeOpNode(&opNode, OP_TYPE_ADD, TSDB_DATA_TYPE_DOUBLE, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_DOUBLE); + ASSERT_EQ(v->datum.d, (scltLeftV + scltRightV)); +} + +TEST(constantTest, double_sub_bigint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_DOUBLE, &scltLeftVd); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_BIGINT, &scltRightV); + scltMakeOpNode(&opNode, OP_TYPE_SUB, TSDB_DATA_TYPE_DOUBLE, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_DOUBLE); + ASSERT_EQ(v->datum.d, (scltLeftVd - scltRightV)); } -TEST(scalarTest, func) { +TEST(constantTest, tinyint_and_smallint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_TINYINT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &scltRightV); + scltMakeOpNode(&opNode, OP_TYPE_BIT_AND, TSDB_DATA_TYPE_BIGINT, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BIGINT); + ASSERT_EQ(v->datum.i, (int64_t)scltLeftV & (int64_t)scltRightV); +} + +TEST(constantTest, bigint_or_double) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_BIGINT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_DOUBLE, &scltRightVd); + scltMakeOpNode(&opNode, OP_TYPE_BIT_OR, TSDB_DATA_TYPE_BIGINT, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BIGINT); + ASSERT_EQ(v->datum.i, (int64_t)scltLeftV | (int64_t)scltRightVd); +} + +TEST(constantTest, int_greater_double) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_INT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_DOUBLE, &scltRightVd); + scltMakeOpNode(&opNode, OP_TYPE_GREATER_THAN, TSDB_DATA_TYPE_BOOL, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, scltLeftV > scltRightVd); +} + +TEST(constantTest, int_greater_equal_binary) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + char binaryStr[64] = {0}; + sprintf(&binaryStr[2], "%d", scltRightV); + varDataSetLen(binaryStr, strlen(&binaryStr[2])); + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_INT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_BINARY, binaryStr); + scltMakeOpNode(&opNode, OP_TYPE_GREATER_THAN, TSDB_DATA_TYPE_BOOL, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, scltLeftV > scltRightVd); +} +TEST(constantTest, tinyint_lower_ubigint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_TINYINT, &scltLeftV); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_UBIGINT, &scltRightV); + scltMakeOpNode(&opNode, OP_TYPE_LOWER_THAN, TSDB_DATA_TYPE_BOOL, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, scltLeftV < scltRightV); } +TEST(constantTest, usmallint_lower_equal_ubigint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + int32_t leftv = 1, rightv = 1; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_USMALLINT, &leftv); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_UBIGINT, &rightv); + scltMakeOpNode(&opNode, OP_TYPE_LOWER_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, leftv <= rightv); +} + +TEST(constantTest, int_equal_smallint) { + SNode *pLeft = NULL, *pRight = NULL, *opNode = NULL, *res = NULL; + int32_t leftv = 1, rightv = 1; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_INT, &leftv); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &rightv); + scltMakeOpNode(&opNode, OP_TYPE_EQUAL, TSDB_DATA_TYPE_BOOL, pLeft, pRight); + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, leftv == rightv); +} + +TEST(constantTest, int_in_smallint) { + SNode *pLeft = NULL, *pRight = NULL, *listNode = NULL, *res = NULL, *opNode = NULL; + int32_t leftv = 1, rightv1 = 1,rightv2 = 2,rightv3 = 3; + scltMakeValueNode(&pLeft, TSDB_DATA_TYPE_INT, &leftv); + SNodeList* list = nodesMakeList(); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &rightv1); + nodesListAppend(list, pRight); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &rightv2); + nodesListAppend(list, pRight); + scltMakeValueNode(&pRight, TSDB_DATA_TYPE_SMALLINT, &rightv3); + nodesListAppend(list, pRight); + scltMakeListNode(&listNode,list, TSDB_DATA_TYPE_SMALLINT); + scltMakeOpNode(opNode, OP_TYPE_IN, TSDB_DATA_TYPE_BOOL, pLeft, listNode) + + int32_t code = scalarCalculateConstants(opNode, &res); + ASSERT_EQ(code, 0); + ASSERT_TRUE(res); + ASSERT_EQ(nodeType(res), QUERY_NODE_VALUE); + SValueNode *v = (SValueNode *)res; + ASSERT_EQ(v->node.resType.type, TSDB_DATA_TYPE_BOOL); + ASSERT_EQ(v->datum.b, true); +} + + + int main(int argc, char** argv) { srand(time(NULL));