diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 64bcd6d898..73b4ec2a74 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -387,8 +387,18 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields) len += sprintf(str + len, "%lf", dv); } break; + case TSDB_DATA_TYPE_VARBINARY:{ + void* data = NULL; + uint32_t size = 0; + int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE); + if(taosAscii2Hex(row[i], charLen, &data, &size) < 0){ + break; + } + memcpy(str + len, data, size); + len += size; + taosMemoryFree(data); + }break; case TSDB_DATA_TYPE_BINARY: - case TSDB_DATA_TYPE_VARBINARY: case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_GEOMETRY: { int32_t charLen = varDataLen((char *)row[i] - VARSTR_HEADER_SIZE); diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index af6b3bcc8c..4098881b14 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -522,9 +522,9 @@ static char* processAlterTable(SMqMetaRsp* metaRsp) { buf = parseTagDatatoJson(vAlterTbReq.pTagVal); } else { if(vAlterTbReq.tagType == TSDB_DATA_TYPE_VARBINARY){ - buf = taosMemoryCalloc(vAlterTbReq.nTagVal + 1, 1); + buf = taosMemoryCalloc(vAlterTbReq.nTagVal*2 + 2 + 3, 1); }else{ - buf = taosMemoryCalloc(vAlterTbReq.nTagVal + 1, 1); + buf = taosMemoryCalloc(vAlterTbReq.nTagVal + 3, 1); } dataConverToStr(buf, vAlterTbReq.tagType, vAlterTbReq.pTagVal, vAlterTbReq.nTagVal, NULL); } diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 9a301b7f1c..e18c1f4c44 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -314,7 +314,7 @@ static int32_t translateInOutStr(SFunctionNode* pFunc, char* pErrBuf, int32_t le } SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0); - if (!IS_STR_DATA_TYPE(pPara1->resType.type)) { + if (TSDB_DATA_TYPE_VARBINARY == pPara1->resType.type || !IS_STR_DATA_TYPE(pPara1->resType.type)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -328,7 +328,7 @@ static int32_t translateTrimStr(SFunctionNode* pFunc, char* pErrBuf, int32_t len } SExprNode* pPara1 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0); - if (!IS_STR_DATA_TYPE(pPara1->resType.type)) { + if (TSDB_DATA_TYPE_VARBINARY == pPara1->resType.type || !IS_STR_DATA_TYPE(pPara1->resType.type)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -1824,6 +1824,10 @@ static int32_t translateLength(SFunctionNode* pFunc, char* pErrBuf, int32_t len) return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } + if (TSDB_DATA_TYPE_VARBINARY == ((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; } @@ -1852,6 +1856,10 @@ static int32_t translateConcatImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t for (int32_t i = 0; i < numOfParams; ++i) { SNode* pPara = nodesListGetNode(pFunc->pParameterList, i); uint8_t paraType = ((SExprNode*)pPara)->resType.type; + if (TSDB_DATA_TYPE_VARBINARY == paraType) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } + if (!IS_STR_DATA_TYPE(paraType) && !IS_NULL_TYPE(paraType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -1908,7 +1916,7 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) uint8_t para0Type = pPara0->resType.type; uint8_t para1Type = pPara1->resType.type; - if (!IS_STR_DATA_TYPE(para0Type) || !IS_INTEGER_TYPE(para1Type)) { + if (TSDB_DATA_TYPE_VARBINARY == para0Type || !IS_STR_DATA_TYPE(para0Type) || !IS_INTEGER_TYPE(para1Type)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -1936,6 +1944,12 @@ static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { // The number of parameters has been limited by the syntax definition + SExprNode* pPara0 = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0); + uint8_t para0Type = pPara0->resType.type; + if (TSDB_DATA_TYPE_VARBINARY == para0Type) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } + // The function return type has been set during syntax parsing uint8_t para2Type = pFunc->node.resType.type; @@ -2007,7 +2021,7 @@ static int32_t translateToUnixtimestamp(SFunctionNode* pFunc, char* pErrBuf, int } uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_STR_DATA_TYPE(para1Type)) { + if (para1Type == TSDB_DATA_TYPE_VARBINARY || !IS_STR_DATA_TYPE(para1Type)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } @@ -2141,7 +2155,7 @@ static int32_t translateToJson(SFunctionNode* pFunc, char* pErrBuf, int32_t len) } SExprNode* pPara = (SExprNode*)nodesListGetNode(pFunc->pParameterList, 0); - if (QUERY_NODE_VALUE != nodeType(pPara) || (!IS_VAR_DATA_TYPE(pPara->resType.type))) { + if (QUERY_NODE_VALUE != nodeType(pPara) || TSDB_DATA_TYPE_VARBINARY == pPara->resType.type || (!IS_VAR_DATA_TYPE(pPara->resType.type))) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index f85218c50a..3e95f843a7 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -518,7 +518,7 @@ SNode* createCastFunctionNode(SAstCreateContext* pCxt, SNode* pExpr, SDataType d CHECK_OUT_OF_MEM(func); strcpy(func->functionName, "cast"); func->node.resType = dt; - if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_GEOMETRY == dt.type) { + if (TSDB_DATA_TYPE_VARCHAR == dt.type || TSDB_DATA_TYPE_GEOMETRY == dt.type || TSDB_DATA_TYPE_VARBINARY == dt.type) { func->node.resType.bytes = func->node.resType.bytes + VARSTR_HEADER_SIZE; } else if (TSDB_DATA_TYPE_NCHAR == dt.type) { func->node.resType.bytes = func->node.resType.bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE; diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index b9af716929..8c6f9a71b2 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -964,6 +964,16 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp } break; } + case TSDB_DATA_TYPE_VARBINARY:{ + if (inputType == TSDB_DATA_TYPE_BINARY) { + int32_t len = TMIN(varDataLen(input), outputLen - VARSTR_HEADER_SIZE); + memcpy(varDataVal(output), varDataVal(input), len); + varDataSetLen(output, len); + }else{ + code = TSDB_CODE_FUNC_FUNTION_PARA_TYPE; + goto _end; + } + } case TSDB_DATA_TYPE_NCHAR: { int32_t outputCharLen = (outputLen - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE; int32_t len; diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 53b2e7acd9..e4303b2e15 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -351,7 +351,7 @@ ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/smaTest.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/sma_index.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml_TS-3724.py -#,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/varbinary.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/varbinary.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/sml.py -R ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/spread.py diff --git a/tools/shell/src/shellEngine.c b/tools/shell/src/shellEngine.c index 35ab86269d..72cf3cd1cc 100644 --- a/tools/shell/src/shellEngine.c +++ b/tools/shell/src/shellEngine.c @@ -409,7 +409,7 @@ void shellDumpFieldToFile(TdFilePtr pFile, const char *val, TAOS_FIELD *field, i if(taosAscii2Hex(val, length, &tmp, &size) < 0){ break; } - taosFprintfFile(pFile, "%s", tmp); + taosFprintfFile(pFile, "%s%s%s", quotationStr, tmp, quotationStr); taosMemoryFree(tmp); break; } diff --git a/utils/test/c/varbinary_test.c b/utils/test/c/varbinary_test.c index 74c50d66d9..bd73cbc0fc 100644 --- a/utils/test/c/varbinary_test.c +++ b/utils/test/c/varbinary_test.c @@ -147,13 +147,70 @@ int varbinary_test() { ASSERT(taos_errno(pRes) != 0); taos_free_result(pRes); -// pRes = taos_query(taos, "select * from stb where c2 contains 'ssd'"); -// ASSERT(taos_errno(pRes) != 0); -// taos_free_result(pRes); -// -// pRes = taos_query(taos, "select * from stb where c2 contains 'ssd'"); -// ASSERT(taos_errno(pRes) != 0); -// taos_free_result(pRes); + + // math function test, not support + pRes = taos_query(taos, "select abs(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select floor(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + // string function test, not support + pRes = taos_query(taos, "select length(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select ltrim(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select upper(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + + pRes = taos_query(taos, "select to_json(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select TO_UNIXTIMESTAMP(c2) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select cast(c2 as varchar(16)) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select cast(c3 as varbinary(16)) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select cast(c1 as varbinary(16)) from stb"); + ASSERT(taos_errno(pRes) != 0); + taos_free_result(pRes); + + // support first/last/last_row/count/hyperloglog/sample/tail/mode + pRes = taos_query(taos, "select first(c2) from stb"); + ASSERT(taos_errno(pRes) == 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select count(c2) from stb"); + ASSERT(taos_errno(pRes) == 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select sample(c2,2) from stb"); + ASSERT(taos_errno(pRes) == 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select mode(c2) from stb"); + ASSERT(taos_errno(pRes) == 0); + taos_free_result(pRes); + + pRes = taos_query(taos, "select cast(t2 as varbinary(16)) from stb"); + ASSERT(taos_errno(pRes) == 0); + taos_free_result(pRes); int numRows = 0; @@ -192,7 +249,6 @@ int varbinary_test() { ASSERT(numRows == 2); taos_free_result(pRes); - pRes = taos_query(taos, "select * from stb where c2 not between '\\x3e' and '\\x7F8290'"); GET_ROW_NUM ASSERT(numRows == 3);