diff --git a/packaging/tools/makeclient.sh b/packaging/tools/makeclient.sh index 4c3278e41b0c51e86d84c3e200092b4554e6523c..92d3f8a89cf3d985ca9149fdb9d910949285d5d8 100755 --- a/packaging/tools/makeclient.sh +++ b/packaging/tools/makeclient.sh @@ -43,9 +43,11 @@ if [ "$osType" != "Darwin" ]; then if [ "$pagMode" == "lite" ]; then #strip ${build_dir}/bin/taosd strip ${build_dir}/bin/taos - bin_files="${build_dir}/bin/taos ${script_dir}/remove_client.sh" + bin_files="${build_dir}/bin/taos \ + ${script_dir}/remove_client.sh" else - bin_files="${script_dir}/remove_client.sh \ + bin_files="${build_dir}/bin/taos \ + ${script_dir}/remove_client.sh \ ${script_dir}/set_core.sh \ ${script_dir}/get_client.sh" #${script_dir}/get_client.sh ${script_dir}/taosd-dump-cfg.gdb" diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c index 90379e6f7e5ccb5da12e6007ca0e94cfc859ee53..85c2215a2e71746889403e60ed09279e64574750 100644 --- a/src/client/src/tscLocal.c +++ b/src/client/src/tscLocal.c @@ -128,12 +128,13 @@ static int32_t tscSetValueToResObj(SSqlObj *pSql, int32_t rowLen) { // type length int32_t bytes = pSchema[i].bytes; pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 2); - if (pSchema[i].type == TSDB_DATA_TYPE_BINARY || pSchema[i].type == TSDB_DATA_TYPE_NCHAR) { + + if (pSchema[i].type == TSDB_DATA_TYPE_BINARY){ bytes -= VARSTR_HEADER_SIZE; - - if (pSchema[i].type == TSDB_DATA_TYPE_NCHAR) { - bytes = bytes / TSDB_NCHAR_SIZE; - } + } + else if(pSchema[i].type == TSDB_DATA_TYPE_NCHAR || pSchema[i].type == TSDB_DATA_TYPE_JSON) { + bytes -= VARSTR_HEADER_SIZE; + bytes = bytes / TSDB_NCHAR_SIZE; } *(int32_t *)(pRes->data + tscFieldInfoGetOffset(pQueryInfo, 2) * totalNumOfRows + pField->bytes * i) = bytes; diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 063333d9cf72111826309939a818938b18879060..b045c566f1a72b8f0ca970d8e30d1b0e6486be68 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -4519,13 +4519,16 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, if (TSDB_FUNC_IS_SCALAR(functionId)) { code = validateSQLExprItem(pCmd, pParamElem->pNode, pQueryInfo, pList, childrenTypes + i, uid, childrenHeight+i); if (code != TSDB_CODE_SUCCESS) { - free(childrenTypes); + tfree(childrenTypes); + tfree(childrenHeight); return code; } } if (!TSDB_FUNC_IS_SCALAR(functionId) && (pParamElem->pNode->type == SQL_NODE_EXPR || pParamElem->pNode->type == SQL_NODE_SQLFUNCTION)) { + tfree(childrenTypes); + tfree(childrenHeight); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } @@ -4547,6 +4550,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, *height = maxChildrenHeight + 1; if (anyChildAgg && anyChildScalar) { + tfree(childrenTypes); + tfree(childrenHeight); return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1); } if (anyChildAgg) { @@ -4558,7 +4563,8 @@ static int32_t validateSQLExprItemSQLFunc(SSqlCmd* pCmd, tSqlExpr* pExpr, *type = SQLEXPR_TYPE_AGG; } } - free(childrenTypes); + tfree(childrenTypes); + tfree(childrenHeight); //end if param list is not null } else { if (TSDB_FUNC_IS_SCALAR(functionId)) { @@ -6869,7 +6875,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { tscError("json type error, should be string"); return invalidOperationMsg(pMsg, msg25); } - if (pItem->pVar.nType > TSDB_MAX_JSON_TAGS_LEN / TSDB_NCHAR_SIZE) { + if (pItem->pVar.nLen > TSDB_MAX_JSON_TAGS_LEN / TSDB_NCHAR_SIZE) { tscError("json tag too long"); return invalidOperationMsg(pMsg, msg14); } diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 585865fb23adb9b5c8c6c7f5f1367a4532f12d41..e96e3c16da84b3ffc25b33e3864c4e38dcc3977f 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -774,11 +774,12 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo memcpy(dst, p, varDataTLen(p)); } else if (varDataLen(p) > 0) { int32_t length = taosUcs4ToMbs(varDataVal(p), varDataLen(p), varDataVal(dst)); - varDataSetLen(dst, length); - - if (length == 0) { + if (length <= 0) { tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); } + if (length >= 0){ + varDataSetLen(dst, length); + } } else { varDataSetLen(dst, 0); } @@ -809,18 +810,23 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo varDataSetLen(dst, strlen(varDataVal(dst))); }else if (type == TSDB_DATA_TYPE_JSON) { int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), varDataVal(dst)); - varDataSetLen(dst, length); - if (length == 0) { + + if (length <= 0) { tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); } + if (length >= 0){ + varDataSetLen(dst, length); + } }else if (type == TSDB_DATA_TYPE_NCHAR) { // value -> "value" *(char*)varDataVal(dst) = '\"'; int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), POINTER_SHIFT(varDataVal(dst), CHAR_BYTES)); - *(char*)(POINTER_SHIFT(varDataVal(dst), length + CHAR_BYTES)) = '\"'; - varDataSetLen(dst, length + CHAR_BYTES*2); - if (length == 0) { + if (length <= 0) { tscError("charset:%s to %s. val:%s convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, (char*)p); } + if (length >= 0){ + varDataSetLen(dst, length + CHAR_BYTES*2); + *(char*)(POINTER_SHIFT(varDataVal(dst), length + CHAR_BYTES)) = '\"'; + } }else if (type == TSDB_DATA_TYPE_DOUBLE) { double jsonVd = *(double*)(realData); sprintf(varDataVal(dst), "%.9lf", jsonVd); @@ -5515,10 +5521,10 @@ int parseJsontoTagData(char* json, SKVRowBuilder* kvRowBuilder, char* errMsg, in char *tagVal = calloc(strlen(jsonValue) * TSDB_NCHAR_SIZE + TSDB_NCHAR_SIZE, 1); *tagVal = jsonType2DbType(0, item->type); // type char* tagData = POINTER_SHIFT(tagVal,CHAR_BYTES); - if (!taosMbsToUcs4(jsonValue, strlen(jsonValue), varDataVal(tagData), + if (strlen(jsonValue) > 0 && !taosMbsToUcs4(jsonValue, strlen(jsonValue), varDataVal(tagData), (int32_t)(strlen(jsonValue) * TSDB_NCHAR_SIZE), &outLen)) { - tscError("json string error:%s|%s", strerror(errno), jsonValue); - retCode = tscSQLSyntaxErrMsg(errMsg, "serizelize json error", NULL); + tscError("charset:%s to %s. val:%s, errno:%s, convert failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, jsonValue, strerror(errno)); + retCode = tscSQLSyntaxErrMsg(errMsg, "charset convert json error", NULL); free(tagVal); goto end; } diff --git a/src/common/src/texpr.c b/src/common/src/texpr.c index 63a19c5c1b74028b8536982b0b2445c06de121b4..db3bec2ddfeee60a90df33cae4c9770bfdb7c46f 100644 --- a/src/common/src/texpr.c +++ b/src/common/src/texpr.c @@ -27,6 +27,7 @@ #include "tskiplist.h" #include "texpr.h" #include "tarithoperator.h" +#include "tulog.h" static int32_t exprValidateMathNode(tExprNode *pExpr); static int32_t exprValidateStringConcatNode(tExprNode *pExpr); @@ -1274,6 +1275,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out } else if (inputType == TSDB_DATA_TYPE_NCHAR) { char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1); int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData); + if (len < 0){ + uError("castConvert taosUcs4ToMbs error 1"); + tfree(newColData); + return; + } newColData[len] = 0; *(int64_t *)output = strtoll(newColData, NULL, 10); tfree(newColData); @@ -1291,6 +1297,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out } else if (inputType == TSDB_DATA_TYPE_NCHAR) { char *newColData = calloc(1, outputBytes * TSDB_NCHAR_SIZE + 1); int len = taosUcs4ToMbs(varDataVal(input), varDataLen(input), newColData); + if (len < 0){ + uError("castConvert taosUcs4ToMbs error 2"); + tfree(newColData); + return; + } newColData[len] = 0; *(int64_t *)output = strtoull(newColData, NULL, 10); tfree(newColData); @@ -1332,11 +1343,19 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out if (inputType == TSDB_DATA_TYPE_BOOL) { char tmp[8] = {0}; int32_t len = sprintf(tmp, "%.*s", ncharSize, *(int8_t*)input ? "true" : "false"); - taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + bool ret = taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + if(!ret) { + uError("castConvert1 taosMbsToUcs4 error"); + return; + } varDataSetLen(output, len); } else if (inputType == TSDB_DATA_TYPE_BINARY) { int32_t len = ncharSize > varDataLen(input) ? varDataLen(input) : ncharSize; - taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + bool ret = taosMbsToUcs4(input + VARSTR_HEADER_SIZE, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + if(!ret) { + uError("castConvert2 taosMbsToUcs4 error"); + return; + } varDataSetLen(output, len); } else if (inputType == TSDB_DATA_TYPE_TIMESTAMP) { assert(0); @@ -1348,7 +1367,11 @@ void castConvert(int16_t inputType, int16_t inputBytes, char *input, int16_t Out char tmp[400] = {0}; NUM_TO_STRING(inputType, input, sizeof(tmp), tmp); int32_t len = (int32_t)(ncharSize > strlen(tmp) ? strlen(tmp) : ncharSize); - taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + bool ret = taosMbsToUcs4(tmp, len, varDataVal(output), outputBytes - VARSTR_HEADER_SIZE, &len); + if(!ret) { + uError("castConvert3 taosMbsToUcs4 error"); + return; + } varDataSetLen(output, len); } break; diff --git a/src/common/src/tvariant.c b/src/common/src/tvariant.c index ee85d2f0086bb2676cb8699ad6bc2acaa33c5fbb..0d00856f9be76ee917d12ff7435142d6d55ccecf 100644 --- a/src/common/src/tvariant.c +++ b/src/common/src/tvariant.c @@ -23,6 +23,7 @@ #include "ttype.h" #include "tutil.h" #include "tvariant.h" +#include "tulog.h" #define SET_EXT_INFO(converted, res, minv, maxv, exti) do { \ if (converted == NULL || exti == NULL || *converted == false) { break; } \ @@ -359,8 +360,12 @@ int32_t tVariantToString(tVariant *pVar, char *dst) { case TSDB_DATA_TYPE_NCHAR: { dst[0] = '\''; - taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1); - int32_t len = (int32_t)strlen(dst); + int32_t len = taosUcs4ToMbs(pVar->wpz, (twcslen(pVar->wpz) + 1) * TSDB_NCHAR_SIZE, dst + 1); + if (len < 0){ + uError("castConvert1 taosUcs4ToMbs error"); + return 0 ; + } + len = (int32_t)strlen(dst); dst[len] = '\''; dst[len + 1] = 0; return len + 1; @@ -428,11 +433,17 @@ static int32_t toBinary(tVariant *pVariant, char **pDest, int32_t *pDestSize) { pBuf = realloc(pBuf, newSize + 1); } - taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf); + int32_t len = taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, pBuf); + if (len < 0){ + uError("castConvert1 taosUcs4ToMbs error"); + } free(pVariant->wpz); pBuf[newSize] = 0; } else { - taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest); + int32_t len = taosUcs4ToMbs(pVariant->wpz, (int32_t)newSize, *pDest); + if (len < 0){ + uError("castConvert1 taosUcs4ToMbs error"); + } } } else { diff --git a/src/connector/C#/src/TDengineDriver/TDengineDriver.cs b/src/connector/C#/src/TDengineDriver/TDengineDriver.cs index 42bba438522db2a1c238609036e2b5be8b37929f..15e0ca0841c0022439c00fc1b7357b770ccb14f6 100644 --- a/src/connector/C#/src/TDengineDriver/TDengineDriver.cs +++ b/src/connector/C#/src/TDengineDriver/TDengineDriver.cs @@ -398,5 +398,8 @@ namespace TDengineDriver IntPtr stmtErrPrt = StmtErrPtr(stmt); return Marshal.PtrToStringAnsi(stmtErrPrt); } + + [DllImport("taos", EntryPoint = "taos_fetch_lengths", CallingConvention = CallingConvention.Cdecl)] + static extern public IntPtr FetchLengths(IntPtr taos); } } diff --git a/src/connector/C#/src/test/Cases/Cases.csproj b/src/connector/C#/src/test/Cases/Cases.csproj index f2ae6938fb4b8c58d9bb657e5fb504814068e92e..57c0dd8f7d363e9da4ae580751cacf706f714883 100644 --- a/src/connector/C#/src/test/Cases/Cases.csproj +++ b/src/connector/C#/src/test/Cases/Cases.csproj @@ -9,4 +9,8 @@ net5.0 + + true + ..\doc\FunctionTest.XML + diff --git a/src/connector/C#/src/test/Cases/FetchLength.cs b/src/connector/C#/src/test/Cases/FetchLength.cs new file mode 100644 index 0000000000000000000000000000000000000000..b5c5c4ecadcd1ff67060a62ac6cfb460e65a530d --- /dev/null +++ b/src/connector/C#/src/test/Cases/FetchLength.cs @@ -0,0 +1,44 @@ +using System; +using Test.UtilsTools; +using System.Collections.Generic; + +namespace Cases +{ + + public class FetchLengthCase + { + /// xiaolei + /// TestRetrieveBinary + /// TD-12103 C# connector fetch_row with binary data retrieving error + /// FetchLength.cs + /// pass or failed + public void TestRetrieveBinary(IntPtr conn) + { + string sql1 = "create stable stb1 (ts timestamp, name binary(10)) tags(n int);"; + string sql2 = "insert into tb1 using stb1 tags(1) values(now, 'log');"; + string sql3 = "insert into tb2 using stb1 tags(2) values(now, 'test');"; + string sql4 = "insert into tb3 using stb1 tags(3) values(now, 'db02');"; + string sql5 = "insert into tb4 using stb1 tags(4) values(now, 'db3');"; + + string sql6 = "select distinct(name) from stb1;";// + + UtilsTools.ExecuteQuery(conn, sql1); + UtilsTools.ExecuteQuery(conn, sql2); + UtilsTools.ExecuteQuery(conn, sql3); + UtilsTools.ExecuteQuery(conn, sql4); + UtilsTools.ExecuteQuery(conn, sql5); + + IntPtr resPtr = IntPtr.Zero; + resPtr = UtilsTools.ExecuteQuery(conn, sql6); + List> result = UtilsTools.GetResultSet(resPtr); + + List colname = result[0]; + List data = result[1]; + UtilsTools.AssertEqual("db3", data[0]); + UtilsTools.AssertEqual("log", data[1]); + UtilsTools.AssertEqual("db02", data[2]); + UtilsTools.AssertEqual("test", data[3]); + + } + } +} diff --git a/src/connector/C#/src/test/Cases/Program.cs b/src/connector/C#/src/test/Cases/Program.cs index a1b47f3890134040d3060fdb7b1e8d3beed4b7dd..89f878e994aa35977fc69c5576bca0ec21c41882 100644 --- a/src/connector/C#/src/test/Cases/Program.cs +++ b/src/connector/C#/src/test/Cases/Program.cs @@ -1,64 +1,67 @@ -using System; -using Test.UtilsTools; -using Cases; - -namespace Cases.EntryPoint -{ - class Program - { - - static void Main(string[] args) - { - IntPtr conn = IntPtr.Zero; - IntPtr stmt = IntPtr.Zero; - IntPtr res = IntPtr.Zero; - - conn = UtilsTools.TDConnection("127.0.0.1", "root", "taosdata", "", 0); - UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); - UtilsTools.ExecuteQuery(conn, "create database if not exists csharp keep 3650"); - UtilsTools.ExecuteQuery(conn, "use csharp"); - - Console.WriteLine("====================StableColumnByColumn==================="); - StableColumnByColumn columnByColumn = new StableColumnByColumn(); - columnByColumn.Test(conn, "stablecolumnbycolumn"); - Console.WriteLine("====================StmtStableQuery==================="); - StmtStableQuery stmtStableQuery = new StmtStableQuery(); - stmtStableQuery.Test(conn, "stablecolumnbycolumn"); - - Console.WriteLine("====================StableMutipleLine==================="); - StableMutipleLine mutipleLine = new StableMutipleLine(); - mutipleLine.Test(conn, "stablemutipleline"); - - //================================================================================ - - Console.WriteLine("====================NtableSingleLine==================="); - NtableSingleLine ntableSingleLine = new NtableSingleLine(); - ntableSingleLine.Test(conn, "stablesingleline"); - - Console.WriteLine("====================NtableMutipleLine==================="); - NtableMutipleLine ntableMutipleLine = new NtableMutipleLine(); - ntableMutipleLine.Test(conn, "ntablemutipleline"); - Console.WriteLine("====================StmtNtableQuery==================="); - StmtNtableQuery stmtNtableQuery = new StmtNtableQuery(); - stmtNtableQuery.Test(conn, "ntablemutipleline"); - - Console.WriteLine("====================NtableColumnByColumn==================="); - NtableColumnByColumn ntableColumnByColumn = new NtableColumnByColumn(); - ntableColumnByColumn.Test(conn, "ntablecolumnbycolumn"); - - Console.WriteLine("====================fetchfeilds==================="); - FetchFields fetchFields = new FetchFields(); - fetchFields.Test(conn,"fetchfeilds"); - - Console.WriteLine("===================JsonTagTest===================="); - JsonTagTest jsonTagTest = new JsonTagTest(); - jsonTagTest.Test(conn); - - // UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); - UtilsTools.CloseConnection(conn); - UtilsTools.ExitProgram(); - - - } - } -} +using System; +using Test.UtilsTools; +using Cases; + +namespace Cases.EntryPoint +{ + class Program + { + + static void Main(string[] args) + { + IntPtr conn = IntPtr.Zero; + IntPtr stmt = IntPtr.Zero; + IntPtr res = IntPtr.Zero; + + conn = UtilsTools.TDConnection("127.0.0.1", "root", "taosdata", "", 0); + UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); + UtilsTools.ExecuteQuery(conn, "create database if not exists csharp keep 3650"); + UtilsTools.ExecuteQuery(conn, "use csharp"); + + Console.WriteLine("====================StableColumnByColumn==================="); + StableColumnByColumn columnByColumn = new StableColumnByColumn(); + columnByColumn.Test(conn, "stablecolumnbycolumn"); + Console.WriteLine("====================StmtStableQuery==================="); + StmtStableQuery stmtStableQuery = new StmtStableQuery(); + stmtStableQuery.Test(conn, "stablecolumnbycolumn"); + + Console.WriteLine("====================StableMutipleLine==================="); + StableMutipleLine mutipleLine = new StableMutipleLine(); + mutipleLine.Test(conn, "stablemutipleline"); + + //================================================================================ + + Console.WriteLine("====================NtableSingleLine==================="); + NtableSingleLine ntableSingleLine = new NtableSingleLine(); + ntableSingleLine.Test(conn, "stablesingleline"); + + Console.WriteLine("====================NtableMutipleLine==================="); + NtableMutipleLine ntableMutipleLine = new NtableMutipleLine(); + ntableMutipleLine.Test(conn, "ntablemutipleline"); + Console.WriteLine("====================StmtNtableQuery==================="); + StmtNtableQuery stmtNtableQuery = new StmtNtableQuery(); + stmtNtableQuery.Test(conn, "ntablemutipleline"); + + Console.WriteLine("====================NtableColumnByColumn==================="); + NtableColumnByColumn ntableColumnByColumn = new NtableColumnByColumn(); + ntableColumnByColumn.Test(conn, "ntablecolumnbycolumn"); + + Console.WriteLine("====================fetchfeilds==================="); + FetchFields fetchFields = new FetchFields(); + fetchFields.Test(conn, "fetchfeilds"); + + Console.WriteLine("===================JsonTagTest===================="); + JsonTagTest jsonTagTest = new JsonTagTest(); + jsonTagTest.Test(conn); + + Console.WriteLine("====================fetchLengthCase==================="); + FetchLengthCase fetchLengthCase = new FetchLengthCase(); + fetchLengthCase.TestRetrieveBinary(conn); + + UtilsTools.ExecuteQuery(conn, "drop database if exists csharp"); + UtilsTools.CloseConnection(conn); + UtilsTools.ExitProgram(); + + } + } +} diff --git a/src/connector/C#/src/test/Cases/Utils.cs b/src/connector/C#/src/test/Cases/Utils.cs index a549d75b16f76539b0f19d73eab576d0d9d582db..7877601e0adbc38c186bd44456ceb3005d806ff1 100644 --- a/src/connector/C#/src/test/Cases/Utils.cs +++ b/src/connector/C#/src/test/Cases/Utils.cs @@ -35,7 +35,6 @@ namespace Test.UtilsTools else { Console.WriteLine(sql.ToString() + " success"); - } return res; } @@ -83,9 +82,13 @@ namespace Test.UtilsTools IntPtr rowdata; StringBuilder builder = new StringBuilder(); + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) { queryRows++; + IntPtr colLengthPtr = TDengine.FetchLengths(res); + int[] colLengthArr = new int[fieldCount]; + Marshal.Copy(colLengthPtr, colLengthArr, 0, fieldCount); for (int fields = 0; fields < fieldCount; ++fields) { TDengineMeta meta = metas[fields]; @@ -131,7 +134,7 @@ namespace Test.UtilsTools builder.Append(v7); break; case TDengineDataType.TSDB_DATA_TYPE_BINARY: - string v8 = Marshal.PtrToStringAnsi(data); + string v8 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]); builder.Append(v8); break; case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: @@ -139,7 +142,7 @@ namespace Test.UtilsTools builder.Append(v9); break; case TDengineDataType.TSDB_DATA_TYPE_NCHAR: - string v10 = Marshal.PtrToStringAnsi(data); + string v10 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]); builder.Append(v10); break; case TDengineDataType.TSDB_DATA_TYPE_JSONTAG: @@ -164,6 +167,117 @@ namespace Test.UtilsTools TDengine.FreeResult(res); Console.WriteLine(""); } + public static List> GetResultSet(IntPtr res) + { + List> result = new List>(); + List colName = new List(); + List dataRaw = new List(); + long queryRows = 0; + if (!IsValidResult(res)) + { + ExitProgram(); + } + + int fieldCount = TDengine.FieldCount(res); + List metas = TDengine.FetchFields(res); + + for (int j = 0; j < metas.Count; j++) + { + TDengineMeta meta = (TDengineMeta)metas[j]; + colName.Add(meta.name); + } + result.Add(colName); + + IntPtr rowdata; + while ((rowdata = TDengine.FetchRows(res)) != IntPtr.Zero) + { + queryRows++; + IntPtr colLengthPtr = TDengine.FetchLengths(res); + int[] colLengthArr = new int[fieldCount]; + Marshal.Copy(colLengthPtr, colLengthArr, 0, fieldCount); + + for (int fields = 0; fields < fieldCount; ++fields) + { + TDengineMeta meta = metas[fields]; + int offset = IntPtr.Size * fields; + IntPtr data = Marshal.ReadIntPtr(rowdata, offset); + + if (data == IntPtr.Zero) + { + dataRaw.Add("NULL"); + continue; + } + + switch ((TDengineDataType)meta.type) + { + case TDengineDataType.TSDB_DATA_TYPE_BOOL: + bool v1 = Marshal.ReadByte(data) == 0 ? false : true; + dataRaw.Add(v1.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_TINYINT: + byte v2 = Marshal.ReadByte(data); + dataRaw.Add(v2.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_SMALLINT: + short v3 = Marshal.ReadInt16(data); + dataRaw.Add(v3.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_INT: + int v4 = Marshal.ReadInt32(data); + dataRaw.Add(v4.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_BIGINT: + long v5 = Marshal.ReadInt64(data); + dataRaw.Add(v5.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_FLOAT: + float v6 = (float)Marshal.PtrToStructure(data, typeof(float)); + dataRaw.Add(v6.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_DOUBLE: + double v7 = (double)Marshal.PtrToStructure(data, typeof(double)); + dataRaw.Add(v7.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_BINARY: + string v8 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]); + dataRaw.Add(v8); + break; + case TDengineDataType.TSDB_DATA_TYPE_TIMESTAMP: + long v9 = Marshal.ReadInt64(data); + dataRaw.Add(v9.ToString()); + break; + case TDengineDataType.TSDB_DATA_TYPE_NCHAR: + string v10 = Marshal.PtrToStringAnsi(data, colLengthArr[fields]); + dataRaw.Add(v10); + break; + } + } + + } + result.Add(dataRaw); + + if (TDengine.ErrorNo(res) != 0) + { + Console.Write("Query is not complete, Error {0:G}", TDengine.ErrorNo(res), TDengine.Error(res)); + } + TDengine.FreeResult(res); Console.WriteLine(""); + return result; + } + + public static bool IsValidResult(IntPtr res) + { + if ((res == IntPtr.Zero) || (TDengine.ErrorNo(res) != 0)) + { + if (res != IntPtr.Zero) + { + Console.Write("reason: " + TDengine.Error(res)); + return false; + } + Console.WriteLine(""); + return false; + } + return true; + } public static void CloseConnection(IntPtr conn) { if (conn != IntPtr.Zero) @@ -183,6 +297,18 @@ namespace Test.UtilsTools List metas = TDengine.FetchFields(res); return metas; } + public static void AssertEqual(string expectVal, string actualVal) + { + if (expectVal == actualVal) + { + Console.WriteLine("{0}=={1} pass", expectVal, actualVal); + } + else + { + Console.WriteLine("{0}=={1} failed", expectVal, actualVal); + ExitProgram(); + } + } public static void ExitProgram() { TDengine.Cleanup(); diff --git a/src/connector/C#/src/test/XUnitTest/XUnitTest.csproj b/src/connector/C#/src/test/XUnitTest/XUnitTest.csproj index 97d13e5e9e74abada2efa27d64e57adbe5459023..997a9d6fe072c01ffeb45a32773f8c76a530825c 100644 --- a/src/connector/C#/src/test/XUnitTest/XUnitTest.csproj +++ b/src/connector/C#/src/test/XUnitTest/XUnitTest.csproj @@ -2,10 +2,14 @@ net5.0 - false + + true + ..\doc\UnitTest.XML + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java index d8ac10d839651bb476a8688f28917aa356b5b1fe..9f573452b1aacbaaf8593433a0b0c5986ad9d3aa 100644 --- a/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java +++ b/src/connector/jdbc/src/main/java/com/taosdata/jdbc/TSDBResultSetRowData.java @@ -443,16 +443,29 @@ public class TSDBResultSetRowData { case 0: { milliseconds = ts; fracNanoseconds = (int) (ts * 1_000_000 % 1_000_000_000); + fracNanoseconds = fracNanoseconds < 0 ? 1_000_000_000 + fracNanoseconds : fracNanoseconds; break; } case 1: { milliseconds = ts / 1_000; fracNanoseconds = (int) (ts * 1_000 % 1_000_000_000); + if (fracNanoseconds < 0) { + if (milliseconds == 0 ){ + milliseconds = -1; + } + fracNanoseconds += 1_000_000_000; + } break; } case 2: { milliseconds = ts / 1_000_000; fracNanoseconds = (int) (ts % 1_000_000_000); + if (fracNanoseconds < 0) { + if (milliseconds == 0 ){ + milliseconds = -1; + } + fracNanoseconds += 1_000_000_000; + } break; } default: { diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java index bfffaa4a129dc7fe19a92c34abbcc886d5e4e22f..4f7f123f5c8b135e757919c8913f1f1bb032d98e 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/cases/DatetimeBefore1970Test.java @@ -1,23 +1,36 @@ package com.taosdata.jdbc.cases; +import com.taosdata.jdbc.annotation.CatalogRunner; +import com.taosdata.jdbc.annotation.Description; +import com.taosdata.jdbc.annotation.TestTarget; import com.taosdata.jdbc.utils.TimestampUtil; import org.junit.*; +import org.junit.runner.RunWith; import java.sql.*; +@RunWith(CatalogRunner.class) +@TestTarget(alias = "negative value convert to timestamp", author = "huolibo", version = "2.0.37") public class DatetimeBefore1970Test { private static final String host = "127.0.0.1"; private Connection conn; @Test - public void test() throws SQLException { + @Description("millisecond") + public void msTest() throws SQLException { + conn = createEnvironment("ms"); + long now = System.currentTimeMillis(); try (Statement stmt = conn.createStatement()) { // given + // before + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.001')"); stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999')"); + // zero stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); - stmt.executeUpdate("insert into weather(ts) values('1970-01-01 08:00:00.000')"); - stmt.executeUpdate("insert into weather(ts) values('1970-01-01 07:59:59.999')"); + //after + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.001')"); + stmt.executeUpdate("insert into weather(ts) values(" + now + ")"); ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); ResultSetMetaData metaData = rs.getMetaData(); Assert.assertEquals(2, metaData.getColumnCount()); @@ -26,44 +39,221 @@ public class DatetimeBefore1970Test { rs.next(); // then Timestamp ts = rs.getTimestamp("ts"); - Assert.assertEquals("1969-12-31 23:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(-24 * 60 * 60 * 1000 + 1, ts.getTime()); // when rs.next(); // then ts = rs.getTimestamp("ts"); - Assert.assertEquals("1970-01-01 00:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(-1, ts.getTime()); // when rs.next(); // then ts = rs.getTimestamp("ts"); - Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(0, ts.getTime()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(1, ts.getTime()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(now, ts.getTime()); + } + } + + @Test + @Description("microsecond") + public void usTest() throws SQLException { + conn = createEnvironment("us"); + long now = System.currentTimeMillis(); + try (Statement stmt = conn.createStatement()) { + // given + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000001')"); + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000001')"); + stmt.executeUpdate("insert into weather(ts) values(" + now + ")"); + ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(2, metaData.getColumnCount()); + + // when + rs.next(); + // then + Timestamp ts = rs.getTimestamp("ts"); + Assert.assertEquals(-24 * 60 * 60 * 1000, ts.getTime()); + Assert.assertEquals(1_000, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(-1, ts.getTime()); + Assert.assertEquals(999_999_000, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(0, ts.getTime()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(0, ts.getTime()); + Assert.assertEquals(1_000, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + String s = String.valueOf(now); + Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 3)), ts.getTime()); + Assert.assertEquals(Long.parseLong(s.substring(s.length() - 6) + "000"), ts.getNanos()); + } + } + + @Test + @Description("nanosecond") + public void nanoTest() throws SQLException { + conn = createEnvironment("ns"); + long now = System.currentTimeMillis() * 1000_000L + System.nanoTime() % 1000_000L; + try (Statement stmt = conn.createStatement()) { + // given + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000000123')"); + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999999')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000001')"); + stmt.executeUpdate("insert into weather(ts) values(" + now + ")"); + ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(2, metaData.getColumnCount()); + + // when + rs.next(); + // then + Timestamp ts = rs.getTimestamp("ts"); + Assert.assertEquals(-24 * 60 * 60 * 1_000, ts.getTime()); + Assert.assertEquals(123, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(-1, ts.getTime()); + Assert.assertEquals(999999999, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(0, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals(1, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + String s = String.valueOf(now); + Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 6)), ts.getTime()); + Assert.assertEquals(Long.parseLong(s.substring(s.length() - 9)), ts.getNanos()); + } + } + + @Test + @Ignore + @Description("nanosecond convert timestamp when timezone is asia shanghai") + public void asiaShanghaiTest() throws SQLException { + conn = createEnvironment("ns"); + long now = System.currentTimeMillis() * 1000_000L + System.nanoTime() % 1000_000L; + try (Statement stmt = conn.createStatement()) { + // given + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 00:00:00.000000123')"); + stmt.executeUpdate("insert into weather(ts) values('1969-12-31 23:59:59.999999999')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000')"); + stmt.executeUpdate("insert into weather(ts) values('1970-01-01 00:00:00.000000001')"); + stmt.executeUpdate("insert into weather(ts) values(" + now + ")"); + ResultSet rs = stmt.executeQuery("select * from weather order by ts asc"); + ResultSetMetaData metaData = rs.getMetaData(); + Assert.assertEquals(2, metaData.getColumnCount()); + + // when + rs.next(); + // then + Timestamp ts = rs.getTimestamp("ts"); + Assert.assertEquals("1969-12-31 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(123, ts.getNanos()); // when rs.next(); // then ts = rs.getTimestamp("ts"); Assert.assertEquals("1970-01-01 07:59:59.999", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(999999999, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(0, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + Assert.assertEquals("1970-01-01 08:00:00.000", TimestampUtil.longToDatetime(ts.getTime())); + Assert.assertEquals(1, ts.getNanos()); + + // when + rs.next(); + // then + ts = rs.getTimestamp("ts"); + String s = String.valueOf(now); + Assert.assertEquals(Long.parseLong(s.substring(0, s.length() - 6)), ts.getTime()); + Assert.assertEquals(Long.parseLong(s.substring(s.length() - 9)), ts.getNanos()); } } - @Before - public void before() throws SQLException { - conn = DriverManager.getConnection("jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata"); + private Connection createEnvironment(String precision) throws SQLException { + String url = "jdbc:TAOS://" + host + ":6030/?user=root&password=taosdata&timezone=UTC"; + String createSql = "create database if not exists test_timestamp keep 36500"; + if (!isEmpty(precision)) { + createSql += " precision '" + precision + "'"; + } + conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement(); stmt.execute("drop database if exists test_timestamp"); - stmt.execute("create database if not exists test_timestamp keep 36500"); + stmt.execute(createSql); stmt.execute("use test_timestamp"); stmt.execute("create table weather(ts timestamp,f1 float)"); stmt.close(); + return conn; + } + + private boolean isEmpty(String string) { + return null == string || string.trim().equals(""); } @After public void after() throws SQLException { - Statement stmt = conn.createStatement(); - stmt.execute("drop database if exists test_timestamp"); - if (conn != null) + if (conn != null) { + Statement stmt = conn.createStatement(); + stmt.execute("drop database if exists test_timestamp"); + stmt.close(); conn.close(); + } } } diff --git a/src/inc/taoserror.h b/src/inc/taoserror.h index 8700cf246a91655c307bbb4c3c2c111d3271fc67..fb70badb862943a0259b2dc94bf52b0a452bd714 100644 --- a/src/inc/taoserror.h +++ b/src/inc/taoserror.h @@ -274,7 +274,6 @@ int32_t* taosGetErrno(); #define TSDB_CODE_TDB_IVLD_TAG_VAL TAOS_DEF_ERROR_CODE(0, 0x0615) //"TSDB invalid tag value") #define TSDB_CODE_TDB_NO_CACHE_LAST_ROW TAOS_DEF_ERROR_CODE(0, 0x0616) //"TSDB no cache last row data") #define TSDB_CODE_TDB_INCOMPLETE_DFILESET TAOS_DEF_ERROR_CODE(0, 0x0617) //"TSDB incomplete DFileSet") -#define TSDB_CODE_TDB_NO_JSON_TAG_KEY TAOS_DEF_ERROR_CODE(0, 0x0618) //"TSDB no tag json key") // query #define TSDB_CODE_QRY_INVALID_QHANDLE TAOS_DEF_ERROR_CODE(0, 0x0700) //"Invalid handle") diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 2ba143b147d5924eb07aeb9bb2fd321b5d519573..6346e743081a6594fcc9e8d8001ae18e3f90ac92 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1942,7 +1942,7 @@ static SQLFunctionCtx* createSQLFunctionCtx(SQueryRuntimeEnv* pRuntimeEnv, SExpr for (int32_t j = 0; j < pCtx->numOfParams; ++j) { int16_t type = pSqlExpr->param[j].nType; int16_t bytes = pSqlExpr->param[j].nLen; - if (pSqlExpr->functionId == TSDB_FUNC_STDDEV_DST) { + if (pSqlExpr->functionId == TSDB_FUNC_STDDEV_DST || pSqlExpr->functionId == TSDB_FUNC_TS_COMP) { continue; } diff --git a/src/query/src/qExtbuffer.c b/src/query/src/qExtbuffer.c index cc214b953303e3b10b053bbe0c183eaee520e32a..9d174b0389d74073b5989af5a8fd7c26d5fd80dd 100644 --- a/src/query/src/qExtbuffer.c +++ b/src/query/src/qExtbuffer.c @@ -1040,7 +1040,10 @@ void tColModelDisplay(SColumnModel *pModel, void *pData, int32_t numOfRows, int3 break; case TSDB_DATA_TYPE_NCHAR: { char buf[4096] = {0}; - taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); + int32_t len = taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); + if (len < 0){ + qError("castConvert1 taosUcs4ToMbs error"); + } printf("%s\t", buf); break; } @@ -1092,7 +1095,10 @@ void tColModelDisplayEx(SColumnModel *pModel, void *pData, int32_t numOfRows, in break; case TSDB_DATA_TYPE_NCHAR: { char buf[128] = {0}; - taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); + int32_t len = taosUcs4ToMbs(val, pModel->pFields[j].field.bytes, buf); + if (len < 0){ + qError("castConvert1 taosUcs4ToMbs error"); + } printf("%s\t", buf); break; } diff --git a/src/query/src/qFilter.c b/src/query/src/qFilter.c index 05ecda2a51f33c00130bcad0c5aa7139e7429a48..6869017e116ab9fe9dce30fbb028242f0e990a4b 100644 --- a/src/query/src/qFilter.c +++ b/src/query/src/qFilter.c @@ -1899,12 +1899,20 @@ int32_t filterInitValFieldData(SFilterInfo *info) { (unit->compare.optr == TSDB_RELATION_MATCH || unit->compare.optr == TSDB_RELATION_NMATCH)){ char newValData[TSDB_REGEX_STRING_DEFAULT_LEN * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE] = {0}; int32_t len = taosUcs4ToMbs(varDataVal(fi->data), varDataLen(fi->data), varDataVal(newValData)); + if (len < 0){ + qError("filterInitValFieldData taosUcs4ToMbs error 1"); + return TSDB_CODE_FAILED; + } varDataSetLen(newValData, len); varDataCopy(fi->data, newValData); }else if(type == TSDB_DATA_TYPE_JSON && (unit->compare.optr == TSDB_RELATION_MATCH || unit->compare.optr == TSDB_RELATION_NMATCH)){ char newValData[TSDB_REGEX_STRING_DEFAULT_LEN * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE] = {0}; int32_t len = taosUcs4ToMbs(((tVariant*)(fi->desc))->pz, ((tVariant*)(fi->desc))->nLen, newValData); + if (len < 0){ + qError("filterInitValFieldData taosUcs4ToMbs error 2"); + return TSDB_CODE_FAILED; + } memcpy(((tVariant*)(fi->desc))->pz, newValData, len); ((tVariant*)(fi->desc))->nLen = len; } @@ -3025,6 +3033,11 @@ static void doJsonCompare(SFilterComUnit *cunit, int8_t *result, void* colData){ }else{ char *newColData = calloc(cunit->dataSize * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 1); int len = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), varDataVal(newColData)); + if (len < 0){ + qError("castConvert1 taosUcs4ToMbs error"); + tfree(newColData); + return; + } varDataSetLen(newColData, len); tVariant* val = cunit->valData; char newValData[TSDB_REGEX_STRING_DEFAULT_LEN * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE] = {0}; @@ -3113,9 +3126,13 @@ bool filterExecuteImplMisc(void *pinfo, int32_t numOfRows, int8_t** p, SDataStat if(info->cunits[uidx].dataType == TSDB_DATA_TYPE_NCHAR && (info->cunits[uidx].optr == TSDB_RELATION_MATCH || info->cunits[uidx].optr == TSDB_RELATION_NMATCH)){ char *newColData = calloc(info->cunits[uidx].dataSize * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 1); - int len = taosUcs4ToMbs(varDataVal(colData), varDataLen(colData), varDataVal(newColData)); - varDataSetLen(newColData, len); - (*p)[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, newColData, info->cunits[uidx].valData); + int32_t len = taosUcs4ToMbs(varDataVal(colData), varDataLen(colData), varDataVal(newColData)); + if (len < 0){ + qError("castConvert1 taosUcs4ToMbs error"); + }else{ + varDataSetLen(newColData, len); + (*p)[i] = filterDoCompare(gDataCompare[info->cunits[uidx].func], info->cunits[uidx].optr, newColData, info->cunits[uidx].valData); + } tfree(newColData); }else if(info->cunits[uidx].dataType == TSDB_DATA_TYPE_JSON){ doJsonCompare(&(info->cunits[uidx]), &(*p)[i], colData); @@ -3170,9 +3187,13 @@ bool filterExecuteImpl(void *pinfo, int32_t numOfRows, int8_t** p, SDataStatis * } else { if(cunit->dataType == TSDB_DATA_TYPE_NCHAR && (cunit->optr == TSDB_RELATION_MATCH || cunit->optr == TSDB_RELATION_NMATCH)){ char *newColData = calloc(cunit->dataSize * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE, 1); - int len = taosUcs4ToMbs(varDataVal(colData), varDataLen(colData), varDataVal(newColData)); - varDataSetLen(newColData, len); - (*p)[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, newColData, cunit->valData); + int32_t len = taosUcs4ToMbs(varDataVal(colData), varDataLen(colData), varDataVal(newColData)); + if (len < 0){ + qError("castConvert1 taosUcs4ToMbs error"); + }else{ + varDataSetLen(newColData, len); + (*p)[i] = filterDoCompare(gDataCompare[cunit->func], cunit->optr, newColData, cunit->valData); + } tfree(newColData); }else if(cunit->dataType == TSDB_DATA_TYPE_JSON){ doJsonCompare(cunit, &(*p)[i], colData); @@ -3577,7 +3598,11 @@ int32_t filterConverNcharColumns(SFilterInfo* info, int32_t rows, bool *gotNchar char *src = FILTER_GET_COL_FIELD_DATA(fi, j); char *dst = FILTER_GET_COL_FIELD_DATA(&nfi, j); int32_t len = 0; - taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); + bool ret = taosMbsToUcs4(varDataVal(src), varDataLen(src), varDataVal(dst), bufSize, &len); + if(!ret) { + qError("filterConverNcharColumns taosMbsToUcs4 error"); + return TSDB_CODE_FAILED; + } varDataLen(dst) = len; } diff --git a/src/tsdb/src/tsdbMeta.c b/src/tsdb/src/tsdbMeta.c index 229d684e8364a4c1aabc5cf1825e45cc698a1de3..a095bff61e05822f6389a51671f98fc5a33e0bbe 100644 --- a/src/tsdb/src/tsdbMeta.c +++ b/src/tsdb/src/tsdbMeta.c @@ -1463,6 +1463,7 @@ static void *tsdbDecodeTable(void *buf, STable **pRTable) { tsdbFreeTable(pTable); return NULL; } + taosHashSetFreeFp(pTable->jsonKeyMap, taosArrayDestroyForHash); }else{ pTable->pIndex = tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), (uint8_t)(colBytes(pCol)), NULL, SL_ALLOW_DUP_KEY, getTagIndexKey); diff --git a/src/tsdb/src/tsdbRead.c b/src/tsdb/src/tsdbRead.c index f3241cd0e0ea4c7929c6d0c82df339a513299c7d..be734ce0cccad6827cba4e2c27d0be478af92af3 100644 --- a/src/tsdb/src/tsdbRead.c +++ b/src/tsdb/src/tsdbRead.c @@ -4243,20 +4243,28 @@ char* parseTagDatatoJson(void *p){ } cJSON_AddItemToObject(json, tagJsonKey, value); }else if(type == TSDB_DATA_TYPE_NCHAR) { - char *tagJsonValue = calloc(varDataLen(realData), 1); - int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), tagJsonValue); - if (length < 0) { - tsdbError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, - (char*)val); + cJSON* value = NULL; + if (varDataLen(realData) > 0){ + char *tagJsonValue = calloc(varDataLen(realData), 1); + int32_t length = taosUcs4ToMbs(varDataVal(realData), varDataLen(realData), tagJsonValue); + if (length < 0) { + tsdbError("charset:%s to %s. val:%s convert json value failed.", DEFAULT_UNICODE_ENCODEC, tsCharset, + (char*)val); + free(tagJsonValue); + goto end; + } + value = cJSON_CreateString(tagJsonValue); free(tagJsonValue); - goto end; - } - cJSON* value = cJSON_CreateString(tagJsonValue); - free(tagJsonValue); - if (value == NULL) - { - goto end; + if (value == NULL) + { + goto end; + } + }else if(varDataLen(realData) == 0){ + value = cJSON_CreateString(""); + }else{ + assert(0); } + cJSON_AddItemToObject(json, tagJsonKey, value); }else if(type == TSDB_DATA_TYPE_DOUBLE){ double jsonVd = *(double*)(realData); diff --git a/src/util/src/terror.c b/src/util/src/terror.c index 3853d2e9c7491db68abf4ca9f7d42edd62da5729..acbee18ec21b02761295de90ef9ff535a97739d1 100644 --- a/src/util/src/terror.c +++ b/src/util/src/terror.c @@ -282,7 +282,6 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TDB_MESSED_MSG, "TSDB messed message") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_IVLD_TAG_VAL, "TSDB invalid tag value") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_CACHE_LAST_ROW, "TSDB no cache last row data") TAOS_DEFINE_ERROR(TSDB_CODE_TDB_INCOMPLETE_DFILESET, "Incomplete DFileSet") -TAOS_DEFINE_ERROR(TSDB_CODE_TDB_NO_JSON_TAG_KEY, "TSDB no tag json key") // query TAOS_DEFINE_ERROR(TSDB_CODE_QRY_INVALID_QHANDLE, "Invalid handle") diff --git a/tests/system-test/2-query/TD-11256.py b/tests/system-test/2-query/TD-11256.py new file mode 100644 index 0000000000000000000000000000000000000000..f101ad211377310d01ad44504e2e1c60a405e826 --- /dev/null +++ b/tests/system-test/2-query/TD-11256.py @@ -0,0 +1,78 @@ +################################################################### +# Copyright (c) 2020 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import taos +import time + +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def __init__(self): + self.err_case = 0 + self.curret_case = 0 + + def caseDescription(self): + + ''' + case1 : [TD-11256] query the super table in a mixed way of expression + tbanme and using group by tbname + ''' + return + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def create_stb(self): + basetime = int(round(time.time() * 1000)) + tdSql.prepare() + tdSql.execute(f"create stable stb1(ts timestamp, c1 int) tags (tag1 int)") + for i in range(10): + tdSql.execute(f"create table t{i} using stb1 tags({i})") + tdSql.execute(f"insert into t{i} values ({basetime}, {i})") + + pass + + def check_td11256(self): + # this case expect connect is current after run group by sql + tdSql.query("select count(*) from stb1 group by ts") + try: + tdSql.error("select c1/2, tbname from stb1 group by tbname") + tdSql.query("show databases") + self.curret_case += 1 + tdLog.printNoPrefix("the case1: td-11256 run passed") + except: + self.err_case += 1 + tdLog.printNoPrefix("the case1: td-11256 run failed") + pass + + def run(self): + self.create_stb() + + self.check_td11256() + + if self.err_case > 0: + tdLog.exit(f"{self.err_case} case for TD-11256 run failed") + else: + tdLog.success("case for TD-11256 run passed") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/system-test/4-taosAdapter/TD-12163.py b/tests/system-test/4-taosAdapter/TD-12163.py new file mode 100644 index 0000000000000000000000000000000000000000..aafc218611c1c51e3d6f82d802c95fd8e2c16cf5 --- /dev/null +++ b/tests/system-test/4-taosAdapter/TD-12163.py @@ -0,0 +1,118 @@ +################################################################### +# Copyright (c) 2020 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from taosdata +# +################################################################### + +# -*- coding: utf-8 -*- + +import taos +import time +import requests + +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import * + + +class TDTestCase: + def __init__(self): + self.err_case = 0 + self.curret_case = 0 + self.url = "http://127.0.0.1:6041/rest/sql" + self.header = {'Authorization': 'Basic cm9vdDp0YW9zZGF0YQ=='} + + def caseDescription(self): + + ''' + case1 : [TD-12163] alter table-schema using restful interface + ''' + return + + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), logSql) + + def check_td12163(self): + # basetime = int(round(time.time() * 1000)) + tdSql.prepare() + tdSql.execute(f"create stable stb1(ts timestamp, c1 int) tags (tag1 int)") + tdSql.execute(f"create table nt1 (nts timestamp, nc1 int)") + + add_column_stb = "alter table db.stb1 add column c2 float" + drop_column_stb = "alter table db.stb1 drop column c2 " + add_column_ntb = "alter table db.nt1 add column nc2 float" + drop_column_ntb = "alter table db.nt1 drop column nc2 " + + conn_add_stb = requests.post(url=self.url, headers=self.header, data=add_column_stb) + resp_code_stb_add = conn_add_stb.status_code + resp_add_stb = conn_add_stb.json() + try: + assert resp_code_stb_add//200 == 1 + assert resp_add_stb["status"] == "succ" + self.curret_case += 1 + tdLog.printNoPrefix("the case add column to stable successful") + except: + self.err_case += 1 + tdLog.printNoPrefix("the case add column to stable failed") + + + conn_add_ntb = requests.post(url=self.url, headers=self.header, data=add_column_ntb) + resp_code_ntb_add = conn_add_ntb.status_code + resp_add_ntb = conn_add_ntb.json() + try: + assert resp_code_ntb_add//200 == 1 + assert resp_add_ntb["status"] == "succ" + self.curret_case += 1 + tdLog.printNoPrefix("the case add column to normal table successful") + except: + self.err_case += 1 + tdLog.printNoPrefix("the case add column to normal table failed") + + conn_drop_stb = requests.post(url=self.url, headers=self.header, data=drop_column_stb) + resp_code_stb_drop = conn_drop_stb.status_code + resp_drop_stb = conn_drop_stb.json() + try: + assert resp_code_stb_drop // 200 == 1 + assert resp_drop_stb["status"] == "succ" + self.curret_case += 1 + tdLog.printNoPrefix("the case drop column to stable successful") + except: + self.err_case += 1 + tdLog.printNoPrefix("the case add column to stable failed") + + conn_drop_ntb = requests.post(url=self.url, headers=self.header, data=drop_column_ntb) + resp_code_ntb_drop = conn_drop_ntb.status_code + resp_drop_ntb = conn_drop_ntb.json() + try: + assert resp_code_ntb_drop // 200 == 1 + assert resp_drop_ntb["status"] == "succ" + self.curret_case += 1 + tdLog.printNoPrefix("the case drop column to stable successful") + except: + self.err_case += 1 + tdLog.printNoPrefix("the case add column to stable failed") + + pass + + def run(self): + self.check_td12163() + + if self.err_case > 0: + tdLog.exit(f"{self.err_case} case for TD-12163 run failed") + else: + tdLog.success("case for TD-12163 run passed") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) \ No newline at end of file diff --git a/tests/system-test/fulltest-query.sh b/tests/system-test/fulltest-query.sh index 1db24953488aedeaac3ef8d378f317f09c6c7f71..104781def751ca8df6028dc7afe5dd80a172b4ff 100755 --- a/tests/system-test/fulltest-query.sh +++ b/tests/system-test/fulltest-query.sh @@ -1,3 +1,8 @@ + +python3 ./test.py -f 2-query/ts_hidden_column.py +python3 ./test.py -f 2-query/union-order.py +python3 test.py -f 2-query/TD-11256.py + python3 ./test.py -f 2-query/TD-11389.py python3 ./test.py -f 2-query/TD-11945_crash.py python3 ./test.py -f 2-query/TD-12340-12342.py diff --git a/tests/system-test/fulltest-taosAdapter.sh b/tests/system-test/fulltest-taosAdapter.sh index 930236e024f07520cd7a6872cf4101d207a4cedd..f7ca439fd4407438d3ffaf11a6dcd2c839508404 100755 --- a/tests/system-test/fulltest-taosAdapter.sh +++ b/tests/system-test/fulltest-taosAdapter.sh @@ -1,2 +1,3 @@ +python3 test.py -f 4-taosAdapter/TD-12163.py python3 ./test.py -f 4-taosAdapter/taosAdapter_insert.py python3 ./test.py -f 4-taosAdapter/taosAdapter_query.py \ No newline at end of file