diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 492bf5241c4f8e4caae11b1553d5579fc00b2398..7d4b0b7edba8f7664f5c797a41241dbe7b2fe4b2 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1588,6 +1588,8 @@ static bool initGroupbyInfo(const SSDataBlock *pSDataBlock, const SGroupbyExpr * return true; } pInfo->pGroupbyDataInfo = taosArrayInit(pGroupbyExpr->numOfGroupCols, sizeof(SGroupbyDataInfo)); + // head put key length (int32_t type) + pInfo->totalBytes = sizeof(int32_t); for (int32_t k = 0; k < pGroupbyExpr->numOfGroupCols; ++k) { SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, k); @@ -1624,7 +1626,8 @@ static void buildGroupbyKeyBuf(const SSDataBlock *pSDataBlock, SGroupbyOperatorI *buf = NULL; return; } - *buf = p; + *buf = p; + p += sizeof(int32_t); for (int32_t i = 0; i < taosArrayGetSize(pInfo->pGroupbyDataInfo); i++) { SGroupbyDataInfo *pDataInfo = taosArrayGet(pInfo->pGroupbyDataInfo, i); @@ -1646,26 +1649,22 @@ static void buildGroupbyKeyBuf(const SSDataBlock *pSDataBlock, SGroupbyOperatorI memcpy(p, MULTI_KEY_DELIM, strlen(MULTI_KEY_DELIM)); p += strlen(MULTI_KEY_DELIM); } + + // calc keyLen and save + int32_t keyLen = (p - *buf) - sizeof(int32_t); + *(int32_t *)(*buf) = keyLen; } static bool isGroupbyKeyEqual(void *a, void *b, void *ext) { - SGroupbyOperatorInfo *pInfo = (SGroupbyOperatorInfo *)ext; - if (memcmp(a, b, pInfo->totalBytes) == 0) { - return true; + int32_t len1 = *(int32_t *)a; + int32_t len2 = *(int32_t *)b; + if (len1 != len2) { + return false; } - int32_t offset = 0; - for (int32_t i = 0; i < taosArrayGetSize(pInfo->pGroupbyDataInfo); i++) { - SGroupbyDataInfo *pDataInfo = taosArrayGet(pInfo->pGroupbyDataInfo, i); + char *a1 = (char *)a + sizeof(int32_t); + char *b1 = (char *)b + sizeof(int32_t); - char *k1 = (char *)a + offset; - char *k2 = (char *)b + offset; - if (getComparFunc(pDataInfo->type, 0)(k1, k2) != 0) { - return false; - } - offset += pDataInfo->bytes; - offset += (int32_t)strlen(MULTI_KEY_DELIM); - } - return true; + return memcmp(a1, b1, len1) == 0; } static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pInfo, SSDataBlock *pSDataBlock) { @@ -1708,7 +1707,9 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pIn setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, pInfo); } - int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, &(pInfo->binfo), pOperator->numOfOutput, pInfo->prevData, type, pInfo->totalBytes, item->groupIndex); + char *preKey = pInfo->prevData + sizeof(int32_t); + int32_t keyLen = *(int32_t *)pInfo->prevData; + int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, &(pInfo->binfo), pOperator->numOfOutput, preKey, type, keyLen, item->groupIndex); if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR); } @@ -1730,7 +1731,9 @@ static void doHashGroupbyAgg(SOperatorInfo* pOperator, SGroupbyOperatorInfo *pIn if (pQueryAttr->stableQuery && pQueryAttr->stabledev && (pRuntimeEnv->prevResult != NULL)) { setParamForStableStddevByColData(pRuntimeEnv, pInfo->binfo.pCtx, pOperator->numOfOutput, pOperator->pExpr, pInfo); } - int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, &(pInfo->binfo), pOperator->numOfOutput, pInfo->prevData, type, pInfo->totalBytes, item->groupIndex); + char *preKey = pInfo->prevData + sizeof(int32_t); + int32_t keyLen = *(int32_t *)pInfo->prevData; + int32_t ret = setGroupResultOutputBuf(pRuntimeEnv, &(pInfo->binfo), pOperator->numOfOutput, preKey, type, keyLen, item->groupIndex); if (ret != TSDB_CODE_SUCCESS) { // null data, too many state code longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_APP_ERROR); } @@ -4312,14 +4315,15 @@ void setParamForStableStddevByColData(SQueryRuntimeEnv* pRuntimeEnv, SQLFunction // find colid in dataBlock int32_t bytes, offset = 0; char* val = NULL; + char* prevData = pInfo->prevData + sizeof(int32_t); // head is key length (int32_t type) for (int32_t idx = 0; idx < taosArrayGetSize(pInfo->pGroupbyDataInfo); idx++) { SGroupbyDataInfo *pDataInfo = taosArrayGet(pInfo->pGroupbyDataInfo, idx); if (pDataInfo->index == pExpr1->colInfo.colId) { bytes = pDataInfo->bytes; - val = pInfo->prevData + offset; + val = prevData + offset; break; } - offset += pDataInfo->bytes; + offset += pDataInfo->bytes + strlen(MULTI_KEY_DELIM); // multi value split by MULTI_KEY_DELIM } if (val == NULL) { continue; } diff --git a/tests/pytest/query/queryGroupbySort.py b/tests/pytest/query/queryGroupbySort.py index 6439fc6560d7f74b6d27ba3847f2459918fd94dc..c5ca1efacd6b4d29ea4c4b9212873ea85aa435ed 100644 --- a/tests/pytest/query/queryGroupbySort.py +++ b/tests/pytest/query/queryGroupbySort.py @@ -88,6 +88,23 @@ class TDTestCase: tdSql.query("select count(*) from tb group by c1") tdSql.checkRows(0) + # TS-1619 + tdSql.execute("create database test") + tdSql.execute("use test") + tdSql.execute("create table stb(ts timestamp, c1 int, c2 nchar(30)) tags(t1 int)") + for i in range(3): + tdSql.execute("create table t%d using stb tags(%d)" % (i, i)) + sql = "insert into t%d values " % i + for j in range(16): + if j % 4 == 0: + s = '00' + else: + s = str (j % 4 * 15) + sql += "(%d, %d, '2022-06-01 0%d:%s')" % (self.ts + j, i, int( j / 4 ), s) + tdSql.execute(sql) + + tdSql.query("select c2, sum(c1) from stb group by c2") + tdSql.checkRows(16) def stop(self): tdSql.close()