2020-03-20 16:01:40 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
|
|
|
*
|
|
|
|
|
* This program is free software: you can use, redistribute, and/or modify
|
|
|
|
|
* it under the terms of the GNU Affero General Public License, version 3
|
|
|
|
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "os.h"
|
2021-12-24 07:00:51 +00:00
|
|
|
#include "tmsg.h"
|
2021-11-02 05:37:31 +00:00
|
|
|
#include "thash.h"
|
2020-11-01 15:08:28 +00:00
|
|
|
|
2021-11-02 05:37:31 +00:00
|
|
|
#include "executil.h"
|
|
|
|
|
#include "executorimpl.h"
|
2021-10-08 02:41:20 +00:00
|
|
|
#include "tcompression.h"
|
2021-02-03 10:29:40 +00:00
|
|
|
#include "tlosertree.h"
|
|
|
|
|
|
|
|
|
|
typedef struct SCompSupporter {
|
|
|
|
|
STableQueryInfo **pTableQueryInfo;
|
|
|
|
|
int32_t *rowIndex;
|
|
|
|
|
int32_t order;
|
|
|
|
|
} SCompSupporter;
|
2020-03-20 16:01:40 +00:00
|
|
|
|
2022-02-22 05:12:03 +00:00
|
|
|
int32_t initResultRowInfo(SResultRowInfo *pResultRowInfo, int32_t size) {
|
2022-04-16 07:15:28 +00:00
|
|
|
pResultRowInfo->size = 0;
|
|
|
|
|
pResultRowInfo->cur.pageId = -1;
|
2020-03-20 16:01:40 +00:00
|
|
|
return TSDB_CODE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-12 10:36:35 +00:00
|
|
|
void cleanupResultRowInfo(SResultRowInfo *pResultRowInfo) {
|
2020-12-03 02:33:40 +00:00
|
|
|
if (pResultRowInfo == NULL) {
|
2020-05-01 08:33:06 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2020-12-12 10:36:35 +00:00
|
|
|
|
2021-03-31 02:52:13 +00:00
|
|
|
for(int32_t i = 0; i < pResultRowInfo->size; ++i) {
|
2022-03-31 08:10:32 +00:00
|
|
|
// if (pResultRowInfo->pResult[i]) {
|
|
|
|
|
// taosMemoryFreeClear(pResultRowInfo->pResult[i]->key);
|
|
|
|
|
// }
|
2020-11-23 04:47:34 +00:00
|
|
|
}
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
2022-01-08 08:28:44 +00:00
|
|
|
void resetResultRowInfo(STaskRuntimeEnv *pRuntimeEnv, SResultRowInfo *pResultRowInfo) {
|
2020-12-03 02:33:40 +00:00
|
|
|
for (int32_t i = 0; i < pResultRowInfo->size; ++i) {
|
2022-03-31 08:10:32 +00:00
|
|
|
// SResultRow *pWindowRes = pResultRowInfo->pResult[i];
|
|
|
|
|
// clearResultRow(pRuntimeEnv, pWindowRes);
|
2020-11-20 03:58:26 +00:00
|
|
|
|
|
|
|
|
int32_t groupIndex = 0;
|
|
|
|
|
int64_t uid = 0;
|
|
|
|
|
|
|
|
|
|
SET_RES_WINDOW_KEY(pRuntimeEnv->keyBuf, &groupIndex, sizeof(groupIndex), uid);
|
|
|
|
|
taosHashRemove(pRuntimeEnv->pResultRowHashTable, (const char *)pRuntimeEnv->keyBuf, GET_RES_WINDOW_KEY_LEN(sizeof(groupIndex)));
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
2021-07-08 02:58:46 +00:00
|
|
|
|
|
|
|
|
pResultRowInfo->size = 0;
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
2020-12-12 10:36:35 +00:00
|
|
|
void closeAllResultRows(SResultRowInfo *pResultRowInfo) {
|
2022-05-30 12:10:30 +00:00
|
|
|
// do nothing
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-31 08:10:32 +00:00
|
|
|
bool isResultRowClosed(SResultRow* pRow) {
|
|
|
|
|
return (pRow->closed == true);
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-31 08:10:32 +00:00
|
|
|
void closeResultRow(SResultRow* pResultRow) {
|
|
|
|
|
pResultRow->closed = true;
|
2020-03-20 16:01:40 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-23 06:01:44 +00:00
|
|
|
// TODO refactor: use macro
|
2022-05-20 15:58:34 +00:00
|
|
|
SResultRowEntryInfo* getResultCell(const SResultRow* pRow, int32_t index, const int32_t* offset) {
|
2021-02-23 06:01:44 +00:00
|
|
|
assert(index >= 0 && offset != NULL);
|
2022-01-20 08:02:09 +00:00
|
|
|
return (SResultRowEntryInfo*)((char*) pRow->pEntryInfo + offset[index]);
|
2020-11-02 06:10:15 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-10 07:24:05 +00:00
|
|
|
size_t getResultRowSize(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
|
|
|
|
|
int32_t rowSize = (numOfOutput * sizeof(SResultRowEntryInfo)) + sizeof(SResultRow);
|
|
|
|
|
|
|
|
|
|
for(int32_t i = 0; i < numOfOutput; ++i) {
|
|
|
|
|
rowSize += pCtx[i].resDataInfo.interBufSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rowSize;
|
2020-11-01 15:08:28 +00:00
|
|
|
}
|
|
|
|
|
|
2021-02-03 10:29:40 +00:00
|
|
|
void cleanupGroupResInfo(SGroupResInfo* pGroupResInfo) {
|
|
|
|
|
assert(pGroupResInfo != NULL);
|
|
|
|
|
|
|
|
|
|
taosArrayDestroy(pGroupResInfo->pRows);
|
|
|
|
|
pGroupResInfo->pRows = NULL;
|
|
|
|
|
pGroupResInfo->index = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-17 04:16:44 +00:00
|
|
|
static int32_t resultrowComparAsc(const void* p1, const void* p2) {
|
2022-04-24 12:48:42 +00:00
|
|
|
SResKeyPos* pp1 = *(SResKeyPos**) p1;
|
|
|
|
|
SResKeyPos* pp2 = *(SResKeyPos**) p2;
|
|
|
|
|
|
|
|
|
|
if (pp1->groupId == pp2->groupId) {
|
|
|
|
|
int64_t pts1 = *(int64_t*) pp1->key;
|
|
|
|
|
int64_t pts2 = *(int64_t*) pp2->key;
|
|
|
|
|
|
|
|
|
|
if (pts1 == pts2) {
|
|
|
|
|
return 0;
|
|
|
|
|
} else {
|
|
|
|
|
return pts1 < pts2? -1:1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return pp1->groupId < pp2->groupId? -1:1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-17 04:16:44 +00:00
|
|
|
static int32_t resultrowComparDesc(const void* p1, const void* p2) {
|
|
|
|
|
return resultrowComparAsc(p2, p1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initGroupedResultInfo(SGroupResInfo* pGroupResInfo, SHashObj* pHashmap, int32_t order) {
|
2021-02-03 10:29:40 +00:00
|
|
|
if (pGroupResInfo->pRows != NULL) {
|
|
|
|
|
taosArrayDestroy(pGroupResInfo->pRows);
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-24 12:48:42 +00:00
|
|
|
// extract the result rows information from the hash map
|
|
|
|
|
void* pData = NULL;
|
|
|
|
|
pGroupResInfo->pRows = taosArrayInit(10, POINTER_BYTES);
|
|
|
|
|
|
|
|
|
|
size_t keyLen = 0;
|
|
|
|
|
while((pData = taosHashIterate(pHashmap, pData)) != NULL) {
|
|
|
|
|
void* key = taosHashGetKey(pData, &keyLen);
|
|
|
|
|
|
|
|
|
|
SResKeyPos* p = taosMemoryMalloc(keyLen + sizeof(SResultRowPosition));
|
|
|
|
|
|
|
|
|
|
p->groupId = *(uint64_t*) key;
|
|
|
|
|
p->pos = *(SResultRowPosition*) pData;
|
2022-04-26 06:11:16 +00:00
|
|
|
memcpy(p->key, (char*)key + sizeof(uint64_t), keyLen - sizeof(uint64_t));
|
2022-04-24 12:48:42 +00:00
|
|
|
|
|
|
|
|
taosArrayPush(pGroupResInfo->pRows, &p);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-17 04:16:44 +00:00
|
|
|
if (order == TSDB_ORDER_ASC || order == TSDB_ORDER_DESC) {
|
|
|
|
|
__compar_fn_t fn = (order == TSDB_ORDER_ASC)? resultrowComparAsc:resultrowComparDesc;
|
|
|
|
|
qsort(pGroupResInfo->pRows->pData, taosArrayGetSize(pGroupResInfo->pRows), POINTER_BYTES, fn);
|
2022-04-24 12:48:42 +00:00
|
|
|
}
|
|
|
|
|
|
2021-03-04 10:12:52 +00:00
|
|
|
pGroupResInfo->index = 0;
|
2021-02-03 10:29:40 +00:00
|
|
|
assert(pGroupResInfo->index <= getNumOfTotalRes(pGroupResInfo));
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 09:09:06 +00:00
|
|
|
void initMultiResInfoFromArrayList(SGroupResInfo* pGroupResInfo, SArray* pArrayList) {
|
|
|
|
|
if (pGroupResInfo->pRows != NULL) {
|
2022-05-27 08:03:43 +00:00
|
|
|
taosArrayDestroyP(pGroupResInfo->pRows, taosMemoryFree);
|
2022-03-30 09:09:06 +00:00
|
|
|
}
|
|
|
|
|
|
2022-03-30 11:38:30 +00:00
|
|
|
pGroupResInfo->pRows = pArrayList;
|
2022-03-30 09:09:06 +00:00
|
|
|
pGroupResInfo->index = 0;
|
|
|
|
|
ASSERT(pGroupResInfo->index <= getNumOfTotalRes(pGroupResInfo));
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-20 15:58:34 +00:00
|
|
|
bool hashRemainDataInGroupInfo(SGroupResInfo* pGroupResInfo) {
|
2021-02-03 10:29:40 +00:00
|
|
|
if (pGroupResInfo->pRows == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return pGroupResInfo->index < taosArrayGetSize(pGroupResInfo->pRows);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t getNumOfTotalRes(SGroupResInfo* pGroupResInfo) {
|
|
|
|
|
assert(pGroupResInfo != NULL);
|
|
|
|
|
if (pGroupResInfo->pRows == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-06 03:21:40 +00:00
|
|
|
return (int32_t) taosArrayGetSize(pGroupResInfo->pRows);
|
2021-02-03 10:29:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t tableResultComparFn(const void *pLeft, const void *pRight, void *param) {
|
|
|
|
|
int32_t left = *(int32_t *)pLeft;
|
|
|
|
|
int32_t right = *(int32_t *)pRight;
|
|
|
|
|
|
|
|
|
|
SCompSupporter * supporter = (SCompSupporter *)param;
|
|
|
|
|
|
|
|
|
|
int32_t leftPos = supporter->rowIndex[left];
|
|
|
|
|
int32_t rightPos = supporter->rowIndex[right];
|
|
|
|
|
|
|
|
|
|
/* left source is exhausted */
|
|
|
|
|
if (leftPos == -1) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* right source is exhausted*/
|
|
|
|
|
if (rightPos == -1) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-31 08:10:32 +00:00
|
|
|
ASSERT(0);
|
2021-02-03 10:29:40 +00:00
|
|
|
STableQueryInfo** pList = supporter->pTableQueryInfo;
|
2022-03-31 08:10:32 +00:00
|
|
|
// SResultRow* pWindowRes1 = pList[left]->resInfo.pResult[leftPos];
|
2021-09-09 11:33:10 +00:00
|
|
|
// SResultRow * pWindowRes1 = getResultRow(&(pList[left]->resInfo), leftPos);
|
2022-03-31 08:10:32 +00:00
|
|
|
// TSKEY leftTimestamp = pWindowRes1->win.skey;
|
2021-02-03 10:29:40 +00:00
|
|
|
|
2021-09-09 11:33:10 +00:00
|
|
|
// SResultRowInfo *pWindowResInfo2 = &(pList[right]->resInfo);
|
|
|
|
|
// SResultRow * pWindowRes2 = getResultRow(pWindowResInfo2, rightPos);
|
2022-03-31 08:10:32 +00:00
|
|
|
// SResultRow* pWindowRes2 = pList[right]->resInfo.pResult[rightPos];
|
|
|
|
|
// TSKEY rightTimestamp = pWindowRes2->win.skey;
|
2021-02-03 10:29:40 +00:00
|
|
|
|
2022-03-31 08:10:32 +00:00
|
|
|
// if (leftTimestamp == rightTimestamp) {
|
2021-02-03 10:29:40 +00:00
|
|
|
return 0;
|
2022-03-31 08:10:32 +00:00
|
|
|
// }
|
2021-02-03 10:29:40 +00:00
|
|
|
|
2022-03-31 08:10:32 +00:00
|
|
|
// if (supporter->order == TSDB_ORDER_ASC) {
|
|
|
|
|
// return (leftTimestamp > rightTimestamp)? 1:-1;
|
|
|
|
|
// } else {
|
|
|
|
|
// return (leftTimestamp < rightTimestamp)? 1:-1;
|
|
|
|
|
// }
|
2021-02-03 10:29:40 +00:00
|
|
|
}
|
|
|
|
|
|
2021-09-10 06:19:50 +00:00
|
|
|
int32_t tsAscOrder(const void* p1, const void* p2) {
|
|
|
|
|
SResultRowCell* pc1 = (SResultRowCell*) p1;
|
|
|
|
|
SResultRowCell* pc2 = (SResultRowCell*) p2;
|
|
|
|
|
|
|
|
|
|
if (pc1->groupId == pc2->groupId) {
|
2022-03-31 08:10:32 +00:00
|
|
|
ASSERT(0);
|
|
|
|
|
// if (pc1->pRow->win.skey == pc2->pRow->win.skey) {
|
|
|
|
|
// return 0;
|
|
|
|
|
// } else {
|
|
|
|
|
// return (pc1->pRow->win.skey < pc2->pRow->win.skey)? -1:1;
|
|
|
|
|
// }
|
2021-09-10 06:19:50 +00:00
|
|
|
} else {
|
|
|
|
|
return (pc1->groupId < pc2->groupId)? -1:1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t tsDescOrder(const void* p1, const void* p2) {
|
|
|
|
|
SResultRowCell* pc1 = (SResultRowCell*) p1;
|
|
|
|
|
SResultRowCell* pc2 = (SResultRowCell*) p2;
|
|
|
|
|
|
|
|
|
|
if (pc1->groupId == pc2->groupId) {
|
2022-03-31 08:10:32 +00:00
|
|
|
ASSERT(0);
|
|
|
|
|
// if (pc1->pRow->win.skey == pc2->pRow->win.skey) {
|
|
|
|
|
// return 0;
|
|
|
|
|
// } else {
|
|
|
|
|
// return (pc1->pRow->win.skey < pc2->pRow->win.skey)? 1:-1;
|
|
|
|
|
// }
|
2021-09-10 06:19:50 +00:00
|
|
|
} else {
|
|
|
|
|
return (pc1->groupId < pc2->groupId)? -1:1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-08 08:28:44 +00:00
|
|
|
void orderTheResultRows(STaskRuntimeEnv* pRuntimeEnv) {
|
2021-09-10 06:19:50 +00:00
|
|
|
__compar_fn_t fn = NULL;
|
2022-04-14 06:39:28 +00:00
|
|
|
// if (pRuntimeEnv->pQueryAttr->order.order == TSDB_ORDER_ASC) {
|
|
|
|
|
// fn = tsAscOrder;
|
|
|
|
|
// } else {
|
|
|
|
|
// fn = tsDescOrder;
|
|
|
|
|
// }
|
2021-09-10 06:19:50 +00:00
|
|
|
|
|
|
|
|
taosArraySort(pRuntimeEnv->pResultRowArrayList, fn);
|
|
|
|
|
}
|