From 8ff2d9c5934745c1c69c29e56fe01633637cac9a Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Thu, 27 Nov 2025 18:31:30 +0800 Subject: [PATCH 1/6] fix: show create table error when using json tag --- source/libs/command/src/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 0aefa9f996bc..5852c281b0cd 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -713,7 +713,7 @@ static int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg, void* c return terrno; } *len += tsnprintf(buf + VARSTR_HEADER_SIZE + *len, SHOW_CREATE_TB_RESULT_FIELD2_LEN - (VARSTR_HEADER_SIZE + *len), - "%s", pJson); + "\'%s\'", pJson); taosMemoryFree(pJson); return TSDB_CODE_SUCCESS; From c96f18daecba517a5016d9f97ec970e4a90b6d85 Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Thu, 27 Nov 2025 18:36:55 +0800 Subject: [PATCH 2/6] enh: group by json tag support --- source/libs/executor/src/groupoperator.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c index acc4b9504d4d..734f30cab128 100644 --- a/source/libs/executor/src/groupoperator.c +++ b/source/libs/executor/src/groupoperator.c @@ -222,10 +222,10 @@ static void recordNewGroupKeys(SArray* pGroupCols, SArray* pGroupColVals, SSData pkey->isNull = false; char* val = colDataGetData(pColInfoData, rowIndex); if (pkey->type == TSDB_DATA_TYPE_JSON) { - if (tTagIsJson(val)) { - terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR; - return; - } + // if (tTagIsJson(val)) { + // terrno = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR; + // return; + // } int32_t dataLen = getJsonValueLen(val); memcpy(pkey->pData, val, dataLen); } else if (IS_VAR_DATA_TYPE(pkey->type)) { From e978cabfd21b86279d01b1c2653112808313206d Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Fri, 28 Nov 2025 11:07:27 +0800 Subject: [PATCH 3/6] fix: partition by json tag support --- source/libs/executor/src/executil.c | 8 ++-- .../01-Scalar/test_fun_sca_to_json.py | 47 +++++++++++++++++-- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 0d47dcaa4ba5..699a00b4c81a 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -1350,10 +1350,10 @@ int32_t getColInfoResultForGroupby(void* pVnode, SNodeList* group, STableListInf isNull[j] = 0; char* data = colDataGetData(pValue, i); if (pValue->info.type == TSDB_DATA_TYPE_JSON) { - if (tTagIsJson(data)) { - code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR; - goto end; - } + // if (tTagIsJson(data)) { + // code = TSDB_CODE_QRY_JSON_IN_GROUP_ERROR; + // goto end; + // } if (tTagIsJsonNull(data)) { isNull[j] = 1; continue; diff --git a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py index e0eb4da9f08d..83835b713755 100644 --- a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py +++ b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py @@ -387,7 +387,8 @@ def test_fun_sca_to_json(self): tdSql.execute(f"insert into {dbname}.jsons1_14 using {dbname}.jsons1 tags('{{\"tag1\":\"收到货\",\"tag2\":\"\",\"tag3\":null}}') values(1591062628000, 2, NULL, '你就会', 'dws')") tdSql.query(f"select distinct jtag->'tag1' from {dbname}.jsons1") tdSql.checkRows(8) - tdSql.error(f"select distinct jtag from {dbname}.jsons1") + tdSql.query(f"select distinct jtag from {dbname}.jsons1") + tdSql.checkRows(8) #test dumplicate key with normal colomn tdSql.execute(f"insert into {dbname}.jsons1_15 using {dbname}.jsons1 tags('{{\"tbname\":\"tt\",\"databool\":true,\"datastr\":\"是是是\"}}') values(1591060828000, 4, false, 'jjsf', \"你就会\")") @@ -425,8 +426,8 @@ def test_fun_sca_to_json(self): tdSql.checkData(2, 1, '"femail"') tdSql.checkData(7, 1, "false") - tdSql.error(f"select count(*) from {dbname}.jsons1 group by jtag") - tdSql.error(f"select count(*) from {dbname}.jsons1 partition by jtag") + tdSql.query(f"select count(*) from {dbname}.jsons1 group by jtag") + tdSql.query(f"select count(*) from {dbname}.jsons1 partition by jtag") tdSql.error(f"select count(*) from {dbname}.jsons1 group by jtag order by jtag") tdSql.error(f"select count(*) from {dbname}.jsons1 group by jtag->'tag1' order by jtag->'tag2'") tdSql.error(f"select count(*) from {dbname}.jsons1 group by jtag->'tag1' order by jtag") @@ -704,6 +705,44 @@ def test_fun_sca_to_json(self): tdSql.execute(f"insert into {dbname}.jsons_13918_4 using {dbname}.jsons_stb tags(\"NULL\") values(1591061628006, 11)") tdSql.query(f"select * from {dbname}.jsons_stb") tdSql.checkRows(4) - + + createSql = r'''CREATE TABLE `jsons1_t1` USING `jsons1` (`jtag`) TAGS ('{"tag1":5,"tag2":"beijing"}')''' + tdSql.execute(createSql) + tdSql.query(f"show create table {dbname}.jsons1_t1") + tdSql.checkRows(1) + tdSql.checkData(0, 1, createSql) + + createSql = r'''CREATE TABLE `jsons1_t2` USING `jsons1` (`jtag`) TAGS ('{"tag1":false,"tag2":"beijing"}')''' + tdSql.execute(createSql) + tdSql.query(f"show create table {dbname}.jsons1_t2") + tdSql.checkRows(1) + + createSql = r'''CREATE TABLE `jsons1_t3` USING `jsons1` (`jtag`) TAGS ('null')''' + tdSql.execute(createSql) + tdSql.query(f"show create table {dbname}.jsons1_t3") + tdSql.checkRows(1) + tdSql.checkData(0, 1, createSql) + + + sql = f"SELECT distinct tbname, jtag from {dbname}.jsons1 where tbname IN('jsons1_t1', 'jsons1_t2', 'jsons1_t3')" + tdSql.query(sql) + tdSql.checkRows(3) + + # select count(*) from db.jsons1; + sql = f"select jtag->'tag1', count(*) from {dbname}.jsons1 group by jtag->'tag1'" + tdSql.query(sql) + tdSql.checkRows(7) + + sql = f"select jtag, count(*) from {dbname}.jsons1 group by jtag" + tdSql.query(sql) + tdSql.checkRows(10) + + sql = f"select jtag->'tag1', count(*) from {dbname}.jsons1 group by jtag" + tdSql.query(sql) + tdSql.checkRows(10) + + sql = f"select jtag, count(*) from {dbname}.jsons1 group by jtag->'tag1'" + tdSql.error(sql) + #tdSql.close() tdLog.success("%s successfully executed" % __file__) From 0c485b1947b15c9bc502a97cf5d22f1008d80643 Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Fri, 28 Nov 2025 15:15:25 +0800 Subject: [PATCH 4/6] test: add test case --- .../01-Scalar/test_fun_sca_to_json.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py index 83835b713755..e000637c9677 100644 --- a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py +++ b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py @@ -744,5 +744,20 @@ def test_fun_sca_to_json(self): sql = f"select jtag, count(*) from {dbname}.jsons1 group by jtag->'tag1'" tdSql.error(sql) + sql = f"select jtag->'tag1', count(*) from {dbname}.jsons1 partition by jtag->'tag1'" + tdSql.query(sql) + tdSql.checkRows(7) + + sql = f"select jtag, count(*) from {dbname}.jsons1 partition by jtag" + tdSql.query(sql) + tdSql.checkRows(10) + + sql = f"select jtag->'tag1', count(*) from {dbname}.jsons1 partition by jtag" + tdSql.query(sql) + tdSql.checkRows(10) + + sql = f"select jtag, count(*) from {dbname}.jsons1 partition by jtag->'tag1'" + tdSql.error(sql) + #tdSql.close() tdLog.success("%s successfully executed" % __file__) From 3ae7d1cf3db7b656293d8960b92c615f736a3835 Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Fri, 28 Nov 2025 18:32:19 +0800 Subject: [PATCH 5/6] fix: memleak --- source/common/src/tdatablock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 7b58701cac1e..2a8d80e07c2d 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -1559,7 +1559,10 @@ int32_t blockDataSort(SSDataBlock* pDataBlock, SArray* pOrderInfo) { terrno = 0; taosqsort_r(index, rows, sizeof(int32_t), &helper, dataBlockCompar); - if (terrno) return terrno; + if (terrno) { + destroyTupleIndex(index); + return terrno; + } int64_t p1 = taosGetTimestampUs(); From c922ede472e7969bafd5fab80f899070214b0117 Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Sun, 30 Nov 2025 18:24:12 +0800 Subject: [PATCH 6/6] fix: use escaped json for show create sql --- source/libs/command/src/command.c | 22 +++++++++++++++++-- .../01-Scalar/test_fun_sca_to_json.py | 6 +++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 5852c281b0cd..a0f59b03ce80 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -17,6 +17,8 @@ #include "catalog.h" #include "commandInt.h" #include "decimal.h" +#include "osMemory.h" +#include "osString.h" #include "scheduler.h" #include "systable.h" #include "taosdef.h" @@ -712,8 +714,24 @@ static int32_t appendTagValues(char* buf, int32_t* len, STableCfg* pCfg, void* c qError("failed to parse tag to json, pJson is NULL"); return terrno; } - *len += tsnprintf(buf + VARSTR_HEADER_SIZE + *len, SHOW_CREATE_TB_RESULT_FIELD2_LEN - (VARSTR_HEADER_SIZE + *len), - "\'%s\'", pJson); + char* escapedJson = taosMemCalloc(sizeof(char), strlen(pJson) * 2 + 1); // taosMemoryAlloc(strlen(pJson) * 2 + 1); + if (escapedJson) { + char* writer = escapedJson; + for (char* reader = pJson; *reader; ++reader) { + if (*reader == '\'') { + *writer++ = '\''; // Escape single quote by doubling it + } + *writer++ = *reader; + } + *writer = '\0'; + + *len += tsnprintf(buf + VARSTR_HEADER_SIZE + *len, SHOW_CREATE_TB_RESULT_FIELD2_LEN - (VARSTR_HEADER_SIZE + *len), + "'%s'", escapedJson); + taosMemoryFree(escapedJson); + } else { + taosMemoryFree(pJson); + return terrno; + } taosMemoryFree(pJson); return TSDB_CODE_SUCCESS; diff --git a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py index e000637c9677..bbb36fb4ff4f 100644 --- a/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py +++ b/test/cases/11-Functions/01-Scalar/test_fun_sca_to_json.py @@ -759,5 +759,11 @@ def test_fun_sca_to_json(self): sql = f"select jtag, count(*) from {dbname}.jsons1 partition by jtag->'tag1'" tdSql.error(sql) + createSql = r'''CREATE TABLE `jsons1_t4` USING `jsons1` (`jtag`) TAGS ('{"tag1":false,"tag2":"xi''an"}')''' + tdSql.execute(createSql) + tdSql.query(f"show create table {dbname}.jsons1_t4") + tdSql.checkRows(1) + tdSql.checkData(0, 1, createSql) + #tdSql.close() tdLog.success("%s successfully executed" % __file__)