From 503a6110f74e727dae8027479568e0b6f7db4ff4 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 16 Jul 2021 10:08:45 +0800 Subject: [PATCH 1/5] [td-5250]: improve the performance of multi-table meta bulk load. --- src/client/inc/tscUtil.h | 2 +- src/client/src/tscSQLParser.c | 2 +- src/client/src/tscServer.c | 44 +++++++++++++++++++---------------- src/client/src/tscSql.c | 9 +++++-- src/inc/taosmsg.h | 10 ++++---- src/mnode/src/mnodeTable.c | 1 + 6 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/client/inc/tscUtil.h b/src/client/inc/tscUtil.h index dbb31f4634..900178fafb 100644 --- a/src/client/inc/tscUtil.h +++ b/src/client/inc/tscUtil.h @@ -310,7 +310,7 @@ void tscTryQueryNextVnode(SSqlObj *pSql, __async_cb_func_t fp); void tscAsyncQuerySingleRowForNextVnode(void *param, TAOS_RES *tres, int numOfRows); void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp); int tscSetMgmtEpSetFromCfg(const char *first, const char *second, SRpcCorEpSet *corEpSet); -int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, __async_cb_func_t fp); +int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, __async_cb_func_t fp, bool metaClone); int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t length, SArray* pNameArray); diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 59807d1e2e..1b896c8d59 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -7738,7 +7738,7 @@ int32_t loadAllTableMeta(SSqlObj* pSql, struct SSqlInfo* pInfo) { // load the table meta for a given table name list if (taosArrayGetSize(plist) > 0 || taosArrayGetSize(pVgroupList) > 0) { - code = getMultiTableMetaFromMnode(pSql, plist, pVgroupList, tscTableMetaCallBack); + code = getMultiTableMetaFromMnode(pSql, plist, pVgroupList, tscTableMetaCallBack, true); } _end: diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 657d8b7848..2f927614f5 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -1873,7 +1873,6 @@ static int32_t tableMetaMsgConvert(STableMetaMsg* pMetaMsg) { pMetaMsg->vgroup.vgId = htonl(pMetaMsg->vgroup.vgId); pMetaMsg->uid = htobe64(pMetaMsg->uid); -// pMetaMsg->contLen = htonl(pMetaMsg->contLen); pMetaMsg->numOfColumns = htons(pMetaMsg->numOfColumns); if ((pMetaMsg->tableType != TSDB_SUPER_TABLE) && @@ -1938,13 +1937,14 @@ static void doAddTableMetaToLocalBuf(STableMeta* pTableMeta, STableMetaMsg* pMet int32_t len = (int32_t) strnlen(pTableMeta->sTableName, TSDB_TABLE_FNAME_LEN); // The super tableMeta already exists, create it according to tableMeta and add it to hash map - STableMeta* pSupTableMeta = createSuperTableMeta(pMetaMsg); + if (updateSTable) { + STableMeta* pSupTableMeta = createSuperTableMeta(pMetaMsg); + uint32_t size = tscGetTableMetaSize(pSupTableMeta); + int32_t code = taosHashPut(tscTableMetaInfo, pTableMeta->sTableName, len, pSupTableMeta, size); + assert(code == TSDB_CODE_SUCCESS); - uint32_t size = tscGetTableMetaSize(pSupTableMeta); - int32_t code = taosHashPut(tscTableMetaInfo, pTableMeta->sTableName, len, pSupTableMeta, size); - assert(code == TSDB_CODE_SUCCESS); - - tfree(pSupTableMeta); + tfree(pSupTableMeta); + } CChildTableMeta* cMeta = tscCreateChildMeta(pTableMeta); taosHashPut(tscTableMetaInfo, pMetaMsg->tableFname, strlen(pMetaMsg->tableFname), cMeta, sizeof(CChildTableMeta)); @@ -2049,10 +2049,10 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { } SSqlCmd *pParentCmd = &pParentSql->cmd; - SHashObj *pSet = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); + SHashObj *pSet = taosHashInit(pMultiMeta->numOfVgroup, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); - char* pMsg = pMultiMeta->meta; char* buf = NULL; + char* pMsg = pMultiMeta->meta; if (pMultiMeta->compressed) { buf = malloc(pMultiMeta->rawLen - sizeof(SMultiTableMeta)); int32_t len = tsDecompressString(pMultiMeta->meta, pMultiMeta->contLen - sizeof(SMultiTableMeta), 1, @@ -2086,22 +2086,25 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { SName sn = {0}; tNameFromString(&sn, pMetaMsg->tableFname, T_NAME_ACCT | T_NAME_DB | T_NAME_TABLE); - const char* tableName = tNameGetTableName(&sn); - size_t keyLen = strlen(tableName); + if (pMultiMeta->metaClone == 1 || pTableMeta->tableType == TSDB_SUPER_TABLE) { + STableMetaVgroupInfo p = {.pTableMeta = pTableMeta,}; - STableMetaVgroupInfo p = {.pTableMeta = pTableMeta,}; - taosHashPut(pParentCmd->pTableMetaMap, tableName, keyLen, &p, sizeof(STableMetaVgroupInfo)); + const char* tableName = tNameGetTableName(&sn); + size_t keyLen = strlen(tableName); + taosHashPut(pParentCmd->pTableMetaMap, tableName, keyLen, &p, sizeof(STableMetaVgroupInfo)); + } - bool addToBuf = false; - if (taosHashGet(pSet, &pMetaMsg->uid, sizeof(pMetaMsg->uid)) == NULL) { - addToBuf = true; - taosHashPut(pSet, &pMetaMsg->uid, sizeof(pMetaMsg->uid), "", 0); + // for each super table, only update meta information once + bool updateStableMeta = false; + if (pTableMeta->tableType == TSDB_CHILD_TABLE && taosHashGet(pSet, &pMetaMsg->uid, sizeof(pMetaMsg->uid)) == NULL) { + updateStableMeta = true; + taosHashPut(pSet, &pTableMeta->suid, sizeof(pMetaMsg->suid), "", 0); } // create the tableMeta and add it into the TableMeta map - doAddTableMetaToLocalBuf(pTableMeta, pMetaMsg, addToBuf); + doAddTableMetaToLocalBuf(pTableMeta, pMetaMsg, updateStableMeta); - // if the vgroup is not updated in current process, update it. + // for each vgroup, only update the information once. int64_t vgId = pMetaMsg->vgroup.vgId; if (pTableMeta->tableType != TSDB_SUPER_TABLE && taosHashGet(pSet, &vgId, sizeof(vgId)) == NULL) { doUpdateVgroupInfo(pTableMeta, &pMetaMsg->vgroup); @@ -2513,7 +2516,7 @@ static int32_t getTableMetaFromMnode(SSqlObj *pSql, STableMetaInfo *pTableMetaIn return code; } -int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, __async_cb_func_t fp) { +int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVgroupNameList, __async_cb_func_t fp, bool metaClone) { SSqlObj *pNew = calloc(1, sizeof(SSqlObj)); if (NULL == pNew) { tscError("0x%"PRIx64" failed to allocate sqlobj to get multiple table meta", pSql->self); @@ -2535,6 +2538,7 @@ int32_t getMultiTableMetaFromMnode(SSqlObj *pSql, SArray* pNameList, SArray* pVg } SMultiTableInfoMsg* pInfo = (SMultiTableInfoMsg*) pNew->cmd.payload; + pInfo->metaClone = metaClone? 1:0; pInfo->numOfTables = htonl((uint32_t) taosArrayGetSize(pNameList)); pInfo->numOfVgroups = htonl((uint32_t) taosArrayGetSize(pVgroupNameList)); diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 60261368f4..5726d3937f 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -948,7 +948,6 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { SSqlObj* pSql = calloc(1, sizeof(SSqlObj)); pSql->pTscObj = taos; pSql->signature = pSql; - pSql->cmd.pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); int32_t length = (int32_t)strlen(tableNameList); if (length > MAX_TABLE_NAME_LENGTH) { @@ -967,6 +966,11 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { strtolower(str, tableNameList); SArray* plist = taosArrayInit(4, POINTER_BYTES); SArray* vgroupList = taosArrayInit(4, POINTER_BYTES); + if (plist == NULL || vgroupList == NULL) { + tfree(str); + tscFreeSqlObj(pSql); + return TSDB_CODE_TSC_OUT_OF_MEMORY; + } int32_t code = (uint8_t) tscTransferTableNameList(pSql, str, length, plist); free(str); @@ -976,10 +980,11 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { return code; } + pSql->cmd.pTableMetaMap = taosHashInit(taosArrayGetSize(plist), taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK); registerSqlObj(pSql); tscDebug("0x%"PRIx64" load multiple table meta, tableNameList: %s pObj:%p", pSql->self, tableNameList, pObj); - code = getMultiTableMetaFromMnode(pSql, plist, vgroupList, loadMultiTableMetaCallback); + code = getMultiTableMetaFromMnode(pSql, plist, vgroupList, loadMultiTableMetaCallback, false); if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) { code = TSDB_CODE_SUCCESS; } diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index 4e76b6dcc1..48794e311d 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -710,6 +710,7 @@ typedef struct { } STableInfoMsg; typedef struct { + uint8_t metaClone; // create local clone of the cached table meta int32_t numOfVgroups; int32_t numOfTables; char tableNames[]; @@ -761,10 +762,11 @@ typedef struct STableMetaMsg { typedef struct SMultiTableMeta { int32_t numOfTables; - int32_t numOfVgroup; - uint32_t contLen:31; - uint8_t compressed:1; // denote if compressed or not - uint32_t rawLen; // size before compress + uint8_t metaClone; // make meta clone after retrieve meta from mnode + uint8_t compressed; // denote if compressed or not + int32_t numOfVgroup; // number of tables + uint32_t contLen; // current content length + uint32_t rawLen; // size before compressed char meta[]; } SMultiTableMeta; diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 6dc2f8ad28..46947026cb 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -3036,6 +3036,7 @@ static int32_t mnodeProcessMultiTableMetaMsg(SMnodeMsg *pMsg) { int32_t len = tsCompressString(pMultiMeta->meta, (int32_t)pMultiMeta->contLen - sizeof(SMultiTableMeta), 1, tmp + sizeof(SMultiTableMeta), (int32_t)pMultiMeta->contLen - sizeof(SMultiTableMeta) + 2, ONE_STAGE_COMP, NULL, 0); + pMultiMeta->metaClone = pInfo->metaClone; pMultiMeta->rawLen = pMultiMeta->contLen; if (len == -1 || len + sizeof(SMultiTableMeta) >= pMultiMeta->contLen + 2) { // compress failed, do not compress this binary data pMultiMeta->compressed = 0; From 4c593efcf4d41f7816c5ed85dba217f3ac244c91 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 16 Jul 2021 11:59:13 +0800 Subject: [PATCH 2/5] [td-5190]: fix the bug in stddev query with fill clause. --- src/client/src/tscSubquery.c | 1 + src/query/src/qSqlParser.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index f10646e3a3..5df25e1b61 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -2287,6 +2287,7 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) { SArray* pColList = pNewQueryInfo->colList; pNewQueryInfo->colList = NULL; + pNewQueryInfo->fillType = TSDB_FILL_NONE; tscClearSubqueryInfo(pCmd); tscFreeSqlResult(pSql); diff --git a/src/query/src/qSqlParser.c b/src/query/src/qSqlParser.c index 4d23a9685c..e287751b50 100644 --- a/src/query/src/qSqlParser.c +++ b/src/query/src/qSqlParser.c @@ -146,7 +146,8 @@ tSqlExpr *tSqlExprCreateIdValue(SStrToken *pToken, int32_t optrType) { pSqlExpr->type = SQL_NODE_VALUE; pSqlExpr->flags |= 1 << EXPR_FLAG_NS_TIMESTAMP; } else if (optrType == TK_VARIABLE) { - // use nanosecond by default TODO set value after getting database precision + // use nanosecond by default + // TODO set value after getting database precision int32_t ret = parseAbsoluteDuration(pToken->z, pToken->n, &pSqlExpr->value.i64, TSDB_TIME_PRECISION_NANO); if (ret != TSDB_CODE_SUCCESS) { terrno = TSDB_CODE_TSC_SQL_SYNTAX_ERROR; From 0b05f0b06df05c3d3e4fd59297727c90bae39e66 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 16 Jul 2021 12:56:19 +0800 Subject: [PATCH 3/5] [td-5190]: add test cases. --- tests/script/general/parser/function.sim | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/script/general/parser/function.sim b/tests/script/general/parser/function.sim index a485276e01..a3470b1763 100644 --- a/tests/script/general/parser/function.sim +++ b/tests/script/general/parser/function.sim @@ -1132,4 +1132,19 @@ if $data92 != t1 then return -1 endi +print =========================>TD-5190 +sql select stddev(f1) from st1 where ts>'2021-07-01 1:1:1' and ts<'2021-07-30 00:00:00' interval(1d) fill(NULL); +if $rows != 29 then + return -1 +endi + +if $data00 != @21-07-01 00:00:00.000@ then + return -1 +endi + +if $data01 != NULL then + return -1 +endi + + sql select derivative(test_column_alias_name, 1s, 0) from (select avg(k) test_column_alias_name from t1 interval(1s)); From 289e10823a77825fafb16797602451e7c026de50 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 16 Jul 2021 14:23:48 +0800 Subject: [PATCH 4/5] [td-5250]: fix memory leak and remove duplicated name in name array list. --- src/client/src/tscServer.c | 8 +++++++- src/client/src/tscSql.c | 21 ++++++++++++--------- src/client/src/tscUtil.c | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 2f927614f5..3235578ee9 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2073,6 +2073,7 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { return code; } + bool freeMeta = false; STableMeta* pTableMeta = tscCreateTableMetaFromMsg(pMetaMsg); if (!tIsValidSchema(pTableMeta->schema, pTableMeta->tableInfo.numOfColumns, pTableMeta->tableInfo.numOfTags)) { tscError("0x%"PRIx64" invalid table meta from mnode, name:%s", pSql->self, pMetaMsg->tableFname); @@ -2092,11 +2093,13 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { const char* tableName = tNameGetTableName(&sn); size_t keyLen = strlen(tableName); taosHashPut(pParentCmd->pTableMetaMap, tableName, keyLen, &p, sizeof(STableMetaVgroupInfo)); + } else { + freeMeta = true; } // for each super table, only update meta information once bool updateStableMeta = false; - if (pTableMeta->tableType == TSDB_CHILD_TABLE && taosHashGet(pSet, &pMetaMsg->uid, sizeof(pMetaMsg->uid)) == NULL) { + if (pTableMeta->tableType == TSDB_CHILD_TABLE && taosHashGet(pSet, &pMetaMsg->suid, sizeof(pMetaMsg->suid)) == NULL) { updateStableMeta = true; taosHashPut(pSet, &pTableMeta->suid, sizeof(pMetaMsg->suid), "", 0); } @@ -2112,6 +2115,9 @@ int tscProcessMultiTableMetaRsp(SSqlObj *pSql) { } pMsg += pMetaMsg->contLen; + if (freeMeta) { + tfree(pTableMeta); + } } for(int32_t i = 0; i < pMultiMeta->numOfVgroup; ++i) { diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 5726d3937f..7385fef524 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -945,21 +945,19 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { return TSDB_CODE_TSC_DISCONNECTED; } - SSqlObj* pSql = calloc(1, sizeof(SSqlObj)); - pSql->pTscObj = taos; - pSql->signature = pSql; - int32_t length = (int32_t)strlen(tableNameList); + if (length == 0) { + return TSDB_CODE_SUCCESS; + } + if (length > MAX_TABLE_NAME_LENGTH) { - tscError("0x%"PRIx64" tableNameList too long, length:%d, maximum allowed:%d", pSql->self, length, MAX_TABLE_NAME_LENGTH); - tscFreeSqlObj(pSql); + tscError("tableNameList too long, length:%d, maximum allowed:%d", length, MAX_TABLE_NAME_LENGTH); return TSDB_CODE_TSC_INVALID_OPERATION; } char *str = calloc(1, length + 1); if (str == NULL) { - tscError("0x%"PRIx64" failed to allocate sql string buffer", pSql->self); - tscFreeSqlObj(pSql); + tscError("failed to allocate sql string buffer, size:%d", length); return TSDB_CODE_TSC_OUT_OF_MEMORY; } @@ -968,10 +966,15 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { SArray* vgroupList = taosArrayInit(4, POINTER_BYTES); if (plist == NULL || vgroupList == NULL) { tfree(str); - tscFreeSqlObj(pSql); return TSDB_CODE_TSC_OUT_OF_MEMORY; } + SSqlObj* pSql = calloc(1, sizeof(SSqlObj)); + tscAllocPayload(&pSql->cmd, 1024); + + pSql->pTscObj = taos; + pSql->signature = pSql; + int32_t code = (uint8_t) tscTransferTableNameList(pSql, str, length, plist); free(str); diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 0f29f3c178..fdd68d0e30 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -4497,6 +4497,15 @@ static int32_t doAddTableName(char* nextStr, char** str, SArray* pNameArray, SSq return TSDB_CODE_SUCCESS; } +int32_t nameComparFn(const void* n1, const void* n2) { + int32_t ret = strcmp(*(char**)n1, *(char**)n2); + if (ret == 0) { + return 0; + } else { + return ret > 0? 1:-1; + } +} + int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t length, SArray* pNameArray) { SSqlCmd *pCmd = &pSql->cmd; @@ -4538,6 +4547,34 @@ int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t lengt return code; } + taosArraySort(pNameArray, nameComparFn); + size_t len = taosArrayGetSize(pNameArray); + + int32_t pos = 0; + for(int32_t i = 1; i < len; ++i) { + char** p1 = taosArrayGet(pNameArray, pos); + char** p2 = taosArrayGet(pNameArray, i); + + if (strcmp(*p1, *p2) == 0) { + // do nothing + } else { + if (pos + 1 != i) { + char* p = taosArrayGetP(pNameArray, pos + 1); + tfree(p); + taosArraySet(pNameArray, pos + 1, p2); + pos += 1; + } else { + pos += 1; + } + } + } + + for(int32_t i = pos + 1; i < pNameArray->size; ++i) { + char* p = taosArrayGetP(pNameArray, i); + tfree(p); + } + + pNameArray->size = pos + 1; return TSDB_CODE_SUCCESS; } From e27f1ce493a2036d4698b3e235c6995343f11343 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 16 Jul 2021 14:59:42 +0800 Subject: [PATCH 5/5] [td-225]refactor codes. --- src/client/src/tscUtil.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index fdd68d0e30..bf7eed8b5a 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -4466,8 +4466,13 @@ static int32_t doAddTableName(char* nextStr, char** str, SArray* pNameArray, SSq strncpy(tablename, *str, TSDB_TABLE_FNAME_LEN); len = (int32_t) strlen(tablename); } else { - memcpy(tablename, *str, nextStr - (*str)); len = (int32_t)(nextStr - (*str)); + if (len >= TSDB_TABLE_NAME_LEN) { + sprintf(pCmd->payload, "table name too long"); + return TSDB_CODE_TSC_INVALID_OPERATION; + } + + memcpy(tablename, *str, nextStr - (*str)); tablename[len] = '\0'; } @@ -4479,9 +4484,8 @@ static int32_t doAddTableName(char* nextStr, char** str, SArray* pNameArray, SSq // Check if the table name available or not if (tscValidateName(&sToken) != TSDB_CODE_SUCCESS) { - code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; sprintf(pCmd->payload, "table name is invalid"); - return code; + return TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; } SName name = {0}; @@ -4541,14 +4545,18 @@ int tscTransferTableNameList(SSqlObj *pSql, const char *pNameList, int32_t lengt } } - if (taosArrayGetSize(pNameArray) > TSDB_MULTI_TABLEMETA_MAX_NUM) { + size_t len = taosArrayGetSize(pNameArray); + if (len == 1) { + return TSDB_CODE_SUCCESS; + } + + if (len > TSDB_MULTI_TABLEMETA_MAX_NUM) { code = TSDB_CODE_TSC_INVALID_TABLE_ID_LENGTH; sprintf(pCmd->payload, "tables over the max number"); return code; } taosArraySort(pNameArray, nameComparFn); - size_t len = taosArrayGetSize(pNameArray); int32_t pos = 0; for(int32_t i = 1; i < len; ++i) {