From 4fd0bc409d2177a77148a502546e590179496bcb Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Tue, 13 Sep 2022 09:09:21 +0800 Subject: [PATCH 01/50] fix: fix client/server memory leak issues --- source/client/src/clientImpl.c | 1 + source/client/src/clientMain.c | 2 ++ source/client/src/clientRawBlockWrite.c | 6 ++++++ source/common/src/tmsg.c | 2 ++ source/libs/catalog/src/ctgUtil.c | 11 ++++++++++- source/libs/parser/src/parTranslater.c | 25 ++++++------------------- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 5ebc2729f8..1c18812509 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -854,6 +854,7 @@ void schedulerExecCb(SExecResult* pResult, void* param, int32_t code) { pRequest->metric.resultReady = taosGetTimestampUs(); if (pResult) { + destroyQueryExecRes(&pRequest->body.resInfo.execRes); memcpy(&pRequest->body.resInfo.execRes, pResult, sizeof(*pResult)); } diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c index 3086078080..73636e7372 100644 --- a/source/client/src/clientMain.c +++ b/source/client/src/clientMain.c @@ -870,11 +870,13 @@ static void fetchCallback(void *pResult, void *param, int32_t code) { if (code != TSDB_CODE_SUCCESS) { pRequest->code = code; + taosMemoryFreeClear(pResultInfo->pData); pRequest->body.fetchFp(pRequest->body.param, pRequest, 0); return; } if (pRequest->code != TSDB_CODE_SUCCESS) { + taosMemoryFreeClear(pResultInfo->pData); pRequest->body.fetchFp(pRequest->body.param, pRequest, 0); return; } diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index c135965f07..6e9711f57b 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -701,6 +701,12 @@ typedef struct SVgroupCreateTableBatch { static void destroyCreateTbReqBatch(void* data) { SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*)data; + size_t size = taosArrayGetSize(pTbBatch->req.pArray); + for (int32_t i = 0; i < size; ++i) { + SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); + tdDestroySVCreateTbReq(pTableReq); + } + taosArrayDestroy(pTbBatch->req.pArray); } diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index ea25094d10..f96462945f 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -5436,6 +5436,8 @@ void tFreeSSubmitRsp(SSubmitRsp *pRsp) { for (int32_t i = 0; i < pRsp->nBlocks; ++i) { SSubmitBlkRsp *sRsp = pRsp->pBlocks + i; taosMemoryFree(sRsp->tblFName); + tFreeSTableMetaRsp(sRsp->pMeta); + taosMemoryFree(sRsp->pMeta); } taosMemoryFree(pRsp->pBlocks); diff --git a/source/libs/catalog/src/ctgUtil.c b/source/libs/catalog/src/ctgUtil.c index 296100ce6d..97b174de1c 100644 --- a/source/libs/catalog/src/ctgUtil.c +++ b/source/libs/catalog/src/ctgUtil.c @@ -99,7 +99,16 @@ char *ctgTaskTypeStr(CTG_TASK_TYPE type) { } void ctgFreeQNode(SCtgQNode *node) { - //TODO + if (NULL == node) { + return; + } + + if (node->op) { + taosMemoryFree(node->op->data); + taosMemoryFree(node->op); + } + + taosMemoryFree(node); } void ctgFreeSTableIndex(void *info) { diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index ad9a467dee..7d49e3d7c5 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -5922,12 +5922,6 @@ typedef struct SVgroupCreateTableBatch { char dbName[TSDB_DB_NAME_LEN]; } SVgroupCreateTableBatch; -static void destroyCreateTbReq(SVCreateTbReq* pReq) { - taosMemoryFreeClear(pReq->name); - taosMemoryFreeClear(pReq->comment); - taosMemoryFreeClear(pReq->ntb.schemaRow.pSchema); -} - static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt* pStmt, const SVgroupInfo* pVgroupInfo, SVgroupCreateTableBatch* pBatch) { char dbFName[TSDB_DB_FNAME_LEN] = {0}; @@ -5942,7 +5936,7 @@ static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt* if (pStmt->pOptions->commentNull == false) { req.comment = strdup(pStmt->pOptions->comment); if (NULL == req.comment) { - destroyCreateTbReq(&req); + tdDestroySVCreateTbReq(&req); return TSDB_CODE_OUT_OF_MEMORY; } req.commentLen = strlen(pStmt->pOptions->comment); @@ -5953,7 +5947,7 @@ static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt* req.ntb.schemaRow.version = 1; req.ntb.schemaRow.pSchema = taosMemoryCalloc(req.ntb.schemaRow.nCols, sizeof(SSchema)); if (NULL == req.name || NULL == req.ntb.schemaRow.pSchema) { - destroyCreateTbReq(&req); + tdDestroySVCreateTbReq(&req); return TSDB_CODE_OUT_OF_MEMORY; } if (pStmt->ignoreExists) { @@ -5969,7 +5963,7 @@ static int32_t buildNormalTableBatchReq(int32_t acctId, const SCreateTableStmt* strcpy(pBatch->dbName, pStmt->dbName); pBatch->req.pArray = taosArrayInit(1, sizeof(struct SVCreateTbReq)); if (NULL == pBatch->req.pArray) { - destroyCreateTbReq(&req); + tdDestroySVCreateTbReq(&req); return TSDB_CODE_OUT_OF_MEMORY; } taosArrayPush(pBatch->req.pArray, &req); @@ -6014,16 +6008,7 @@ static void destroyCreateTbReqBatch(void* data) { size_t size = taosArrayGetSize(pTbBatch->req.pArray); for (int32_t i = 0; i < size; ++i) { SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); - taosMemoryFreeClear(pTableReq->name); - taosMemoryFreeClear(pTableReq->comment); - - if (pTableReq->type == TSDB_NORMAL_TABLE) { - taosMemoryFreeClear(pTableReq->ntb.schemaRow.pSchema); - } else if (pTableReq->type == TSDB_CHILD_TABLE) { - taosMemoryFreeClear(pTableReq->ctb.pTag); - taosMemoryFreeClear(pTableReq->ctb.name); - taosArrayDestroy(pTableReq->ctb.tagName); - } + tdDestroySVCreateTbReq(pTableReq); } taosArrayDestroy(pTbBatch->req.pArray); @@ -6384,6 +6369,8 @@ static int32_t rewriteCreateSubTable(STranslateContext* pCxt, SCreateSubTableCla if (TSDB_CODE_SUCCESS == code) { addCreateTbReqIntoVgroup(pCxt->pParseCxt->acctId, pVgroupHashmap, pStmt, pTag, pSuperTableMeta->uid, pStmt->useTableName, &info, tagName, pSuperTableMeta->tableInfo.numOfTags); + } else { + taosMemoryFree(pTag); } taosArrayDestroy(tagName); From ce9fb842212cd74f1cb54b6c523ed3ffaa197d3b Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 14:21:43 +0800 Subject: [PATCH 02/50] refact --- include/common/tdataformat.h | 43 ++++- source/common/src/tdataformat.c | 175 +++++++++++++++++- source/dnode/vnode/src/inc/tsdb.h | 26 --- source/dnode/vnode/src/tsdb/tsdbUtil.c | 244 +------------------------ 4 files changed, 210 insertions(+), 278 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index df16f4f0ab..2edecc6199 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -36,8 +36,13 @@ typedef struct STSRow2 STSRow2; typedef struct STSRowBuilder STSRowBuilder; typedef struct STagVal STagVal; typedef struct STag STag; +typedef struct SColData SColData; -// bitmap +#define HAS_NONE ((int8_t)0x1) +#define HAS_NULL ((int8_t)0x2) +#define HAS_VALUE ((int8_t)0x4) + +// bitmap ================================ const static uint8_t BIT2_MAP[4][4] = {{0b00000000, 0b00000001, 0b00000010, 0}, {0b00000000, 0b00000100, 0b00001000, 2}, {0b00000000, 0b00010000, 0b00100000, 4}, @@ -51,21 +56,21 @@ const static uint8_t BIT2_MAP[4][4] = {{0b00000000, 0b00000001, 0b00000010, 0}, #define SET_BIT2(p, i, v) ((p)[(i) >> 2] = (p)[(i) >> 2] & N1(BIT2_MAP[(i)&3][3]) | BIT2_MAP[(i)&3][(v)]) #define GET_BIT2(p, i) (((p)[(i) >> 2] >> BIT2_MAP[(i)&3][3]) & ((uint8_t)3)) -// STSchema +// STSchema ================================ int32_t tTSchemaCreate(int32_t sver, SSchema *pSchema, int32_t nCols, STSchema **ppTSchema); void tTSchemaDestroy(STSchema *pTSchema); -// SValue +// SValue ================================ int32_t tPutValue(uint8_t *p, SValue *pValue, int8_t type); int32_t tGetValue(uint8_t *p, SValue *pValue, int8_t type); int tValueCmprFn(const SValue *pValue1, const SValue *pValue2, int8_t type); -// SColVal +// SColVal ================================ #define COL_VAL_NONE(CID, TYPE) ((SColVal){.cid = (CID), .type = (TYPE), .isNone = 1}) #define COL_VAL_NULL(CID, TYPE) ((SColVal){.cid = (CID), .type = (TYPE), .isNull = 1}) #define COL_VAL_VALUE(CID, TYPE, V) ((SColVal){.cid = (CID), .type = (TYPE), .value = (V)}) -// STSRow2 +// STSRow2 ================================ #define TSROW_LEN(PROW, V) tGetI32v((uint8_t *)(PROW)->data, (V) ? &(V) : NULL) #define TSROW_SVER(PROW, V) tGetI32v((PROW)->data + TSROW_LEN(PROW, NULL), (V) ? &(V) : NULL) @@ -77,7 +82,7 @@ int32_t tTSRowToArray(STSRow2 *pRow, STSchema *pTSchema, SArray **ppArray); int32_t tPutTSRow(uint8_t *p, STSRow2 *pRow); int32_t tGetTSRow(uint8_t *p, STSRow2 **ppRow); -// STSRowBuilder +// STSRowBuilder ================================ #define tsRowBuilderInit() ((STSRowBuilder){0}) #define tsRowBuilderClear(B) \ do { \ @@ -86,7 +91,7 @@ int32_t tGetTSRow(uint8_t *p, STSRow2 **ppRow); } \ } while (0) -// STag +// STag ================================ int32_t tTagNew(SArray *pArray, int32_t version, int8_t isJson, STag **ppTag); void tTagFree(STag *pTag); bool tTagIsJson(const void *pTag); @@ -100,7 +105,17 @@ void tTagSetCid(const STag *pTag, int16_t iTag, int16_t cid); void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remove int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf); -// STRUCT ================= +// SColData ================================ +void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); +void tColDataReset(SColData *pColData); +void tColDataClear(void *ph); +int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); +int32_t tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); +int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); +int32_t tPutColData(uint8_t *p, SColData *pColData); +int32_t tGetColData(uint8_t *p, SColData *pColData); + +// STRUCT ================================ struct STColumn { col_id_t colId; int8_t type; @@ -166,6 +181,18 @@ struct SColVal { SValue value; }; +struct SColData { + int16_t cid; + int8_t type; + int8_t smaOn; + int32_t nVal; + uint8_t flag; + uint8_t *pBitMap; + int32_t *aOffset; + int32_t nData; + uint8_t *pData; +}; + #pragma pack(push, 1) struct STagVal { // char colName[TSDB_COL_NAME_LEN]; // only used for tmq_get_meta diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index b40f449a05..48fb0bb5f4 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -15,6 +15,7 @@ #define _DEFAULT_SOURCE #include "tdataformat.h" +#include "tRealloc.h" #include "tcoding.h" #include "tdatablock.h" #include "tlog.h" @@ -1172,4 +1173,176 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) { return pSchema; } -#endif \ No newline at end of file +#endif + +// SColData ======================================== +void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { + pColData->cid = cid; + pColData->type = type; + pColData->smaOn = smaOn; + tColDataReset(pColData); +} + +void tColDataReset(SColData *pColData) { + pColData->nVal = 0; + pColData->flag = 0; + pColData->nData = 0; +} + +void tColDataClear(void *ph) { + SColData *pColData = (SColData *)ph; + + tFree(pColData->pBitMap); + tFree((uint8_t *)pColData->aOffset); + tFree(pColData->pData); +} + +int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { + int32_t code = 0; + int64_t size; + SValue value = {0}; + SValue *pValue = &value; + + ASSERT(pColVal->cid == pColData->cid); + ASSERT(pColVal->type == pColData->type); + + // realloc bitmap + size = BIT2_SIZE(pColData->nVal + 1); + code = tRealloc(&pColData->pBitMap, size); + if (code) goto _exit; + if ((pColData->nVal & 3) == 0) { + pColData->pBitMap[pColData->nVal >> 2] = 0; + } + + // put value + if (pColVal->isNone) { + pColData->flag |= HAS_NONE; + SET_BIT2(pColData->pBitMap, pColData->nVal, 0); + } else if (pColVal->isNull) { + pColData->flag |= HAS_NULL; + SET_BIT2(pColData->pBitMap, pColData->nVal, 1); + } else { + pColData->flag |= HAS_VALUE; + SET_BIT2(pColData->pBitMap, pColData->nVal, 2); + pValue = &pColVal->value; + } + + if (IS_VAR_DATA_TYPE(pColData->type)) { + // offset + code = tRealloc((uint8_t **)&pColData->aOffset, sizeof(int32_t) * (pColData->nVal + 1)); + if (code) goto _exit; + pColData->aOffset[pColData->nVal] = pColData->nData; + + // value + if ((!pColVal->isNone) && (!pColVal->isNull)) { + code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); + if (code) goto _exit; + memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); + pColData->nData += pColVal->value.nData; + } + } else { + code = tRealloc(&pColData->pData, pColData->nData + tPutValue(NULL, pValue, pColVal->type)); + if (code) goto _exit; + pColData->nData += tPutValue(pColData->pData + pColData->nData, pValue, pColVal->type); + } + + pColData->nVal++; + +_exit: + return code; +} + +int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { + int32_t code = 0; + int32_t size; + + ASSERT(pColDataSrc->nVal > 0); + ASSERT(pColDataDest->cid = pColDataSrc->cid); + ASSERT(pColDataDest->type = pColDataSrc->type); + + pColDataDest->smaOn = pColDataSrc->smaOn; + pColDataDest->nVal = pColDataSrc->nVal; + pColDataDest->flag = pColDataSrc->flag; + + // bitmap + if (pColDataSrc->flag != HAS_NONE && pColDataSrc->flag != HAS_NULL && pColDataSrc->flag != HAS_VALUE) { + size = BIT2_SIZE(pColDataSrc->nVal); + code = tRealloc(&pColDataDest->pBitMap, size); + if (code) goto _exit; + memcpy(pColDataDest->pBitMap, pColDataSrc->pBitMap, size); + } + + // offset + if (IS_VAR_DATA_TYPE(pColDataDest->type)) { + size = sizeof(int32_t) * pColDataSrc->nVal; + + code = tRealloc((uint8_t **)&pColDataDest->aOffset, size); + if (code) goto _exit; + + memcpy(pColDataDest->aOffset, pColDataSrc->aOffset, size); + } + + // value + pColDataDest->nData = pColDataSrc->nData; + code = tRealloc(&pColDataDest->pData, pColDataSrc->nData); + if (code) goto _exit; + memcpy(pColDataDest->pData, pColDataSrc->pData, pColDataDest->nData); + +_exit: + return code; +} + +int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { + int32_t code = 0; + + ASSERT(iVal < pColData->nVal); + ASSERT(pColData->flag); + + if (pColData->flag == HAS_NONE) { + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); + goto _exit; + } else if (pColData->flag == HAS_NULL) { + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); + goto _exit; + } else if (pColData->flag != HAS_VALUE) { + uint8_t v = GET_BIT2(pColData->pBitMap, iVal); + if (v == 0) { + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); + goto _exit; + } else if (v == 1) { + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); + goto _exit; + } + } + + // get value + SValue value; + if (IS_VAR_DATA_TYPE(pColData->type)) { + if (iVal + 1 < pColData->nVal) { + value.nData = pColData->aOffset[iVal + 1] - pColData->aOffset[iVal]; + } else { + value.nData = pColData->nData - pColData->aOffset[iVal]; + } + + value.pData = pColData->pData + pColData->aOffset[iVal]; + } else { + tGetValue(pColData->pData + tDataTypes[pColData->type].bytes * iVal, &value, pColData->type); + } + *pColVal = COL_VAL_VALUE(pColData->cid, pColData->type, value); + +_exit: + return code; +} + +static FORCE_INLINE int32_t tColDataCmprFn(const void *p1, const void *p2) { + SColData *pColData1 = (SColData *)p1; + SColData *pColData2 = (SColData *)p2; + + if (pColData1->cid < pColData2->cid) { + return -1; + } else if (pColData1->cid > pColData2->cid) { + return 1; + } + + return 0; +} diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index a836fa2bc5..063b33f3a9 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -44,7 +44,6 @@ typedef struct SMapData SMapData; typedef struct SBlockIdx SBlockIdx; typedef struct SDataBlk SDataBlk; typedef struct SSttBlk SSttBlk; -typedef struct SColData SColData; typedef struct SDiskDataHdr SDiskDataHdr; typedef struct SBlockData SBlockData; typedef struct SDelFile SDelFile; @@ -71,10 +70,6 @@ typedef struct SLDataIter SLDataIter; #define TSDB_MAX_SUBBLOCKS 8 #define TSDB_FHDR_SIZE 512 -#define HAS_NONE ((int8_t)0x1) -#define HAS_NULL ((int8_t)0x2) -#define HAS_VALUE ((int8_t)0x4) - #define VERSION_MIN 0 #define VERSION_MAX INT64_MAX @@ -148,15 +143,6 @@ int32_t tPutBlockIdx(uint8_t *p, void *ph); int32_t tGetBlockIdx(uint8_t *p, void *ph); int32_t tCmprBlockIdx(void const *lhs, void const *rhs); int32_t tCmprBlockL(void const *lhs, void const *rhs); -// SColdata -void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); -void tColDataReset(SColData *pColData); -void tColDataClear(void *ph); -int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); -int32_t tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); -int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); -int32_t tPutColData(uint8_t *p, SColData *pColData); -int32_t tGetColData(uint8_t *p, SColData *pColData); // SBlockData #define tBlockDataFirstRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, 0) #define tBlockDataLastRow(PBLOCKDATA) tsdbRowFromBlockData(PBLOCKDATA, (PBLOCKDATA)->nRow - 1) @@ -470,18 +456,6 @@ struct SSttBlk { SBlockInfo bInfo; }; -struct SColData { - int16_t cid; - int8_t type; - int8_t smaOn; - int32_t nVal; - uint8_t flag; - uint8_t *pBitMap; - int32_t *aOffset; - int32_t nData; - uint8_t *pData; -}; - // (SBlockData){.suid = 0, .uid = 0}: block data not initialized // (SBlockData){.suid = suid, .uid = uid}: block data for ONE child table int .data file // (SBlockData){.suid = suid, .uid = 0}: block data for N child tables int .last file diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index caeca45e01..1a109b2cf6 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -909,248 +909,6 @@ int32_t tsdbBuildDeleteSkyline(SArray *aDelData, int32_t sidx, int32_t eidx, SAr return code; } -// SColData ======================================== -void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { - pColData->cid = cid; - pColData->type = type; - pColData->smaOn = smaOn; - tColDataReset(pColData); -} - -void tColDataReset(SColData *pColData) { - pColData->nVal = 0; - pColData->flag = 0; - pColData->nData = 0; -} - -void tColDataClear(void *ph) { - SColData *pColData = (SColData *)ph; - - tFree(pColData->pBitMap); - tFree((uint8_t *)pColData->aOffset); - tFree(pColData->pData); -} - -int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { - int32_t code = 0; - int64_t size; - SValue value = {0}; - SValue *pValue = &value; - - ASSERT(pColVal->cid == pColData->cid); - ASSERT(pColVal->type == pColData->type); - - // realloc bitmap - size = BIT2_SIZE(pColData->nVal + 1); - code = tRealloc(&pColData->pBitMap, size); - if (code) goto _exit; - if ((pColData->nVal & 3) == 0) { - pColData->pBitMap[pColData->nVal >> 2] = 0; - } - - // put value - if (pColVal->isNone) { - pColData->flag |= HAS_NONE; - SET_BIT2(pColData->pBitMap, pColData->nVal, 0); - } else if (pColVal->isNull) { - pColData->flag |= HAS_NULL; - SET_BIT2(pColData->pBitMap, pColData->nVal, 1); - } else { - pColData->flag |= HAS_VALUE; - SET_BIT2(pColData->pBitMap, pColData->nVal, 2); - pValue = &pColVal->value; - } - - if (IS_VAR_DATA_TYPE(pColData->type)) { - // offset - code = tRealloc((uint8_t **)&pColData->aOffset, sizeof(int32_t) * (pColData->nVal + 1)); - if (code) goto _exit; - pColData->aOffset[pColData->nVal] = pColData->nData; - - // value - if ((!pColVal->isNone) && (!pColVal->isNull)) { - code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); - if (code) goto _exit; - memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); - pColData->nData += pColVal->value.nData; - } - } else { - code = tRealloc(&pColData->pData, pColData->nData + tPutValue(NULL, pValue, pColVal->type)); - if (code) goto _exit; - pColData->nData += tPutValue(pColData->pData + pColData->nData, pValue, pColVal->type); - } - - pColData->nVal++; - -_exit: - return code; -} - -int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { - int32_t code = 0; - int32_t size; - - ASSERT(pColDataSrc->nVal > 0); - ASSERT(pColDataDest->cid = pColDataSrc->cid); - ASSERT(pColDataDest->type = pColDataSrc->type); - - pColDataDest->smaOn = pColDataSrc->smaOn; - pColDataDest->nVal = pColDataSrc->nVal; - pColDataDest->flag = pColDataSrc->flag; - - // bitmap - if (pColDataSrc->flag != HAS_NONE && pColDataSrc->flag != HAS_NULL && pColDataSrc->flag != HAS_VALUE) { - size = BIT2_SIZE(pColDataSrc->nVal); - code = tRealloc(&pColDataDest->pBitMap, size); - if (code) goto _exit; - memcpy(pColDataDest->pBitMap, pColDataSrc->pBitMap, size); - } - - // offset - if (IS_VAR_DATA_TYPE(pColDataDest->type)) { - size = sizeof(int32_t) * pColDataSrc->nVal; - - code = tRealloc((uint8_t **)&pColDataDest->aOffset, size); - if (code) goto _exit; - - memcpy(pColDataDest->aOffset, pColDataSrc->aOffset, size); - } - - // value - pColDataDest->nData = pColDataSrc->nData; - code = tRealloc(&pColDataDest->pData, pColDataSrc->nData); - if (code) goto _exit; - memcpy(pColDataDest->pData, pColDataSrc->pData, pColDataDest->nData); - -_exit: - return code; -} - -int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { - int32_t code = 0; - - ASSERT(iVal < pColData->nVal); - ASSERT(pColData->flag); - - if (pColData->flag == HAS_NONE) { - *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); - goto _exit; - } else if (pColData->flag == HAS_NULL) { - *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); - goto _exit; - } else if (pColData->flag != HAS_VALUE) { - uint8_t v = GET_BIT2(pColData->pBitMap, iVal); - if (v == 0) { - *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); - goto _exit; - } else if (v == 1) { - *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); - goto _exit; - } - } - - // get value - SValue value; - if (IS_VAR_DATA_TYPE(pColData->type)) { - if (iVal + 1 < pColData->nVal) { - value.nData = pColData->aOffset[iVal + 1] - pColData->aOffset[iVal]; - } else { - value.nData = pColData->nData - pColData->aOffset[iVal]; - } - - value.pData = pColData->pData + pColData->aOffset[iVal]; - } else { - tGetValue(pColData->pData + tDataTypes[pColData->type].bytes * iVal, &value, pColData->type); - } - *pColVal = COL_VAL_VALUE(pColData->cid, pColData->type, value); - -_exit: - return code; -} - -int32_t tPutColData(uint8_t *p, SColData *pColData) { - int32_t n = 0; - - n += tPutI16v(p ? p + n : p, pColData->cid); - n += tPutI8(p ? p + n : p, pColData->type); - n += tPutI8(p ? p + n : p, pColData->smaOn); - n += tPutI32v(p ? p + n : p, pColData->nVal); - n += tPutU8(p ? p + n : p, pColData->flag); - - if (pColData->flag == HAS_NONE || pColData->flag == HAS_NULL) goto _exit; - if (pColData->flag != HAS_VALUE) { - // bitmap - - int32_t size = BIT2_SIZE(pColData->nVal); - if (p) { - memcpy(p + n, pColData->pBitMap, size); - } - n += size; - } - if (IS_VAR_DATA_TYPE(pColData->type)) { - // offset - - int32_t size = sizeof(int32_t) * pColData->nVal; - if (p) { - memcpy(p + n, pColData->aOffset, size); - } - n += size; - } - n += tPutI32v(p ? p + n : p, pColData->nData); - if (p) { - memcpy(p + n, pColData->pData, pColData->nData); - } - n += pColData->nData; - -_exit: - return n; -} - -int32_t tGetColData(uint8_t *p, SColData *pColData) { - int32_t n = 0; - - n += tGetI16v(p + n, &pColData->cid); - n += tGetI8(p + n, &pColData->type); - n += tGetI8(p + n, &pColData->smaOn); - n += tGetI32v(p + n, &pColData->nVal); - n += tGetU8(p + n, &pColData->flag); - - if (pColData->flag == HAS_NONE || pColData->flag == HAS_NULL) goto _exit; - if (pColData->flag != HAS_VALUE) { - // bitmap - - int32_t size = BIT2_SIZE(pColData->nVal); - pColData->pBitMap = p + n; - n += size; - } - if (IS_VAR_DATA_TYPE(pColData->type)) { - // offset - - int32_t size = sizeof(int32_t) * pColData->nVal; - pColData->aOffset = (int32_t *)(p + n); - n += size; - } - n += tGetI32v(p + n, &pColData->nData); - pColData->pData = p + n; - n += pColData->nData; - -_exit: - return n; -} - -static FORCE_INLINE int32_t tColDataCmprFn(const void *p1, const void *p2) { - SColData *pColData1 = (SColData *)p1; - SColData *pColData2 = (SColData *)p2; - - if (pColData1->cid < pColData2->cid) { - return -1; - } else if (pColData1->cid > pColData2->cid) { - return 1; - } - - return 0; -} - // SBlockData ====================================================== int32_t tBlockDataCreate(SBlockData *pBlockData) { int32_t code = 0; @@ -1501,7 +1259,7 @@ void tBlockDataGetColData(SBlockData *pBlockData, int16_t cid, SColData **ppColD while (lidx <= ridx) { int32_t midx = (lidx + ridx) / 2; SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, midx); - int32_t c = tColDataCmprFn(pColData, &(SColData){.cid = cid}); + int32_t c = (pColData->cid == cid) ? 0 : ((pColData->cid > cid) ? 1 : -1); if (c == 0) { *ppColData = pColData; From 0fc81c7d84f4f7bc96d477bc84b4f1811a2d9b52 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 14:52:31 +0800 Subject: [PATCH 03/50] refact code --- include/common/tdataformat.h | 2 +- source/common/src/tdataformat.c | 22 ++++++++++------------ source/dnode/vnode/src/tsdb/tsdbUtil.c | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 2edecc6199..4e5ecd90dc 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -108,7 +108,7 @@ int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, voi // SColData ================================ void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); void tColDataReset(SColData *pColData); -void tColDataClear(void *ph); +void tColDataDestroy(void *ph); int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); int32_t tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index 48fb0bb5f4..88f0777f57 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -681,7 +681,7 @@ int32_t tGetTSRow(uint8_t *p, STSRow2 **ppRow) { return n; } -// STSchema +// STSchema ======================================== int32_t tTSchemaCreate(int32_t sver, SSchema *pSchema, int32_t ncols, STSchema **ppTSchema) { *ppTSchema = (STSchema *)taosMemoryMalloc(sizeof(STSchema) + sizeof(STColumn) * ncols); if (*ppTSchema == NULL) { @@ -721,9 +721,7 @@ void tTSchemaDestroy(STSchema *pTSchema) { if (pTSchema) taosMemoryFree(pTSchema); } -// STSRowBuilder - -// STag +// STag ======================================== static int tTagValCmprFn(const void *p1, const void *p2) { if (((STagVal *)p1)->cid < ((STagVal *)p2)->cid) { return -1; @@ -1176,6 +1174,14 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) { #endif // SColData ======================================== +void tColDataDestroy(void *ph) { + SColData *pColData = (SColData *)ph; + + tFree(pColData->pBitMap); + tFree((uint8_t *)pColData->aOffset); + tFree(pColData->pData); +} + void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { pColData->cid = cid; pColData->type = type; @@ -1189,14 +1195,6 @@ void tColDataReset(SColData *pColData) { pColData->nData = 0; } -void tColDataClear(void *ph) { - SColData *pColData = (SColData *)ph; - - tFree(pColData->pBitMap); - tFree((uint8_t *)pColData->aOffset); - tFree(pColData->pData); -} - int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { int32_t code = 0; int64_t size; diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 1a109b2cf6..0a78085db2 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -940,7 +940,7 @@ void tBlockDataDestroy(SBlockData *pBlockData, int8_t deepClear) { tFree((uint8_t *)pBlockData->aVersion); tFree((uint8_t *)pBlockData->aTSKEY); taosArrayDestroy(pBlockData->aIdx); - taosArrayDestroyEx(pBlockData->aColData, deepClear ? tColDataClear : NULL); + taosArrayDestroyEx(pBlockData->aColData, deepClear ? tColDataDestroy : NULL); pBlockData->aUid = NULL; pBlockData->aVersion = NULL; pBlockData->aTSKEY = NULL; From 9e5e8d9969940c1846975426804845ed5b6f465f Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 15:23:45 +0800 Subject: [PATCH 04/50] more code --- source/common/src/tdataformat.c | 120 ++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index 88f0777f57..ec20baa024 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1174,6 +1174,126 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) { #endif // SColData ======================================== +static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVal) { + int32_t code = 0; + + if (IS_VAR_DATA_TYPE(pColData->type)) { + code = tRealloc((uint8_t **)(&pColData->aOffset), sizeof(int32_t) * (pColData->nVal + 1)); + if (code) goto _exit; + pColData->aOffset[pColData->nVal] = pColData->nData; + + // value + if ((!pColVal->isNone) && (!pColVal->isNull)) { + code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); + if (code) goto _exit; + memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); + pColData->nData += pColVal->value.nData; + } + } else { + code = tRealloc(&pColData->pData, pColData->nData + tDataTypes[pColData->type].bytes); + if (code) goto _exit; + pColData->nData += tPutValue(pColData->pData + pColData->nData, &pColVal->value, pColVal->type); + } + +_exit: + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue0(SColData *pColData, SColVal *pColVal) { + int32_t code = 0; + + if (pColVal->isNone) { + pColData->flag = HAS_NONE; + } else if (pColVal->isNull) { + pColData->flag = HAS_NULL; + } else { + pColData->flag = HAS_VALUE; + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + } + pColData->nVal++; + +_exit: + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue1(SColData *pColData, SColVal *pColVal) { // HAS_NONE + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue2(SColData *pColData, SColVal *pColVal) { // HAS_NULL + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pColVal) { // HAS_NONE | HAS_NULL + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue4(SColData *pColData, SColVal *pColVal) { // HAS_VALUE + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue5(SColData *pColData, SColVal *pColVal) { // HAS_VALUE | HAS_NONE + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue6(SColData *pColData, SColVal *pColVal) { // HAS_VALUE | HAS_NULL + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue7(SColData *pColData, + SColVal *pColVal) { // HAS_VALUE | HAS_NULL | HAS_NONE + int32_t code = 0; + + if (pColVal->isNone) { + } else if (pColVal->isNull) { + } else { + } + pColData->nVal++; + + return code; +} + void tColDataDestroy(void *ph) { SColData *pColData = (SColData *)ph; From 10749dc607e00e3d1919f5abdc104d32038140b5 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 16:11:24 +0800 Subject: [PATCH 05/50] refact code --- source/common/src/tdataformat.c | 125 +++++++++++--------------------- 1 file changed, 44 insertions(+), 81 deletions(-) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index ec20baa024..fb18fb9e0f 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1174,6 +1174,27 @@ STSchema *tdGetSchemaFromBuilder(STSchemaBuilder *pBuilder) { #endif // SColData ======================================== +void tColDataDestroy(void *ph) { + SColData *pColData = (SColData *)ph; + + tFree(pColData->pBitMap); + tFree((uint8_t *)pColData->aOffset); + tFree(pColData->pData); +} + +void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { + pColData->cid = cid; + pColData->type = type; + pColData->smaOn = smaOn; + tColDataReset(pColData); +} + +void tColDataReset(SColData *pColData) { + pColData->nVal = 0; + pColData->flag = 0; + pColData->nData = 0; +} + static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVal) { int32_t code = 0; @@ -1198,7 +1219,7 @@ static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVa _exit: return code; } -static FORCE_INLINE int32_t tColDataAppendValue0(SColData *pColData, SColVal *pColVal) { +static FORCE_INLINE int32_t tColDataAppendValue0(SColData *pColData, SColVal *pColVal) { // 0 int32_t code = 0; if (pColVal->isNone) { @@ -1220,7 +1241,11 @@ static FORCE_INLINE int32_t tColDataAppendValue1(SColData *pColData, SColVal *pC if (pColVal->isNone) { } else if (pColVal->isNull) { + pColData->flag |= HAS_NULL; + // TODO } else { + pColData->flag |= HAS_VALUE; + // TODO } pColData->nVal++; @@ -1230,8 +1255,12 @@ static FORCE_INLINE int32_t tColDataAppendValue2(SColData *pColData, SColVal *pC int32_t code = 0; if (pColVal->isNone) { + pColData->flag |= HAS_NONE; + // TODO } else if (pColVal->isNull) { } else { + pColData->flag |= HAS_VALUE; + // TODO } pColData->nVal++; @@ -1293,78 +1322,25 @@ static FORCE_INLINE int32_t tColDataAppendValue7(SColData *pColData, return code; } - -void tColDataDestroy(void *ph) { - SColData *pColData = (SColData *)ph; - - tFree(pColData->pBitMap); - tFree((uint8_t *)pColData->aOffset); - tFree(pColData->pData); -} - -void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { - pColData->cid = cid; - pColData->type = type; - pColData->smaOn = smaOn; - tColDataReset(pColData); -} - -void tColDataReset(SColData *pColData) { - pColData->nVal = 0; - pColData->flag = 0; - pColData->nData = 0; -} +static int32_t (*tColDataAppendValueImpl[])(SColData *pColData, SColVal *pColVal) = { + tColDataAppendValue0, // 0 + tColDataAppendValue1, // HAS_NONE + tColDataAppendValue2, // HAS_NULL + tColDataAppendValue3, // HAS_NULL | HAS_NONE + tColDataAppendValue4, // HAS_VALUE + tColDataAppendValue5, // HAS_VALUE | HAS_NONE + tColDataAppendValue6, // HAS_VALUE | HAS_NULL + tColDataAppendValue7 // HAS_VALUE | HAS_NULL | HAS_NONE +}; int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { int32_t code = 0; - int64_t size; - SValue value = {0}; - SValue *pValue = &value; - ASSERT(pColVal->cid == pColData->cid); - ASSERT(pColVal->type == pColData->type); + ASSERT(pColData->cid == pColVal->cid); + ASSERT(pColData->type == pColVal->type); - // realloc bitmap - size = BIT2_SIZE(pColData->nVal + 1); - code = tRealloc(&pColData->pBitMap, size); + code = tColDataAppendValueImpl[pColData->flag](pColData, pColVal); if (code) goto _exit; - if ((pColData->nVal & 3) == 0) { - pColData->pBitMap[pColData->nVal >> 2] = 0; - } - - // put value - if (pColVal->isNone) { - pColData->flag |= HAS_NONE; - SET_BIT2(pColData->pBitMap, pColData->nVal, 0); - } else if (pColVal->isNull) { - pColData->flag |= HAS_NULL; - SET_BIT2(pColData->pBitMap, pColData->nVal, 1); - } else { - pColData->flag |= HAS_VALUE; - SET_BIT2(pColData->pBitMap, pColData->nVal, 2); - pValue = &pColVal->value; - } - - if (IS_VAR_DATA_TYPE(pColData->type)) { - // offset - code = tRealloc((uint8_t **)&pColData->aOffset, sizeof(int32_t) * (pColData->nVal + 1)); - if (code) goto _exit; - pColData->aOffset[pColData->nVal] = pColData->nData; - - // value - if ((!pColVal->isNone) && (!pColVal->isNull)) { - code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); - if (code) goto _exit; - memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); - pColData->nData += pColVal->value.nData; - } - } else { - code = tRealloc(&pColData->pData, pColData->nData + tPutValue(NULL, pValue, pColVal->type)); - if (code) goto _exit; - pColData->nData += tPutValue(pColData->pData + pColData->nData, pValue, pColVal->type); - } - - pColData->nVal++; _exit: return code; @@ -1450,17 +1426,4 @@ int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { _exit: return code; -} - -static FORCE_INLINE int32_t tColDataCmprFn(const void *p1, const void *p2) { - SColData *pColData1 = (SColData *)p1; - SColData *pColData2 = (SColData *)p2; - - if (pColData1->cid < pColData2->cid) { - return -1; - } else if (pColData1->cid > pColData2->cid) { - return 1; - } - - return 0; -} +} \ No newline at end of file From 0d7e1eb4e03a02d1e9995285a28a9b4106ecd412 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 13 Sep 2022 16:45:40 +0800 Subject: [PATCH 06/50] fix(query): twa function output NULL if input has overlap timestamps TD-18224 --- source/libs/function/src/builtinsimpl.c | 54 ++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 0d7fd1a6da..35e3e07839 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -5398,8 +5398,8 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { int32_t i = pInput->startRowIndex; if (pCtx->start.key != INT64_MIN) { - ASSERT((pCtx->start.key < tsList[i] && pCtx->order == TSDB_ORDER_ASC) || - (pCtx->start.key > tsList[i] && pCtx->order == TSDB_ORDER_DESC)); + //ASSERT((pCtx->start.key < tsList[i] && pCtx->order == TSDB_ORDER_ASC) || + // (pCtx->start.key > tsList[i] && pCtx->order == TSDB_ORDER_DESC)); ASSERT(last->key == INT64_MIN); for (; i < pInput->numOfRows + pInput->startRowIndex; ++i) { @@ -5446,6 +5446,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5461,6 +5466,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5475,6 +5485,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5489,6 +5504,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5503,6 +5523,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5517,6 +5542,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5531,6 +5561,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5545,6 +5580,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5559,6 +5599,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; @@ -5573,6 +5618,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + if (pInfo->p.key == st.key) { + numOfElems = 0; + goto _twa_over; + } + INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; From b6daab624b6fc62481b449d95b9797fb1a984e65 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 17:30:20 +0800 Subject: [PATCH 07/50] more code --- include/common/tdataformat.h | 4 +- source/common/src/tdataformat.c | 137 +++++++++++++++++-------- source/dnode/vnode/src/tsdb/tsdbUtil.c | 2 +- 3 files changed, 96 insertions(+), 47 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 4e5ecd90dc..726e0eba6b 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -107,10 +107,10 @@ int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, voi // SColData ================================ void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); -void tColDataReset(SColData *pColData); +void tColDataClear(SColData *pColData); void tColDataDestroy(void *ph); int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); -int32_t tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); +void tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); int32_t tPutColData(uint8_t *p, SColData *pColData); int32_t tGetColData(uint8_t *p, SColData *pColData); diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index fb18fb9e0f..ee68e53e18 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1186,10 +1186,10 @@ void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn) { pColData->cid = cid; pColData->type = type; pColData->smaOn = smaOn; - tColDataReset(pColData); + tColDataClear(pColData); } -void tColDataReset(SColData *pColData) { +void tColDataClear(SColData *pColData) { pColData->nVal = 0; pColData->flag = 0; pColData->nData = 0; @@ -1346,6 +1346,97 @@ _exit: return code; } +static FORCE_INLINE void tColDataGetValue1(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NONE + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); +} +static FORCE_INLINE void tColDataGetValue2(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NULL + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); +} +static FORCE_INLINE void tColDataGetValue3(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NULL|HAS_NONE + switch (GET_BIT1(pColData->pBitMap, iVal)) { + case 0: + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); + break; + case 1: + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); + break; + default: + ASSERT(0); + } +} +static FORCE_INLINE void tColDataGetValue4(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_VALUE + SValue value; + if (IS_VAR_DATA_TYPE(pColData->type)) { + if (iVal + 1 < pColData->nVal) { + value.nData = pColData->aOffset[iVal + 1] - pColData->aOffset[iVal]; + } else { + value.nData = pColData->nData - pColData->aOffset[iVal]; + } + value.pData = pColData->pData + pColData->aOffset[iVal]; + } else { + tGetValue(pColData->pData + tDataTypes[pColData->type].bytes * iVal, &value, pColData->type); + } + *pColVal = COL_VAL_VALUE(pColData->cid, pColData->type, value); +} +static FORCE_INLINE void tColDataGetValue5(SColData *pColData, int32_t iVal, + SColVal *pColVal) { // HAS_VALUE|HAS_NONE + switch (GET_BIT1(pColData->pBitMap, iVal)) { + case 0: + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); + break; + case 1: + tColDataGetValue4(pColData, iVal, pColVal); + break; + default: + ASSERT(0); + } +} +static FORCE_INLINE void tColDataGetValue6(SColData *pColData, int32_t iVal, + SColVal *pColVal) { // HAS_VALUE|HAS_NULL + switch (GET_BIT1(pColData->pBitMap, iVal)) { + case 0: + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); + break; + case 1: + tColDataGetValue4(pColData, iVal, pColVal); + break; + default: + ASSERT(0); + } +} +static FORCE_INLINE void tColDataGetValue7(SColData *pColData, int32_t iVal, + SColVal *pColVal) { // HAS_VALUE|HAS_NULL|HAS_NONE + switch (GET_BIT2(pColData->pBitMap, iVal)) { + case 0: + *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); + break; + case 1: + *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); + break; + case 2: + tColDataGetValue4(pColData, iVal, pColVal); + break; + default: + ASSERT(0); + } +} +static void (*tColDataGetValueImpl[])(SColData *pColData, int32_t iVal, SColVal *pColVal) = { + NULL, // 0 + tColDataGetValue1, // HAS_NONE + tColDataGetValue2, // HAS_NULL + tColDataGetValue3, // HAS_NULL | HAS_NONE + tColDataGetValue4, // HAS_VALUE + tColDataGetValue5, // HAS_VALUE | HAS_NONE + tColDataGetValue6, // HAS_VALUE | HAS_NULL + tColDataGetValue7 // HAS_VALUE | HAS_NULL | HAS_NONE +}; +void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { + ASSERT(iVal >= 0 && iVal < pColData->nVal); + ASSERT(pColData->flag); + + tColDataGetValueImpl[pColData->flag](pColData, iVal, pColVal); +} + int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { int32_t code = 0; int32_t size; @@ -1382,48 +1473,6 @@ int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { if (code) goto _exit; memcpy(pColDataDest->pData, pColDataSrc->pData, pColDataDest->nData); -_exit: - return code; -} - -int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { - int32_t code = 0; - - ASSERT(iVal < pColData->nVal); - ASSERT(pColData->flag); - - if (pColData->flag == HAS_NONE) { - *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); - goto _exit; - } else if (pColData->flag == HAS_NULL) { - *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); - goto _exit; - } else if (pColData->flag != HAS_VALUE) { - uint8_t v = GET_BIT2(pColData->pBitMap, iVal); - if (v == 0) { - *pColVal = COL_VAL_NONE(pColData->cid, pColData->type); - goto _exit; - } else if (v == 1) { - *pColVal = COL_VAL_NULL(pColData->cid, pColData->type); - goto _exit; - } - } - - // get value - SValue value; - if (IS_VAR_DATA_TYPE(pColData->type)) { - if (iVal + 1 < pColData->nVal) { - value.nData = pColData->aOffset[iVal + 1] - pColData->aOffset[iVal]; - } else { - value.nData = pColData->nData - pColData->aOffset[iVal]; - } - - value.pData = pColData->pData + pColData->aOffset[iVal]; - } else { - tGetValue(pColData->pData + tDataTypes[pColData->type].bytes * iVal, &value, pColData->type); - } - *pColVal = COL_VAL_VALUE(pColData->cid, pColData->type, value); - _exit: return code; } \ No newline at end of file diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 0a78085db2..32fc7b82a1 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -1009,7 +1009,7 @@ void tBlockDataClear(SBlockData *pBlockData) { pBlockData->nRow = 0; for (int32_t iColData = 0; iColData < taosArrayGetSize(pBlockData->aIdx); iColData++) { SColData *pColData = tBlockDataGetColDataByIdx(pBlockData, iColData); - tColDataReset(pColData); + tColDataClear(pColData); } } From 6b2bf42f6824df1599303768160cfc403c04b7c1 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 13 Sep 2022 16:45:40 +0800 Subject: [PATCH 08/50] fix(query): twa function output NULL if input has overlap timestamps TD-18224 --- include/util/taoserror.h | 1 + source/libs/function/src/builtinsimpl.c | 30 +++++++++---------------- source/util/src/terror.c | 1 + 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/include/util/taoserror.h b/include/util/taoserror.h index d16a599811..0058b03b30 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -577,6 +577,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_FUNC_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2802) #define TSDB_CODE_FUNC_FUNTION_PARA_VALUE TAOS_DEF_ERROR_CODE(0, 0x2803) #define TSDB_CODE_FUNC_NOT_BUILTIN_FUNTION TAOS_DEF_ERROR_CODE(0, 0x2804) +#define TSDB_CODE_FUNC_DUP_TIMESTAMP TAOS_DEF_ERROR_CODE(0, 0x012B) //udf #define TSDB_CODE_UDF_STOPPING TAOS_DEF_ERROR_CODE(0, 0x2901) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 35e3e07839..7d8c231c15 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -5447,8 +5447,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5467,8 +5466,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5486,8 +5484,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5505,8 +5502,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5524,8 +5520,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5543,8 +5538,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5562,8 +5556,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5581,8 +5574,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5600,8 +5592,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); @@ -5619,8 +5610,7 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { numOfElems++; if (pInfo->p.key == st.key) { - numOfElems = 0; - goto _twa_over; + return TSDB_CODE_FUNC_DUP_TIMESTAMP; } INIT_INTP_POINT(st, tsList[i], val[i]); diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 044cdc86b4..ab0771d218 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -579,6 +579,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_FUNTION_PARA_NUM, "Invalid function par TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_FUNTION_PARA_TYPE, "Invalid function para type") TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_FUNTION_PARA_VALUE, "Invalid function para value") TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_NOT_BUILTIN_FUNTION, "Not buildin function") +TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_DUP_TIMESTAMP, "Duplicate timestamps not allowed in function") //udf TAOS_DEFINE_ERROR(TSDB_CODE_UDF_STOPPING, "udf is stopping") From c497b7b77d67db3a03458f0f34d081d4f5f031c9 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 13 Sep 2022 18:17:24 +0800 Subject: [PATCH 09/50] refact more code --- include/common/tdataformat.h | 6 +- source/common/src/tdataformat.c | 190 +++++++++++++++++++++++++++----- 2 files changed, 163 insertions(+), 33 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 726e0eba6b..c51eff6a48 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -38,9 +38,9 @@ typedef struct STagVal STagVal; typedef struct STag STag; typedef struct SColData SColData; -#define HAS_NONE ((int8_t)0x1) -#define HAS_NULL ((int8_t)0x2) -#define HAS_VALUE ((int8_t)0x4) +#define HAS_NONE ((uint8_t)0x1) +#define HAS_NULL ((uint8_t)0x2) +#define HAS_VALUE ((uint8_t)0x4) // bitmap ================================ const static uint8_t BIT2_MAP[4][4] = {{0b00000000, 0b00000001, 0b00000010, 0}, diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index ee68e53e18..6affa2bf50 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1239,87 +1239,218 @@ _exit: static FORCE_INLINE int32_t tColDataAppendValue1(SColData *pColData, SColVal *pColVal) { // HAS_NONE int32_t code = 0; - if (pColVal->isNone) { - } else if (pColVal->isNull) { - pColData->flag |= HAS_NULL; - // TODO - } else { - pColData->flag |= HAS_VALUE; - // TODO + if (!pColVal->isNone) { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT1(pColData->pBitMap, iVal, 0); + } + SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + + if (pColVal->isNull) { + pColData->flag |= HAS_NULL; + } else { + pColData->flag |= HAS_VALUE; + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + } } pColData->nVal++; +_exit: return code; } static FORCE_INLINE int32_t tColDataAppendValue2(SColData *pColData, SColVal *pColVal) { // HAS_NULL int32_t code = 0; - if (pColVal->isNone) { - pColData->flag |= HAS_NONE; - // TODO - } else if (pColVal->isNull) { - } else { - pColData->flag |= HAS_VALUE; - // TODO + if (!pColVal->isNull) { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + if (pColVal->isNone) { + pColData->flag |= HAS_NONE; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT1(pColData->pBitMap, iVal, 1); + } + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + } else { + pColData->flag |= HAS_VALUE; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT1(pColData->pBitMap, iVal, 0); + } + SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + } } pColData->nVal++; +_exit: return code; } -static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pColVal) { // HAS_NONE | HAS_NULL +static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pColVal) { // HAS_NULL|HAS_NONE int32_t code = 0; if (pColVal->isNone) { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else if (pColVal->isNull) { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + SET_BIT1(pColData->pBitMap, pColData->nVal, 1); } else { + uint8_t *pBitMap = NULL; + code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal)); + } + SET_BIT2(pBitMap, pColData->nVal, 2); + + pColData->flag |= HAS_VALUE; + + tFree(pColData->pBitMap); + pColData->pBitMap = pBitMap; + + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; } pColData->nVal++; +_exit: return code; } static FORCE_INLINE int32_t tColDataAppendValue4(SColData *pColData, SColVal *pColVal) { // HAS_VALUE int32_t code = 0; if (pColVal->isNone) { + pColData->flag |= HAS_NONE; + + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT1(pColData->pBitMap, iVal, 1); + } + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else if (pColVal->isNull) { + pColData->flag |= HAS_NULL; + + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { + SET_BIT1(pColData->pBitMap, iVal, 1); + } + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else { + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; } pColData->nVal++; +_exit: return code; } -static FORCE_INLINE int32_t tColDataAppendValue5(SColData *pColData, SColVal *pColVal) { // HAS_VALUE | HAS_NONE +static FORCE_INLINE int32_t tColDataAppendValue5(SColData *pColData, SColVal *pColVal) { // HAS_VALUE|HAS_NONE + int32_t code = 0; + + if (pColVal->isNull) { + pColData->flag |= HAS_NULL; + + uint8_t *pBitMap = NULL; + code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nData; iVal++) { + SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 0); + } + SET_BIT2(pBitMap, pColData->nVal, 1); + + tFree(pColData->pBitMap); + pColData->pBitMap = pBitMap; + } else { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + if (pColVal->isNone) { + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + } else { + SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + } + } + + pColData->nVal++; + +_exit: + return code; +} +static FORCE_INLINE int32_t tColDataAppendValue6(SColData *pColData, SColVal *pColVal) { // HAS_VALUE|HAS_NULL int32_t code = 0; if (pColVal->isNone) { - } else if (pColVal->isNull) { - } else { - } - pColData->nVal++; - - return code; -} -static FORCE_INLINE int32_t tColDataAppendValue6(SColData *pColData, SColVal *pColVal) { // HAS_VALUE | HAS_NULL - int32_t code = 0; - - if (pColVal->isNone) { - } else if (pColVal->isNull) { + pColData->flag |= HAS_NONE; + + uint8_t *pBitMap = NULL; + code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + for (int32_t iVal = 0; iVal < pColData->nData; iVal++) { + SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 1); + } + SET_BIT2(pBitMap, pColData->nVal, 0); + + tFree(pColData->pBitMap); + pColData->pBitMap = pBitMap; } else { + code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + + if (pColVal->isNull) { + SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + } else { + SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + } } pColData->nVal++; +_exit: return code; } static FORCE_INLINE int32_t tColDataAppendValue7(SColData *pColData, - SColVal *pColVal) { // HAS_VALUE | HAS_NULL | HAS_NONE + SColVal *pColVal) { // HAS_VALUE|HAS_NULL|HAS_NONE int32_t code = 0; + code = tRealloc(&pColData->pBitMap, BIT2_SIZE(pColData->nVal + 1)); + if (code) goto _exit; + if (pColVal->isNone) { + SET_BIT2(pColData->pBitMap, pColData->nVal, 0); } else if (pColVal->isNull) { + SET_BIT2(pColData->pBitMap, pColData->nVal, 1); } else { + SET_BIT2(pColData->pBitMap, pColData->nVal, 2); + + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; } pColData->nVal++; +_exit: return code; } static int32_t (*tColDataAppendValueImpl[])(SColData *pColData, SColVal *pColVal) = { @@ -1332,7 +1463,6 @@ static int32_t (*tColDataAppendValueImpl[])(SColData *pColData, SColVal *pColVal tColDataAppendValue6, // HAS_VALUE | HAS_NULL tColDataAppendValue7 // HAS_VALUE | HAS_NULL | HAS_NONE }; - int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { int32_t code = 0; From 5463159a3d5a8f56a4f3f08f9864a79c24013c0d Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 13 Sep 2022 18:24:29 +0800 Subject: [PATCH 10/50] fix twa function input dup timestamps --- source/libs/function/src/builtinsimpl.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 7d8c231c15..5862a06aac 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -5446,11 +5446,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5465,11 +5465,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5483,11 +5483,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5501,11 +5501,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5519,11 +5519,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5537,11 +5537,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5555,11 +5555,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5573,11 +5573,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5591,11 +5591,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } @@ -5609,11 +5609,11 @@ int32_t twaFunction(SqlFunctionCtx* pCtx) { } numOfElems++; + INIT_INTP_POINT(st, tsList[i], val[i]); if (pInfo->p.key == st.key) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } - INIT_INTP_POINT(st, tsList[i], val[i]); pInfo->dOutput += twa_get_area(pInfo->p, st); pInfo->p = st; } From 9ee003c971aa2c064c1da800aa1e366ffd262eab Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 13 Sep 2022 18:32:17 +0800 Subject: [PATCH 11/50] fix test case --- tests/system-test/2-query/twa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system-test/2-query/twa.py b/tests/system-test/2-query/twa.py index 62940477cf..4c163da485 100644 --- a/tests/system-test/2-query/twa.py +++ b/tests/system-test/2-query/twa.py @@ -124,7 +124,7 @@ class TDTestCase: tdSql.checkData(0,1,4.500000000) # mixup with other functions - tdSql.query(f"select twa(c1),twa(c2),max(c1),elapsed(ts) from {dbname}.stb1 ") + tdSql.query(f"select twa(c1),twa(c2),max(c1),elapsed(ts) from {dbname}.ct1 ") tdSql.checkData(0,0,1.000000000) tdSql.checkData(0,1,11111.000000000) tdSql.checkData(0,2,1) From 0e1a4212075a8f87557acec8d82a0734120e89e0 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Wed, 14 Sep 2022 09:35:57 +0800 Subject: [PATCH 12/50] refact --- source/common/src/tdataformat.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index 6affa2bf50..ed2d68961f 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1457,11 +1457,11 @@ static int32_t (*tColDataAppendValueImpl[])(SColData *pColData, SColVal *pColVal tColDataAppendValue0, // 0 tColDataAppendValue1, // HAS_NONE tColDataAppendValue2, // HAS_NULL - tColDataAppendValue3, // HAS_NULL | HAS_NONE + tColDataAppendValue3, // HAS_NULL|HAS_NONE tColDataAppendValue4, // HAS_VALUE - tColDataAppendValue5, // HAS_VALUE | HAS_NONE - tColDataAppendValue6, // HAS_VALUE | HAS_NULL - tColDataAppendValue7 // HAS_VALUE | HAS_NULL | HAS_NONE + tColDataAppendValue5, // HAS_VALUE|HAS_NONE + tColDataAppendValue6, // HAS_VALUE|HAS_NULL + tColDataAppendValue7 // HAS_VALUE|HAS_NULL|HAS_NONE }; int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { int32_t code = 0; From e076b8c7c24208b3c9d2ca3653c6930454380f85 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 14 Sep 2022 11:05:24 +0800 Subject: [PATCH 13/50] fix test case --- tests/system-test/2-query/max_partition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system-test/2-query/max_partition.py b/tests/system-test/2-query/max_partition.py index 01c2677242..08bb7675ad 100644 --- a/tests/system-test/2-query/max_partition.py +++ b/tests/system-test/2-query/max_partition.py @@ -181,7 +181,7 @@ class TDTestCase: # bug need fix tdSql.checkData(0,1,None) - tdSql.query(f"select c1 , twa(c1) from {dbname}.stb partition by c1 order by c1") + tdSql.query(f"select c1 , twa(c1) from {dbname}.sub_stb_1 partition by c1 order by c1") tdSql.checkRows(11) tdSql.checkData(0,1,None) From 892d7861f08ef62da6f6748b4fd24df6c041b3f6 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Wed, 14 Sep 2022 11:06:37 +0800 Subject: [PATCH 14/50] fix(tsc): avoid mem leak --- source/client/src/clientImpl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index 39b4b069a0..e7b34ab783 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1369,7 +1369,7 @@ int32_t doProcessMsgFromServer(void* param) { updateTargetEpSet(pSendInfo, pTscObj, pMsg, pEpSet); SDataBuf buf = { - .msgType = pMsg->msgType, .len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle, .pEpSet = pEpSet}; + .msgType = pMsg->msgType, .len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle, .pEpSet = NULL}; if (pMsg->contLen > 0) { buf.pData = taosMemoryCalloc(1, pMsg->contLen); @@ -1384,6 +1384,8 @@ int32_t doProcessMsgFromServer(void* param) { pSendInfo->fp(pSendInfo->param, &buf, pMsg->code); rpcFreeCont(pMsg->pCont); destroySendMsgInfo(pSendInfo); + + taosMemoryFree(arg->pEpset); taosMemoryFree(arg); return TSDB_CODE_SUCCESS; } From 0a6ec7c0d763e288118e6e88352c7d9115244ac0 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 14 Sep 2022 11:17:12 +0800 Subject: [PATCH 15/50] fix(query): restrict max/min function input type not including timestamp type --- source/libs/function/src/builtins.c | 20 ++------------------ source/libs/function/src/builtinsimpl.c | 6 +++--- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 5844784ea4..f3d3393ac3 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -311,22 +311,6 @@ static int32_t translateInOutStr(SFunctionNode* pFunc, char* pErrBuf, int32_t le return TSDB_CODE_SUCCESS; } -static int32_t translateMinMax(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - if (1 != LIST_LENGTH(pFunc->pParameterList)) { - return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); - } - - uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_TIMESTAMP_TYPE(paraType) && !IS_NUMERIC_TYPE(paraType) && !IS_NULL_TYPE(paraType)) { - return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); - } else if (IS_NULL_TYPE(paraType)) { - paraType = TSDB_DATA_TYPE_BIGINT; - } - - pFunc->node.resType = (SDataType){.bytes = tDataTypes[paraType].bytes, .type = paraType}; - return TSDB_CODE_SUCCESS; -} - static int32_t translateTrimStr(SFunctionNode* pFunc, char* pErrBuf, int32_t len, bool isLtrim) { if (1 != LIST_LENGTH(pFunc->pParameterList)) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); @@ -2076,7 +2060,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .name = "min", .type = FUNCTION_TYPE_MIN, .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED | FUNC_MGT_SELECT_FUNC, - .translateFunc = translateMinMax, + .translateFunc = translateInOutNum, .dataRequiredFunc = statisDataRequired, .getEnvFunc = getMinmaxFuncEnv, .initFunc = minmaxFunctionSetup, @@ -2091,7 +2075,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .name = "max", .type = FUNCTION_TYPE_MAX, .classification = FUNC_MGT_AGG_FUNC | FUNC_MGT_SPECIAL_DATA_REQUIRED | FUNC_MGT_SELECT_FUNC, - .translateFunc = translateMinMax, + .translateFunc = translateInOutNum, .dataRequiredFunc = statisDataRequired, .getEnvFunc = getMinmaxFuncEnv, .initFunc = minmaxFunctionSetup, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 0d7fd1a6da..c9e345f49f 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -1204,7 +1204,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); } } else { - if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) { + if (IS_SIGNED_NUMERIC_TYPE(type)) { int64_t prev = 0; GET_TYPED_DATA(prev, int64_t, type, &pBuf->v); @@ -1263,7 +1263,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { int32_t start = pInput->startRowIndex; int32_t numOfRows = pInput->numOfRows; - if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) { + if (IS_SIGNED_NUMERIC_TYPE(type) || type == TSDB_DATA_TYPE_BOOL) { if (type == TSDB_DATA_TYPE_TINYINT || type == TSDB_DATA_TYPE_BOOL) { int8_t* pData = (int8_t*)pCol->pData; int8_t* val = (int8_t*)&pBuf->v; @@ -1357,7 +1357,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { numOfElems += 1; } - } else if (type == TSDB_DATA_TYPE_BIGINT || type == TSDB_DATA_TYPE_TIMESTAMP) { + } else if (type == TSDB_DATA_TYPE_BIGINT) { int64_t* pData = (int64_t*)pCol->pData; int64_t* val = (int64_t*)&pBuf->v; From 2c2d5c16ed0410ae58e78c8b5586dbd583f945b2 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 14 Sep 2022 13:29:06 +0800 Subject: [PATCH 16/50] fix: fix insert memory leak --- source/client/src/clientHb.c | 3 +++ source/libs/parser/src/parInsert.c | 4 +--- source/libs/parser/src/parUtil.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c index 84a827ed78..e484e3c59c 100644 --- a/source/client/src/clientHb.c +++ b/source/client/src/clientHb.c @@ -414,6 +414,9 @@ int32_t hbGetQueryBasicInfo(SClientHbKey *connKey, SClientHbReq *req) { int32_t code = hbBuildQueryDesc(hbBasic, pTscObj); if (code) { releaseTscObj(connKey->tscRid); + if (hbBasic->queryDesc) { + taosArrayDestroyEx(hbBasic->queryDesc, tFreeClientHbQueryDesc); + } taosMemoryFree(hbBasic); return code; } diff --git a/source/libs/parser/src/parInsert.c b/source/libs/parser/src/parInsert.c index 162161b67a..d351333c3e 100644 --- a/source/libs/parser/src/parInsert.c +++ b/source/libs/parser/src/parInsert.c @@ -1420,9 +1420,7 @@ static int32_t parseDataFromFile(SInsertParseContext* pCxt, SToken filePath, STa } static void destroyInsertParseContextForTable(SInsertParseContext* pCxt) { - if (!pCxt->pComCxt->async) { - taosMemoryFreeClear(pCxt->pTableMeta); - } + taosMemoryFreeClear(pCxt->pTableMeta); destroyBoundColumnInfo(&pCxt->tags); tdDestroySVCreateTbReq(&pCxt->createTblReq); } diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 32513fd0b6..daab80667c 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -1124,7 +1124,7 @@ int32_t getTableMetaFromCacheForInsert(SArray* pTableMetaPos, SParseMetaCache* p int32_t reqIndex = *(int32_t*)taosArrayGet(pTableMetaPos, tableNo); SMetaRes* pRes = taosArrayGet(pMetaCache->pTableMetaData, reqIndex); if (TSDB_CODE_SUCCESS == pRes->code) { - *pMeta = pRes->pRes; + *pMeta = tableMetaDup(pRes->pRes); if (NULL == *pMeta) { return TSDB_CODE_OUT_OF_MEMORY; } From 8905d37b7065ffc0832ae96d9141e55e55ff76b8 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 14 Sep 2022 13:35:46 +0800 Subject: [PATCH 17/50] fix test cases --- tests/system-test/2-query/max.py | 21 ++------------- tests/system-test/2-query/min.py | 45 +++++--------------------------- 2 files changed, 8 insertions(+), 58 deletions(-) diff --git a/tests/system-test/2-query/max.py b/tests/system-test/2-query/max.py index 169b1c2c38..5cc9a2d9e8 100644 --- a/tests/system-test/2-query/max.py +++ b/tests/system-test/2-query/max.py @@ -38,18 +38,7 @@ class TDTestCase: elif i>=9: tdSql.checkData(0, 0, np.max(floatData)) - tdSql.query(f"select max(now()) from {dbname}.stb_1") - tdSql.checkRows(1) - - tdSql.query(f"select last(ts) from {dbname}.stb_1") - lastTs = tdSql.getData(0, 0) - tdSql.query(f"select max(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, lastTs) - - tdSql.query(f"select last(ts) from {dbname}.stb") - lastTs = tdSql.getData(0, 0) - tdSql.query(f"select max(ts) from {dbname}.stb") - tdSql.checkData(0, 0, lastTs) + tdSql.error(f"select max(now()) from {dbname}.stb_1") tdSql.query(f"select max(col1) from {dbname}.stb_1 where col2<=5") tdSql.checkData(0,0,5) @@ -78,13 +67,7 @@ class TDTestCase: elif i>=9: tdSql.checkData(0, 0, np.max(floatData)) - tdSql.query(f"select max(now()) from {dbname}.ntb") - tdSql.checkRows(1) - - tdSql.query(f"select last(ts) from {dbname}.ntb") - lastTs = tdSql.getData(0, 0) - tdSql.query(f"select max(ts) from {dbname}.ntb") - tdSql.checkData(0, 0, lastTs) + tdSql.error(f"select max(now()) from {dbname}.ntb") tdSql.query(f"select max(col1) from {dbname}.ntb where col2<=5") tdSql.checkData(0,0,5) diff --git a/tests/system-test/2-query/min.py b/tests/system-test/2-query/min.py index 3d46b7b222..d97c4340f4 100644 --- a/tests/system-test/2-query/min.py +++ b/tests/system-test/2-query/min.py @@ -37,6 +37,8 @@ class TDTestCase: floatData.append(i + 0.1) # max verifacation + tdSql.error(f"select min(now()) from {dbname}.stb_1") + tdSql.error(f"select min(ts) from {dbname}.stb_1") tdSql.error(f"select min(col7) from {dbname}.stb_1") tdSql.error(f"select min(col8) from {dbname}.stb_1") tdSql.error(f"select min(col9) from {dbname}.stb_1") @@ -67,20 +69,9 @@ class TDTestCase: tdSql.query(f"select min(col1) from {dbname}.stb_1 where col2>=5") tdSql.checkData(0,0,5) - tdSql.query(f"select min(now()) from {dbname}.stb_1") - tdSql.checkRows(1) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - + tdSql.error(f"select min(now()) from {dbname}.stb_1") + tdSql.error(f"select min(ts) from {dbname}.stb_1") tdSql.error(f"select min(col7) from {dbname}.stb_1") tdSql.error(f"select min(col8) from {dbname}.stb_1") tdSql.error(f"select min(col9) from {dbname}.stb_1") @@ -111,19 +102,8 @@ class TDTestCase: tdSql.query(f"select min(col1) from {dbname}.stb where col2>=5") tdSql.checkData(0,0,5) - tdSql.query(f"select min(now()) from {dbname}.stb_1") - tdSql.checkRows(1) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - + tdSql.error(f"select min(now()) from {dbname}.stb_1") + tdSql.error(f"select min(ts) from {dbname}.stb_1") tdSql.error(f"select min(col7) from {dbname}.ntb") tdSql.error(f"select min(col8) from {dbname}.ntb") tdSql.error(f"select min(col9) from {dbname}.ntb") @@ -154,19 +134,6 @@ class TDTestCase: tdSql.query(f"select min(col1) from {dbname}.ntb where col2>=5") tdSql.checkData(0,0,5) - tdSql.query(f"select min(now()) from {dbname}.stb_1") - tdSql.checkRows(1) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - - tdSql.query(f"select first(ts) from {dbname}.stb_1") - firstTs = tdSql.getData(0, 0) - tdSql.query(f"select min(ts) from {dbname}.stb_1") - tdSql.checkData(0, 0, firstTs) - def stop(self): tdSql.close() From d2f6a7928686556ea44d9c52f2b59aaeeac25f59 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 14 Sep 2022 13:38:39 +0800 Subject: [PATCH 18/50] fix docs --- docs/en/12-taos-sql/10-function.md | 44 +++++++++++++++--------------- docs/zh/12-taos-sql/10-function.md | 38 +++++++++++++------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/docs/en/12-taos-sql/10-function.md b/docs/en/12-taos-sql/10-function.md index f74d0dbe5c..ab1d2f900b 100644 --- a/docs/en/12-taos-sql/10-function.md +++ b/docs/en/12-taos-sql/10-function.md @@ -126,7 +126,7 @@ SELECT COS(field_name) FROM { tb_name | stb_name } [WHERE clause] SELECT FLOOR(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` -**Description**: The rounded down value of a specific field +**Description**: The rounded down value of a specific field **More explanations**: The restrictions are same as those of the `CEIL` function. #### LOG @@ -173,7 +173,7 @@ SELECT POW(field_name, power) FROM { tb_name | stb_name } [WHERE clause] SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` -**Description**: The rounded value of a specific field. +**Description**: The rounded value of a specific field. **More explanations**: The restrictions are same as those of the `CEIL` function. @@ -434,7 +434,7 @@ SELECT TO_ISO8601(ts[, timezone]) FROM { tb_name | stb_name } [WHERE clause]; **More explanations**: - You can specify a time zone in the following format: [z/Z, +/-hhmm, +/-hh, +/-hh:mm]。 For example, TO_ISO8601(1, "+00:00"). -- If the input is a UNIX timestamp, the precision of the returned value is determined by the digits of the input timestamp +- If the input is a UNIX timestamp, the precision of the returned value is determined by the digits of the input timestamp - If the input is a column of TIMESTAMP type, the precision of the returned value is same as the precision set for the current data base in use @@ -769,14 +769,14 @@ SELECT HISTOGRAM(field_name,bin_type, bin_description, normalized) FROM tb_nam **Explanations**: - bin_type: parameter to indicate the bucket type, valid inputs are: "user_input", "linear_bin", "log_bin"。 -- bin_description: parameter to describe how to generate buckets,can be in the following JSON formats for each bin_type respectively: - - "user_input": "[1, 3, 5, 7]": +- bin_description: parameter to describe how to generate buckets,can be in the following JSON formats for each bin_type respectively: + - "user_input": "[1, 3, 5, 7]": User specified bin values. - + - "linear_bin": "{"start": 0.0, "width": 5.0, "count": 5, "infinity": true}" "start" - bin starting point. "width" - bin offset. "count" - number of bins generated. "infinity" - whether to add(-inf, inf)as start/end point in generated set of bins. The above "linear_bin" descriptor generates a set of bins: [-inf, 0.0, 5.0, 10.0, 15.0, 20.0, +inf]. - + - "log_bin": "{"start":1.0, "factor": 2.0, "count": 5, "infinity": true}" "start" - bin starting point. "factor" - exponential factor of bin offset. "count" - number of bins generated. "infinity" - whether to add(-inf, inf)as start/end point in generated range of bins. The above "linear_bin" descriptor generates a set of bins: [-inf, 1.0, 2.0, 4.0, 8.0, 16.0, +inf]. @@ -862,9 +862,9 @@ SELECT INTERP(field_name) FROM { tb_name | stb_name } [WHERE where_condition] RA - `INTERP` is used to get the value that matches the specified time slice from a column. If no such value exists an interpolation value will be returned based on `FILL` parameter. - The input data of `INTERP` is the value of the specified column and a `where` clause can be used to filter the original data. If no `where` condition is specified then all original data is the input. -- The output time range of `INTERP` is specified by `RANGE(timestamp1,timestamp2)` parameter, with timestamp1<=timestamp2. timestamp1 is the starting point of the output time range and must be specified. timestamp2 is the ending point of the output time range and must be specified. -- The number of rows in the result set of `INTERP` is determined by the parameter `EVERY`. Starting from timestamp1, one interpolation is performed for every time interval specified `EVERY` parameter. -- Interpolation is performed based on `FILL` parameter. +- The output time range of `INTERP` is specified by `RANGE(timestamp1,timestamp2)` parameter, with timestamp1<=timestamp2. timestamp1 is the starting point of the output time range and must be specified. timestamp2 is the ending point of the output time range and must be specified. +- The number of rows in the result set of `INTERP` is determined by the parameter `EVERY`. Starting from timestamp1, one interpolation is performed for every time interval specified `EVERY` parameter. +- Interpolation is performed based on `FILL` parameter. - `INTERP` can only be used to interpolate in single timeline. So it must be used with `partition by tbname` when it's used on a STable. ### LAST @@ -917,7 +917,7 @@ SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]; **Return value type**:Same as the data type of the column being operated upon -**Applicable data types**: Numeric, Timestamp +**Applicable data types**: Numeric **Applicable table types**: standard tables and supertables @@ -932,7 +932,7 @@ SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]; **Return value type**:Same as the data type of the column being operated upon -**Applicable data types**: Numeric, Timestamp +**Applicable data types**: Numeric **Applicable table types**: standard tables and supertables @@ -968,7 +968,7 @@ SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause] **Applicable table types**: standard tables and supertables -**More explanations**: +**More explanations**: This function cannot be used in expression calculation. - Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline @@ -1046,10 +1046,10 @@ SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause] **Applicable table types**: standard tables and supertables -**More explanations**: - +**More explanations**: + - Arithmetic operation can't be performed on the result of `csum` function -- Can only be used with aggregate functions This function can be used with supertables and standard tables. +- Can only be used with aggregate functions This function can be used with supertables and standard tables. - Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline @@ -1067,8 +1067,8 @@ SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHER **Applicable table types**: standard tables and supertables -**More explanation**: - +**More explanation**: + - It can be used together with `PARTITION BY tbname` against a STable. - It can be used together with a selected column. For example: select \_rowts, DERIVATIVE() from。 @@ -1086,7 +1086,7 @@ SELECT {DIFF(field_name, ignore_negative) | DIFF(field_name)} FROM tb_name [WHER **Applicable table types**: standard tables and supertables -**More explanation**: +**More explanation**: - The number of result rows is the number of rows subtracted by one, no output for the first row - It can be used together with a selected column. For example: select \_rowts, DIFF() from。 @@ -1123,9 +1123,9 @@ SELECT MAVG(field_name, K) FROM { tb_name | stb_name } [WHERE clause] **Applicable table types**: standard tables and supertables -**More explanations**: - -- Arithmetic operation can't be performed on the result of `MAVG`. +**More explanations**: + +- Arithmetic operation can't be performed on the result of `MAVG`. - Can only be used with data columns, can't be used with tags. - Can't be used with aggregate functions. - Must be used with `PARTITION BY tbname` when it's used on a STable to force the result on each single timeline diff --git a/docs/zh/12-taos-sql/10-function.md b/docs/zh/12-taos-sql/10-function.md index 9c5b7f771e..86e9aaa80f 100644 --- a/docs/zh/12-taos-sql/10-function.md +++ b/docs/zh/12-taos-sql/10-function.md @@ -127,7 +127,7 @@ SELECT COS(field_name) FROM { tb_name | stb_name } [WHERE clause] SELECT FLOOR(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` -**功能说明**:获得指定字段的向下取整数的结果。 +**功能说明**:获得指定字段的向下取整数的结果。 其他使用说明参见 CEIL 函数描述。 #### LOG @@ -174,7 +174,7 @@ SELECT POW(field_name, power) FROM { tb_name | stb_name } [WHERE clause] SELECT ROUND(field_name) FROM { tb_name | stb_name } [WHERE clause]; ``` -**功能说明**:获得指定字段的四舍五入的结果。 +**功能说明**:获得指定字段的四舍五入的结果。 其他使用说明参见 CEIL 函数描述。 @@ -435,7 +435,7 @@ SELECT TO_ISO8601(ts[, timezone]) FROM { tb_name | stb_name } [WHERE clause]; **使用说明**: - timezone 参数允许输入的时区格式为: [z/Z, +/-hhmm, +/-hh, +/-hh:mm]。例如,TO_ISO8601(1, "+00:00")。 -- 如果输入是表示 UNIX 时间戳的整形,返回格式精度由时间戳的位数决定; +- 如果输入是表示 UNIX 时间戳的整形,返回格式精度由时间戳的位数决定; - 如果输入是 TIMESTAMP 类型的列,返回格式的时间戳精度与当前 DATABASE 设置的时间精度一致。 @@ -770,14 +770,14 @@ SELECT HISTOGRAM(field_name,bin_type, bin_description, normalized) FROM tb_nam **详细说明**: - bin_type 用户指定的分桶类型, 有效输入类型为"user_input“, ”linear_bin", "log_bin"。 -- bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串): - - "user_input": "[1, 3, 5, 7]" +- bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串): + - "user_input": "[1, 3, 5, 7]" 用户指定 bin 的具体数值。 - + - "linear_bin": "{"start": 0.0, "width": 5.0, "count": 5, "infinity": true}" "start" 表示数据起始点,"width" 表示每次 bin 偏移量, "count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点和终点, 生成区间为[-inf, 0.0, 5.0, 10.0, 15.0, 20.0, +inf]。 - + - "log_bin": "{"start":1.0, "factor": 2.0, "count": 5, "infinity": true}" "start" 表示数据起始点,"factor" 表示按指数递增的因子,"count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf)作为区间起点和终点, 生成区间为[-inf, 1.0, 2.0, 4.0, 8.0, 16.0, +inf]。 @@ -918,7 +918,7 @@ SELECT MAX(field_name) FROM { tb_name | stb_name } [WHERE clause]; **返回数据类型**:同应用的字段。 -**适用数据类型**:数值类型,时间戳类型。 +**适用数据类型**:数值类型。 **适用于**:表和超级表。 @@ -933,7 +933,7 @@ SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause]; **返回数据类型**:同应用的字段。 -**适用数据类型**:数值类型,时间戳类型。 +**适用数据类型**:数值类型。 **适用于**:表和超级表。 @@ -969,7 +969,7 @@ SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause] **适用于**:表和超级表。 -**使用说明**: +**使用说明**: - 不能参与表达式计算;该函数可以应用在普通表和超级表上; - 使用在超级表上的时候,需要搭配 PARTITION by tbname 使用,将结果强制规约到单个时间线。 @@ -1047,10 +1047,10 @@ SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause] **适用于**:表和超级表。 -**使用说明**: - +**使用说明**: + - 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。 -- 只能与聚合(Aggregation)函数一起使用。 该函数可以应用在普通表和超级表上。 +- 只能与聚合(Aggregation)函数一起使用。 该函数可以应用在普通表和超级表上。 - 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用,将结果强制规约到单个时间线。 @@ -1068,8 +1068,8 @@ SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHER **适用于**:表和超级表。 -**使用说明**: - +**使用说明**: + - DERIVATIVE 函数可以在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname)。 - 可以与选择相关联的列一起使用。 例如: select \_rowts, DERIVATIVE() from。 @@ -1087,7 +1087,7 @@ SELECT {DIFF(field_name, ignore_negative) | DIFF(field_name)} FROM tb_name [WHER **适用于**:表和超级表。 -**使用说明**: +**使用说明**: - 输出结果行数是范围内总行数减一,第一行没有结果输出。 - 可以与选择相关联的列一起使用。 例如: select \_rowts, DIFF() from。 @@ -1124,9 +1124,9 @@ SELECT MAVG(field_name, K) FROM { tb_name | stb_name } [WHERE clause] **适用于**:表和超级表。 -**使用说明**: - -- 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1); +**使用说明**: + +- 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1); - 只能与普通列,选择(Selection)、投影(Projection)函数一起使用,不能与聚合(Aggregation)函数一起使用; - 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用,将结果强制规约到单个时间线。 From 65ee59fb90a6c267fffed149d68621e849041796 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Wed, 14 Sep 2022 14:01:08 +0800 Subject: [PATCH 19/50] docs: update arch --- docs/zh/21-tdinternal/01-arch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/21-tdinternal/01-arch.md b/docs/zh/21-tdinternal/01-arch.md index 704524fd21..b128b9d438 100644 --- a/docs/zh/21-tdinternal/01-arch.md +++ b/docs/zh/21-tdinternal/01-arch.md @@ -26,7 +26,7 @@ TDengine 分布式架构的逻辑结构图如下: **管理节点(mnode):** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中 M)。同时,管理节点也负责元数据(包括用户、数据库、超级表等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过 3 个)mnode,它们自动构建成为一个虚拟管理节点组(图中 M1,M2,M3)。mnode 支持多副本,采用 RAFT 一致性协议,保证系统的高可用与高可靠,任何数据更新操作只能在 Leader 上进行。mnode 集群的第一个节点在集群部署时自动完成,其他节点的创建与删除由用户通过 SQL 命令完成。每个 dnode 上至多有一个 mnode,由所属的数据节点的 EP 来唯一标识。每个 dnode 通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的 EP。 -**弹性计算节点(qnode):** 一个虚拟的逻辑单元,运行查询计算任务,也包括基于系统表来实现的 show 命令(图中 Q)。集群中可配置多个 qnode,在整个集群内部共享使用(图中 Q1,Q2,Q3)。qnode 不与具体的 DB 绑定,即一个 qnode 可以同时执行多个 DB 的查询任务。每个 dnode 上至多有一个 qnode,由所属的数据节点的 EP 来唯一标识。客户端通过与 mnode 交互,获取可用的 qnode 列表,当没有可用的 qnode 时,计算任务在 vnode 中执行。 +**计算节点(qnode):** 一个虚拟的逻辑单元,运行查询计算任务,也包括基于系统表来实现的 show 命令(图中 Q)。集群中可配置多个 qnode,在整个集群内部共享使用(图中 Q1,Q2,Q3)。qnode 不与具体的 DB 绑定,即一个 qnode 可以同时执行多个 DB 的查询任务。每个 dnode 上至多有一个 qnode,由所属的数据节点的 EP 来唯一标识。客户端通过与 mnode 交互,获取可用的 qnode 列表,当没有可用的 qnode 时,计算任务在 vnode 中执行。当一个查询执行时,依赖执行计划,调度器会安排一个或多个 qnode 来一起执行。qnode 能从 vnode 获取数据,也可以将自己的计算结果发给其他 qnode 做进一步的处理。通过引入独立的计算节点,TDengine 实现了存储和计算分离。 **流计算节点(snode):** 一个虚拟的逻辑单元,只运行流计算任务(图中 S)。集群中可配置多个 snode,在整个集群内部共享使用(图中 S1,S2,S3)。snode 不与具体的 stream 绑定,即一个 snode 可以同时执行多个 stream 的计算任务。每个 dnode 上至多有一个 snode,由所属的数据节点的 EP 来唯一标识。由 mnode 调度可用的 snode 完成流计算任务,当没有可用的 snode 时,流计算任务在 vnode 中执行。 From 63f02c5103cf4559ff8b9facc5c0521a6d516498 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 14 Sep 2022 14:26:21 +0800 Subject: [PATCH 20/50] fix: fix free meta rsp issue --- source/common/src/tmsg.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c index f96462945f..46e29fc07b 100644 --- a/source/common/src/tmsg.c +++ b/source/common/src/tmsg.c @@ -3344,7 +3344,13 @@ int32_t tDeserializeSSTbHbRsp(void *buf, int32_t bufLen, SSTbHbRsp *pRsp) { return 0; } -void tFreeSTableMetaRsp(void *pRsp) { taosMemoryFreeClear(((STableMetaRsp *)pRsp)->pSchemas); } +void tFreeSTableMetaRsp(void *pRsp) { + if (NULL == pRsp) { + return; + } + + taosMemoryFreeClear(((STableMetaRsp *)pRsp)->pSchemas); +} void tFreeSTableIndexRsp(void *info) { if (NULL == info) { From 2c2d13d92839c362e0f0d959dcaa9dd6040cad3b Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Wed, 14 Sep 2022 14:38:18 +0800 Subject: [PATCH 21/50] fix: detech taosadapter exist when make install (#16827) --- packaging/tools/install.sh | 20 ++++++++++++++++---- packaging/tools/make_install.sh | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/packaging/tools/install.sh b/packaging/tools/install.sh index f2f72acafa..5088e9bdac 100755 --- a/packaging/tools/install.sh +++ b/packaging/tools/install.sh @@ -840,14 +840,20 @@ function updateProduct() { echo echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${cfg_install_dir}/${configFile}" - echo -e "${GREEN_DARK}To configure Adapter (if has) ${NC}: edit ${cfg_install_dir}/${adapterName}.toml" + [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start Adapter (if has)${NC}: ${adapterName} &${NC}" echo -e "${GREEN_DARK}To start ${productName} ${NC}: ./${serverName}${NC}" + [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi if [ ${openresty_work} = 'true' ]; then @@ -926,14 +932,20 @@ function installProduct() { # Ask if to start the service echo echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${cfg_install_dir}/${configFile}" - echo -e "${GREEN_DARK}To configure ${adapterName} (if has) ${NC}: edit ${cfg_install_dir}/${adapterName}.toml" + [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start Adapter (if has)${NC}: ${adapterName} &${NC}" echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" + [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi if [ ! -z "$firstEp" ]; then diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh index a6dceeeaad..d1e7a222cc 100755 --- a/packaging/tools/make_install.sh +++ b/packaging/tools/make_install.sh @@ -609,14 +609,20 @@ function update_TDengine() { echo echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${configDir}/${configFile}" - echo -e "${GREEN_DARK}To configure Taos Adapter (if has) ${NC}: edit ${configDir}/taosadapter.toml" + [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adatper ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start Taos Adapter (if has)${NC}: taosadapter &${NC}" echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" + [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi echo -e "${GREEN_DARK}To access ${productName} ${NC}: use ${GREEN_UNDERLINE}${clientName}${NC} in shell${NC}" @@ -649,14 +655,20 @@ function install_TDengine() { echo -e "\033[44;32;1m${productName} is installed successfully!${NC}" echo echo -e "${GREEN_DARK}To configure ${productName} ${NC}: edit ${configDir}/${configFile}" - echo -e "${GREEN_DARK}To configure taosadapter (if has) ${NC}: edit ${configDir}/taosadapter.toml" + [ -f ${configDir}/taosadapter.toml ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To configure Taos Adapter ${NC}: edit ${configDir}/taosadapter.toml" if ((${service_mod} == 0)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}systemctl start ${serverName}${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}systemctl start taosadapter ${NC}" elif ((${service_mod} == 1)); then echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${csudo}service ${serverName} start${NC}" + [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start Taos Adapter (if has)${NC}: taosadapter &${NC}" echo -e "${GREEN_DARK}To start ${productName} ${NC}: ./${serverName}${NC}" + [ -f ${installDir}/bin/taosadapter ] && \ + echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi echo -e "${GREEN_DARK}To access ${productName} ${NC}: use ${GREEN_UNDERLINE}${clientName}${NC} in shell${NC}" From 6e561a6c78954ee1dfc1c78cab98140fd64ba510 Mon Sep 17 00:00:00 2001 From: yihaoDeng Date: Wed, 14 Sep 2022 14:46:14 +0800 Subject: [PATCH 22/50] fix: fix mem leak --- source/client/src/clientImpl.c | 3 +-- source/libs/index/src/indexTfile.c | 4 ---- source/libs/scheduler/src/schTask.c | 2 ++ 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c index e7b34ab783..70d7a49208 100644 --- a/source/client/src/clientImpl.c +++ b/source/client/src/clientImpl.c @@ -1369,7 +1369,7 @@ int32_t doProcessMsgFromServer(void* param) { updateTargetEpSet(pSendInfo, pTscObj, pMsg, pEpSet); SDataBuf buf = { - .msgType = pMsg->msgType, .len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle, .pEpSet = NULL}; + .msgType = pMsg->msgType, .len = pMsg->contLen, .pData = NULL, .handle = pMsg->info.handle, .pEpSet = pEpSet}; if (pMsg->contLen > 0) { buf.pData = taosMemoryCalloc(1, pMsg->contLen); @@ -1385,7 +1385,6 @@ int32_t doProcessMsgFromServer(void* param) { rpcFreeCont(pMsg->pCont); destroySendMsgInfo(pSendInfo); - taosMemoryFree(arg->pEpset); taosMemoryFree(arg); return TSDB_CODE_SUCCESS; } diff --git a/source/libs/index/src/indexTfile.c b/source/libs/index/src/indexTfile.c index c3be0ea6f5..1fc631e9f3 100644 --- a/source/libs/index/src/indexTfile.c +++ b/source/libs/index/src/indexTfile.c @@ -323,10 +323,6 @@ static int32_t tfSearchCompareFunc(void* reader, SIndexTerm* tem, SIdxTRslt* tr, while ((rt = stmStNextWith(st, NULL)) != NULL) { FstSlice* s = &rt->data; char* ch = (char*)fstSliceData(s, NULL); - // if (0 != strncmp(ch, tem->colName, tem->nColName)) { - // swsResultDestroy(rt); - // break; - //} TExeCond cond = cmpFn(ch, p, tem->colType); if (MATCH == cond) { diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index c5f161b66a..ee60d02ba2 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -430,12 +430,14 @@ int32_t schHandleRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32 code = schDoTaskRedirect(pJob, pTask, pData, rspCode); taosMemoryFree(pData->pData); + taosMemoryFree(pData->pEpSet); SCH_RET(code); _return: taosMemoryFree(pData->pData); + taosMemoryFree(pData->pEpSet); SCH_RET(schProcessOnTaskFailure(pJob, pTask, code)); } From 417571140f9b71b1f623099bbf528a8a940d9069 Mon Sep 17 00:00:00 2001 From: Pan YANG Date: Wed, 14 Sep 2022 15:00:54 +0800 Subject: [PATCH 23/50] docs: fix escape of backtick --- docs/zh/12-taos-sql/20-keywords.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/12-taos-sql/20-keywords.md b/docs/zh/12-taos-sql/20-keywords.md index ee36dc44f0..57a45b0a00 100644 --- a/docs/zh/12-taos-sql/20-keywords.md +++ b/docs/zh/12-taos-sql/20-keywords.md @@ -6,7 +6,7 @@ description: TDengine 保留关键字的详细列表 ## 保留关键字 -目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写如果需要用作库名、表名、STable 名、数据列名及标签列名等,需要使用符合``将关键字括起来使用,例如`ADD`。 +目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写如果需要用作库名、表名、STable 名、数据列名及标签列名等,需要使用符号 `` ` `` 将关键字括起来使用,例如 \`ADD\`。 关键字列表如下: ### A From 64226e5e55131c39ae987f9a4553b03c8f2329d8 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 14 Sep 2022 15:01:14 +0800 Subject: [PATCH 24/50] fix error code number --- include/util/taoserror.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 0058b03b30..086de593d0 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -577,7 +577,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_FUNC_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2802) #define TSDB_CODE_FUNC_FUNTION_PARA_VALUE TAOS_DEF_ERROR_CODE(0, 0x2803) #define TSDB_CODE_FUNC_NOT_BUILTIN_FUNTION TAOS_DEF_ERROR_CODE(0, 0x2804) -#define TSDB_CODE_FUNC_DUP_TIMESTAMP TAOS_DEF_ERROR_CODE(0, 0x012B) +#define TSDB_CODE_FUNC_DUP_TIMESTAMP TAOS_DEF_ERROR_CODE(0, 0x2805) //udf #define TSDB_CODE_UDF_STOPPING TAOS_DEF_ERROR_CODE(0, 0x2901) From 43bdaa6c1906dd660f951c5d1ad30079958a6fab Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 14 Sep 2022 16:11:26 +0800 Subject: [PATCH 25/50] fix: fix invalid free issue --- source/client/src/clientRawBlockWrite.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c index 6e9711f57b..c135965f07 100644 --- a/source/client/src/clientRawBlockWrite.c +++ b/source/client/src/clientRawBlockWrite.c @@ -701,12 +701,6 @@ typedef struct SVgroupCreateTableBatch { static void destroyCreateTbReqBatch(void* data) { SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*)data; - size_t size = taosArrayGetSize(pTbBatch->req.pArray); - for (int32_t i = 0; i < size; ++i) { - SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); - tdDestroySVCreateTbReq(pTableReq); - } - taosArrayDestroy(pTbBatch->req.pArray); } From 4c6a8bbc95f0e76199dd0226118a3f25bde58e12 Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Wed, 14 Sep 2022 16:50:42 +0800 Subject: [PATCH 26/50] feat(stream): stream state support tuple --- include/common/tcommon.h | 33 +++++- include/libs/function/function.h | 145 ++++++++++++------------ include/libs/stream/streamState.h | 78 +++++++++++++ include/libs/stream/tstream.h | 42 +------ source/libs/function/CMakeLists.txt | 2 +- source/libs/function/src/builtinsimpl.c | 74 +++++++----- source/libs/stream/src/streamState.c | 21 +++- 7 files changed, 251 insertions(+), 144 deletions(-) create mode 100644 include/libs/stream/streamState.h diff --git a/include/common/tcommon.h b/include/common/tcommon.h index 37db574d98..ba4baa0130 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -45,8 +45,8 @@ enum { // clang-format on typedef struct { - TSKEY ts; uint64_t groupId; + TSKEY ts; } SWinKey; static inline int SWinKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { @@ -68,6 +68,37 @@ static inline int SWinKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, i return 0; } +typedef struct { + uint64_t groupId; + TSKEY ts; + int32_t exprIdx; +} STupleKey; + +static inline int STupleKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { + STupleKey* pTuple1 = (STupleKey*)pKey1; + STupleKey* pTuple2 = (STupleKey*)pKey2; + + if (pTuple1->groupId > pTuple2->groupId) { + return 1; + } else if (pTuple1->groupId < pTuple2->groupId) { + return -1; + } + + if (pTuple1->ts > pTuple2->ts) { + return 1; + } else if (pTuple1->ts < pTuple2->ts) { + return -1; + } + + if (pTuple1->exprIdx > pTuple2->exprIdx) { + return 1; + } else if (pTuple1->exprIdx < pTuple2->exprIdx) { + return -1; + } + + return 0; +} + enum { TMQ_MSG_TYPE__DUMMY = 0, TMQ_MSG_TYPE__POLL_RSP, diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 3f26eee86a..65ddc180d6 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -34,66 +34,69 @@ typedef struct SFuncExecEnv { int32_t calcMemSize; } SFuncExecEnv; -typedef bool (*FExecGetEnv)(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv); -typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo); +typedef bool (*FExecGetEnv)(struct SFunctionNode *pFunc, SFuncExecEnv *pEnv); +typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo *pResultCellInfo); typedef int32_t (*FExecProcess)(struct SqlFunctionCtx *pCtx); -typedef int32_t (*FExecFinalize)(struct SqlFunctionCtx *pCtx, SSDataBlock* pBlock); +typedef int32_t (*FExecFinalize)(struct SqlFunctionCtx *pCtx, SSDataBlock *pBlock); typedef int32_t (*FScalarExecProcess)(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput); typedef int32_t (*FExecCombine)(struct SqlFunctionCtx *pDestCtx, struct SqlFunctionCtx *pSourceCtx); typedef struct SScalarFuncExecFuncs { - FExecGetEnv getEnv; + FExecGetEnv getEnv; FScalarExecProcess process; } SScalarFuncExecFuncs; typedef struct SFuncExecFuncs { - FExecGetEnv getEnv; - FExecInit init; - FExecProcess process; + FExecGetEnv getEnv; + FExecInit init; + FExecProcess process; FExecFinalize finalize; - FExecCombine combine; + FExecCombine combine; } SFuncExecFuncs; -#define MAX_INTERVAL_TIME_WINDOW 1000000 // maximum allowed time windows in final results +#define MAX_INTERVAL_TIME_WINDOW 1000000 // maximum allowed time windows in final results #define TOP_BOTTOM_QUERY_LIMIT 100 #define FUNCTIONS_NAME_MAX_LENGTH 16 typedef struct SResultRowEntryInfo { - bool initialized:1; // output buffer has been initialized - bool complete:1; // query has completed - uint8_t isNullRes:6; // the result is null - uint16_t numOfRes; // num of output result in current buffer. NOT NULL RESULT + bool initialized : 1; // output buffer has been initialized + bool complete : 1; // query has completed + uint8_t isNullRes : 6; // the result is null + uint16_t numOfRes; // num of output result in current buffer. NOT NULL RESULT } SResultRowEntryInfo; // determine the real data need to calculated the result enum { - BLK_DATA_NOT_LOAD = 0x0, - BLK_DATA_SMA_LOAD = 0x1, + BLK_DATA_NOT_LOAD = 0x0, + BLK_DATA_SMA_LOAD = 0x1, BLK_DATA_DATA_LOAD = 0x3, - BLK_DATA_FILTEROUT = 0x4, // discard current data block since it is not qualified for filter + BLK_DATA_FILTEROUT = 0x4, // discard current data block since it is not qualified for filter }; enum { - MAIN_SCAN = 0x0u, - REVERSE_SCAN = 0x1u, // todo remove it - REPEAT_SCAN = 0x2u, //repeat scan belongs to the master scan - MERGE_STAGE = 0x20u, + MAIN_SCAN = 0x0u, + REVERSE_SCAN = 0x1u, // todo remove it + REPEAT_SCAN = 0x2u, // repeat scan belongs to the master scan + MERGE_STAGE = 0x20u, }; typedef struct SPoint1 { - int64_t key; - union{double val; char* ptr;}; + int64_t key; + union { + double val; + char *ptr; + }; } SPoint1; struct SqlFunctionCtx; struct SResultRowEntryInfo; -//for selectivity query, the corresponding tag value is assigned if the data is qualified +// for selectivity query, the corresponding tag value is assigned if the data is qualified typedef struct SSubsidiaryResInfo { - int16_t num; - int32_t rowLen; - char* buf; // serialize data buffer + int16_t num; + int32_t rowLen; + char *buf; // serialize data buffer struct SqlFunctionCtx **pCtx; } SSubsidiaryResInfo; @@ -106,69 +109,70 @@ typedef struct SResultDataInfo { } SResultDataInfo; #define GET_RES_INFO(ctx) ((ctx)->resultInfo) -#define GET_ROWCELL_INTERBUF(_c) ((void*) ((char*)(_c) + sizeof(SResultRowEntryInfo))) +#define GET_ROWCELL_INTERBUF(_c) ((void *)((char *)(_c) + sizeof(SResultRowEntryInfo))) typedef struct SInputColumnInfoData { - int32_t totalRows; // total rows in current columnar data - int32_t startRowIndex; // handle started row index - int32_t numOfRows; // the number of rows needs to be handled - int32_t numOfInputCols; // PTS is not included - bool colDataAggIsSet;// if agg is set or not - SColumnInfoData *pPTS; // primary timestamp column + int32_t totalRows; // total rows in current columnar data + int32_t startRowIndex; // handle started row index + int32_t numOfRows; // the number of rows needs to be handled + int32_t numOfInputCols; // PTS is not included + bool colDataAggIsSet; // if agg is set or not + SColumnInfoData *pPTS; // primary timestamp column SColumnInfoData **pData; SColumnDataAgg **pColumnDataAgg; - uint64_t uid; // table uid, used to set the tag value when building the final query result for selectivity functions. + uint64_t uid; // table uid, used to set the tag value when building the final query result for selectivity functions. } SInputColumnInfoData; typedef struct SSerializeDataHandle { - struct SDiskbasedBuf* pBuf; + struct SDiskbasedBuf *pBuf; int32_t currentPage; + void *pState; } SSerializeDataHandle; // sql function runtime context typedef struct SqlFunctionCtx { - SInputColumnInfoData input; - SResultDataInfo resDataInfo; - uint32_t order; // data block scanner order: asc|desc - uint8_t scanFlag; // record current running step, default: 0 - int16_t functionId; // function id - char *pOutput; // final result output buffer, point to sdata->data - int32_t numOfParams; - SFunctParam *param; // input parameter, e.g., top(k, 20), the number of results for top query is kept in param - SColumnInfoData *pTsOutput; // corresponding output buffer for timestamp of each result, e.g., top/bottom*/ - int32_t offset; - struct SResultRowEntryInfo *resultInfo; - SSubsidiaryResInfo subsidiaries; - SPoint1 start; - SPoint1 end; - SFuncExecFuncs fpSet; - SScalarFuncExecFuncs sfp; - struct SExprInfo *pExpr; - struct SSDataBlock *pSrcBlock; - struct SSDataBlock *pDstBlock; // used by indefinite rows function to set selectivity - SSerializeDataHandle saveHandle; - bool isStream; + SInputColumnInfoData input; + SResultDataInfo resDataInfo; + uint32_t order; // data block scanner order: asc|desc + uint8_t scanFlag; // record current running step, default: 0 + int16_t functionId; // function id + char *pOutput; // final result output buffer, point to sdata->data + int32_t numOfParams; + SFunctParam *param; // input parameter, e.g., top(k, 20), the number of results for top query is kept in param + SColumnInfoData *pTsOutput; // corresponding output buffer for timestamp of each result, e.g., top/bottom*/ + int32_t offset; + struct SResultRowEntryInfo *resultInfo; + SSubsidiaryResInfo subsidiaries; + SPoint1 start; + SPoint1 end; + SFuncExecFuncs fpSet; + SScalarFuncExecFuncs sfp; + struct SExprInfo *pExpr; + struct SSDataBlock *pSrcBlock; + struct SSDataBlock *pDstBlock; // used by indefinite rows function to set selectivity + SSerializeDataHandle saveHandle; + bool isStream; - char udfName[TSDB_FUNC_NAME_LEN]; + char udfName[TSDB_FUNC_NAME_LEN]; } SqlFunctionCtx; enum { - TEXPR_BINARYEXPR_NODE= 0x1, + TEXPR_BINARYEXPR_NODE = 0x1, TEXPR_UNARYEXPR_NODE = 0x2, }; typedef struct tExprNode { int32_t nodeType; union { - struct {// function node - char functionName[FUNCTIONS_NAME_MAX_LENGTH]; // todo refactor - int32_t functionId; - int32_t num; - struct SFunctionNode *pFunctNode; + struct { // function node + char functionName[FUNCTIONS_NAME_MAX_LENGTH]; // todo refactor + int32_t functionId; + int32_t num; + struct SFunctionNode *pFunctNode; } _function; struct { - struct SNode* pRootNode; + struct SNode *pRootNode; } _optrRoot; }; } tExprNode; @@ -182,17 +186,18 @@ struct SScalarParam { int32_t numOfRows; }; -void cleanupResultRowEntry(struct SResultRowEntryInfo* pCell); -int32_t getNumOfResult(SqlFunctionCtx* pCtx, int32_t num, SSDataBlock* pResBlock); -bool isRowEntryCompleted(struct SResultRowEntryInfo* pEntry); -bool isRowEntryInitialized(struct SResultRowEntryInfo* pEntry); +void cleanupResultRowEntry(struct SResultRowEntryInfo *pCell); +int32_t getNumOfResult(SqlFunctionCtx *pCtx, int32_t num, SSDataBlock *pResBlock); +bool isRowEntryCompleted(struct SResultRowEntryInfo *pEntry); +bool isRowEntryInitialized(struct SResultRowEntryInfo *pEntry); typedef struct SPoint { int64_t key; - void * val; + void *val; } SPoint; -int32_t taosGetLinearInterpolationVal(SPoint* point, int32_t outputType, SPoint* point1, SPoint* point2, int32_t inputType); +int32_t taosGetLinearInterpolationVal(SPoint *point, int32_t outputType, SPoint *point1, SPoint *point2, + int32_t inputType); /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // udf api diff --git a/include/libs/stream/streamState.h b/include/libs/stream/streamState.h new file mode 100644 index 0000000000..df19544396 --- /dev/null +++ b/include/libs/stream/streamState.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * 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 . + */ + +#include "tdatablock.h" +#include "tdbInt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _STREAM_STATE_H_ +#define _STREAM_STATE_H_ + +typedef struct SStreamTask SStreamTask; + +// incremental state storage +typedef struct { + SStreamTask* pOwner; + TDB* db; + TTB* pStateDb; + TTB* pFuncStateDb; + TXN txn; +} SStreamState; + +SStreamState* streamStateOpen(char* path, SStreamTask* pTask); +void streamStateClose(SStreamState* pState); +int32_t streamStateBegin(SStreamState* pState); +int32_t streamStateCommit(SStreamState* pState); +int32_t streamStateAbort(SStreamState* pState); + +typedef struct { + TBC* pCur; +} SStreamStateCur; + +#if 1 +int32_t streamStateFuncPut(SStreamState* pState, const STupleKey* key, const void* value, int32_t vLen); +int32_t streamStateFuncGet(SStreamState* pState, const STupleKey* key, void** pVal, int32_t* pVLen); +int32_t streamStateFuncDel(SStreamState* pState, const STupleKey* key); + +int32_t streamStatePut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen); +int32_t streamStateGet(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen); +int32_t streamStateDel(SStreamState* pState, const SWinKey* key); +int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen); +int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal); +void streamFreeVal(void* val); + +SStreamStateCur* streamStateGetCur(SStreamState* pState, const SWinKey* key); +SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key); +SStreamStateCur* streamStateSeekKeyPrev(SStreamState* pState, const SWinKey* key); +void streamStateFreeCur(SStreamStateCur* pCur); + +int32_t streamStateGetKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen); + +int32_t streamStateSeekFirst(SStreamState* pState, SStreamStateCur* pCur); +int32_t streamStateSeekLast(SStreamState* pState, SStreamStateCur* pCur); + +int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur); +int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef _STREAM_STATE_H_ */ diff --git a/include/libs/stream/tstream.h b/include/libs/stream/tstream.h index afd8de6b1c..554d66d621 100644 --- a/include/libs/stream/tstream.h +++ b/include/libs/stream/tstream.h @@ -16,6 +16,7 @@ #include "executor.h" #include "os.h" #include "query.h" +#include "streamState.h" #include "tdatablock.h" #include "tdbInt.h" #include "tmsg.h" @@ -263,14 +264,6 @@ typedef struct { SArray* checkpointVer; } SStreamRecoveringState; -// incremental state storage -typedef struct { - SStreamTask* pOwner; - TDB* db; - TTB* pStateDb; - TXN txn; -} SStreamState; - typedef struct SStreamTask { int64_t streamId; int32_t taskId; @@ -540,39 +533,6 @@ int32_t streamMetaCommit(SStreamMeta* pMeta); int32_t streamMetaRollBack(SStreamMeta* pMeta); int32_t streamLoadTasks(SStreamMeta* pMeta); -SStreamState* streamStateOpen(char* path, SStreamTask* pTask); -void streamStateClose(SStreamState* pState); -int32_t streamStateBegin(SStreamState* pState); -int32_t streamStateCommit(SStreamState* pState); -int32_t streamStateAbort(SStreamState* pState); - -typedef struct { - TBC* pCur; -} SStreamStateCur; - -#if 1 -int32_t streamStatePut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen); -int32_t streamStateGet(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen); -int32_t streamStateDel(SStreamState* pState, const SWinKey* key); -int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void** pVal, int32_t* pVLen); -int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal); -void streamFreeVal(void* val); - -SStreamStateCur* streamStateGetCur(SStreamState* pState, const SWinKey* key); -SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key); -SStreamStateCur* streamStateSeekKeyPrev(SStreamState* pState, const SWinKey* key); -void streamStateFreeCur(SStreamStateCur* pCur); - -int32_t streamStateGetKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen); - -int32_t streamStateSeekFirst(SStreamState* pState, SStreamStateCur* pCur); -int32_t streamStateSeekLast(SStreamState* pState, SStreamStateCur* pCur); - -int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur); -int32_t streamStateCurPrev(SStreamState* pState, SStreamStateCur* pCur); - -#endif - #ifdef __cplusplus } #endif diff --git a/source/libs/function/CMakeLists.txt b/source/libs/function/CMakeLists.txt index ea401e56e5..dd048a047a 100644 --- a/source/libs/function/CMakeLists.txt +++ b/source/libs/function/CMakeLists.txt @@ -14,7 +14,7 @@ target_include_directories( target_link_libraries( function - PRIVATE os util common nodes scalar qcom transport + PRIVATE os util common nodes scalar qcom transport stream PUBLIC uv_a ) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 0d7fd1a6da..411c898657 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -18,6 +18,7 @@ #include "function.h" #include "query.h" #include "querynodes.h" +#include "streamState.h" #include "tcompare.h" #include "tdatablock.h" #include "tdigest.h" @@ -56,8 +57,13 @@ typedef struct SAvgRes { } SAvgRes; typedef struct STuplePos { - int32_t pageId; - int32_t offset; + union { + struct { + int32_t pageId; + int32_t offset; + }; + STupleKey streamTupleKey; + }; } STuplePos; typedef struct SMinmaxResInfo { @@ -1146,7 +1152,8 @@ bool getMinmaxFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { return true; } -static STuplePos saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock); +static STuplePos saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, + const STupleKey* pKey); static int32_t updateTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, STuplePos* pPos); static const char* loadTupleData(SqlFunctionCtx* pCtx, const STuplePos* pPos); @@ -1201,7 +1208,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { pBuf->v = *(int64_t*)tval; if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); - pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } } else { if (IS_SIGNED_NUMERIC_TYPE(type) || IS_TIMESTAMP_TYPE(type)) { @@ -1213,7 +1220,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { *(int64_t*)&pBuf->v = val; if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); - pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } } } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { @@ -1225,7 +1232,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { *(uint64_t*)&pBuf->v = val; if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); - pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } } } else if (type == TSDB_DATA_TYPE_DOUBLE) { @@ -1237,7 +1244,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { *(double*)&pBuf->v = val; if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); - pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } } } else if (type == TSDB_DATA_TYPE_FLOAT) { @@ -1251,7 +1258,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (pCtx->subsidiaries.num > 0) { index = findRowIndex(pInput->startRowIndex, pInput->numOfRows, pCol, tval); - pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } } } @@ -1276,7 +1283,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1307,7 +1314,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1338,7 +1345,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1369,7 +1376,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1402,7 +1409,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1433,7 +1440,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1464,7 +1471,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1495,7 +1502,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1527,7 +1534,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1558,7 +1565,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { if (!pBuf->assign) { *val = pData[i]; if (pCtx->subsidiaries.num > 0) { - pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock); + pBuf->tuplePos = saveTupleData(pCtx, i, pCtx->pSrcBlock, NULL); } pBuf->assign = true; } else { @@ -1581,7 +1588,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { _min_max_over: if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pBuf->nullTupleSaved) { - pBuf->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock); + pBuf->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, NULL); pBuf->nullTupleSaved = true; } return numOfElems; @@ -2758,7 +2765,7 @@ static void firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowInde } if (!pInfo->hasResult) { - pInfo->pos = saveTupleData(pCtx, rowIndex, pSrcBlock); + pInfo->pos = saveTupleData(pCtx, rowIndex, pSrcBlock, NULL); } else { updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos); } @@ -3426,7 +3433,7 @@ int32_t topFunction(SqlFunctionCtx* pCtx) { } if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) { - pRes->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock); + pRes->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, NULL); pRes->nullTupleSaved = true; } return TSDB_CODE_SUCCESS; @@ -3454,7 +3461,7 @@ int32_t bottomFunction(SqlFunctionCtx* pCtx) { } if (numOfElems == 0 && pCtx->subsidiaries.num > 0 && !pRes->nullTupleSaved) { - pRes->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock); + pRes->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, NULL); pRes->nullTupleSaved = true; } @@ -3506,7 +3513,7 @@ void doAddIntoResult(SqlFunctionCtx* pCtx, void* pData, int32_t rowIndex, SSData // save the data of this tuple if (pCtx->subsidiaries.num > 0) { - pItem->tuplePos = saveTupleData(pCtx, rowIndex, pSrcBlock); + pItem->tuplePos = saveTupleData(pCtx, rowIndex, pSrcBlock, NULL); } #ifdef BUF_PAGE_DEBUG qDebug("page_saveTuple i:%d, item:%p,pageId:%d, offset:%d\n", pEntryInfo->numOfRes, pItem, pItem->tuplePos.pageId, @@ -3578,7 +3585,8 @@ void* serializeTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SSubsid return buf; } -static STuplePos doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length) { +static STuplePos doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, + const STupleKey* pKey) { STuplePos p = {0}; if (pHandle->pBuf != NULL) { SFilePage* pPage = NULL; @@ -3604,12 +3612,16 @@ static STuplePos doSaveTupleData(SSerializeDataHandle* pHandle, const void* pBuf releaseBufPage(pHandle->pBuf, pPage); } else { // other tuple save policy + if (streamStateFuncPut(pHandle->pState, pKey, pBuf, length) < 0) { + ASSERT(0); + } + p.streamTupleKey = *pKey; } return p; } -STuplePos saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock) { +STuplePos saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBlock* pSrcBlock, const STupleKey* pKey) { if (pCtx->subsidiaries.rowLen == 0) { int32_t rowLen = 0; for (int32_t j = 0; j < pCtx->subsidiaries.num; ++j) { @@ -3622,7 +3634,7 @@ STuplePos saveTupleData(SqlFunctionCtx* pCtx, int32_t rowIndex, const SSDataBloc } char* buf = serializeTupleData(pSrcBlock, rowIndex, &pCtx->subsidiaries, pCtx->subsidiaries.buf); - return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen); + return doSaveTupleData(&pCtx->saveHandle, buf, pCtx->subsidiaries.rowLen, pKey); } static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf, size_t length, STuplePos* pPos) { @@ -3632,6 +3644,7 @@ static int32_t doUpdateTupleData(SSerializeDataHandle* pHandle, const void* pBuf setBufPageDirty(pPage, true); releaseBufPage(pHandle->pBuf, pPage); } else { + streamStateFuncPut(pHandle->pState, &pPos->streamTupleKey, pBuf, length); } return TSDB_CODE_SUCCESS; @@ -3650,7 +3663,10 @@ static char* doLoadTupleData(SSerializeDataHandle* pHandle, const STuplePos* pPo releaseBufPage(pHandle->pBuf, pPage); return p; } else { - return NULL; + void* value = NULL; + int32_t vLen; + streamStateFuncGet(pHandle->pState, &pPos->streamTupleKey, &value, &vLen); + return (char*)value; } } @@ -4981,7 +4997,7 @@ static void doReservoirSample(SqlFunctionCtx* pCtx, SSampleInfo* pInfo, char* da if (pInfo->numSampled < pInfo->samples) { sampleAssignResult(pInfo, data, pInfo->numSampled); if (pCtx->subsidiaries.num > 0) { - pInfo->tuplePos[pInfo->numSampled] = saveTupleData(pCtx, index, pCtx->pSrcBlock); + pInfo->tuplePos[pInfo->numSampled] = saveTupleData(pCtx, index, pCtx->pSrcBlock, NULL); } pInfo->numSampled++; } else { @@ -5012,7 +5028,7 @@ int32_t sampleFunction(SqlFunctionCtx* pCtx) { } if (pInfo->numSampled == 0 && pCtx->subsidiaries.num > 0 && !pInfo->nullTupleSaved) { - pInfo->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock); + pInfo->nullTuplePos = saveTupleData(pCtx, pInput->startRowIndex, pCtx->pSrcBlock, NULL); pInfo->nullTupleSaved = true; } diff --git a/source/libs/stream/src/streamState.c b/source/libs/stream/src/streamState.c index 5efdbb4679..6cd5132bb9 100644 --- a/source/libs/stream/src/streamState.c +++ b/source/libs/stream/src/streamState.c @@ -35,6 +35,10 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask) { goto _err; } + if (tdbTbOpen("func.state.db", sizeof(STupleKey), -1, STupleKeyCmpr, pState->db, &pState->pFuncStateDb) < 0) { + goto _err; + } + if (streamStateBegin(pState) < 0) { goto _err; } @@ -44,8 +48,9 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask) { return pState; _err: - if (pState->pStateDb) tdbTbClose(pState->pStateDb); - if (pState->db) tdbClose(pState->db); + tdbTbClose(pState->pStateDb); + tdbTbClose(pState->pFuncStateDb); + tdbClose(pState->db); taosMemoryFree(pState); return NULL; } @@ -53,6 +58,7 @@ _err: void streamStateClose(SStreamState* pState) { tdbCommit(pState->db, &pState->txn); tdbTbClose(pState->pStateDb); + tdbTbClose(pState->pFuncStateDb); tdbClose(pState->db); taosMemoryFree(pState); @@ -101,6 +107,17 @@ int32_t streamStateAbort(SStreamState* pState) { return 0; } +int32_t streamStateFuncPut(SStreamState* pState, const STupleKey* key, const void* value, int32_t vLen) { + return tdbTbUpsert(pState->pFuncStateDb, key, sizeof(STupleKey), value, vLen, &pState->txn); +} +int32_t streamStateFuncGet(SStreamState* pState, const STupleKey* key, void** pVal, int32_t* pVLen) { + return tdbTbGet(pState->pFuncStateDb, key, sizeof(STupleKey), pVal, pVLen); +} + +int32_t streamStateFuncDel(SStreamState* pState, const STupleKey* key) { + return tdbTbDelete(pState->pFuncStateDb, key, sizeof(STupleKey), &pState->txn); +} + int32_t streamStatePut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen) { return tdbTbUpsert(pState->pStateDb, key, sizeof(SWinKey), value, vLen, &pState->txn); } From c7f986a656c4ba73e09bec2b338a9c0557a177bc Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Wed, 14 Sep 2022 17:11:50 +0800 Subject: [PATCH 27/50] refactor(tmq): add error code --- include/util/taoserror.h | 1 + source/dnode/mnode/impl/src/mndSubscribe.c | 1 + source/dnode/mnode/impl/src/mndTopic.c | 1 - source/util/src/terror.c | 1 + 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/util/taoserror.h b/include/util/taoserror.h index d16a599811..d3e1416b85 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -285,6 +285,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_MND_TOPIC_SUBSCRIBED TAOS_DEF_ERROR_CODE(0, 0x03EB) #define TSDB_CODE_MND_CGROUP_USED TAOS_DEF_ERROR_CODE(0, 0x03EC) #define TSDB_CODE_MND_TOPIC_MUST_BE_DELETED TAOS_DEF_ERROR_CODE(0, 0x03ED) +#define TSDB_CODE_MND_IN_REBALANCE TAOS_DEF_ERROR_CODE(0, 0x03EF) // mnode-stream #define TSDB_CODE_MND_STREAM_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x03F0) diff --git a/source/dnode/mnode/impl/src/mndSubscribe.c b/source/dnode/mnode/impl/src/mndSubscribe.c index 1452c5ae2f..8a968712e0 100644 --- a/source/dnode/mnode/impl/src/mndSubscribe.c +++ b/source/dnode/mnode/impl/src/mndSubscribe.c @@ -900,6 +900,7 @@ int32_t mndDropSubByTopic(SMnode *pMnode, STrans *pTrans, const char *topicName) // iter all vnode to delete handle if (taosHashGetSize(pSub->consumerHash) != 0) { sdbRelease(pSdb, pSub); + terrno = TSDB_CODE_MND_IN_REBALANCE; return -1; } int32_t sz = taosArrayGetSize(pSub->unassignedVgs); diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c index eb072d013d..7b36966d6c 100644 --- a/source/dnode/mnode/impl/src/mndTopic.c +++ b/source/dnode/mnode/impl/src/mndTopic.c @@ -713,7 +713,6 @@ static int32_t mndProcessDropTopicReq(SRpcMsg *pReq) { mndReleaseTopic(pMnode, pTopic); if (code != 0) { - terrno = code; mError("topic:%s, failed to drop since %s", dropReq.name, terrstr()); return -1; } diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 044cdc86b4..dbe8be6a81 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -288,6 +288,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_MND_CONSUMER_NOT_READY, "Consumer not ready") TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOPIC_SUBSCRIBED, "Topic subscribed cannot be dropped") TAOS_DEFINE_ERROR(TSDB_CODE_MND_TOPIC_MUST_BE_DELETED, "Topic must be dropped first") TAOS_DEFINE_ERROR(TSDB_CODE_MND_CGROUP_USED, "Consumer group being used by some consumer") +TAOS_DEFINE_ERROR(TSDB_CODE_MND_IN_REBALANCE, "Topic being rebalanced") // mnode-stream TAOS_DEFINE_ERROR(TSDB_CODE_MND_STREAM_ALREADY_EXIST, "Stream already exists") From e2586979eb501887432930d53a20d24614bf5410 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Wed, 14 Sep 2022 17:51:21 +0800 Subject: [PATCH 28/50] enh: the delete physical plan increases the timestamp interval of the actual deleted data --- include/libs/nodes/plannodes.h | 4 ++++ include/libs/nodes/querynodes.h | 2 ++ source/libs/nodes/src/nodesCloneFuncs.c | 2 ++ source/libs/nodes/src/nodesCodeFuncs.c | 14 ++++++++++++++ source/libs/nodes/src/nodesMsgFuncs.c | 16 +++++++++++++++- source/libs/nodes/src/nodesUtilFuncs.c | 6 ++++++ source/libs/parser/src/parAstCreater.c | 10 ++++++---- source/libs/parser/src/parTranslater.c | 8 +++++++- source/libs/planner/src/planLogicCreater.c | 16 +++++++++++++++- source/libs/planner/src/planPhysiCreater.c | 12 +++++++++--- 10 files changed, 80 insertions(+), 10 deletions(-) diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index 8aeb86102a..1e86a04775 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -151,6 +151,8 @@ typedef struct SVnodeModifyLogicNode { SArray* pDataBlocks; SVgDataBlocks* pVgDataBlocks; SNode* pAffectedRows; // SColumnNode + SNode* pStartTs; // SColumnNode + SNode* pEndTs; // SColumnNode uint64_t tableId; uint64_t stableId; int8_t tableType; // table type @@ -525,6 +527,8 @@ typedef struct SDataDeleterNode { char tsColName[TSDB_COL_NAME_LEN]; STimeWindow deleteTimeRange; SNode* pAffectedRows; + SNode* pStartTs; + SNode* pEndTs; } SDataDeleterNode; typedef struct SSubplan { diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 3a1eaf289e..e90c994e8f 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -315,6 +315,8 @@ typedef struct SDeleteStmt { SNode* pFromTable; // FROM clause SNode* pWhere; // WHERE clause SNode* pCountFunc; // count the number of rows affected + SNode* pFirstFunc; // the start timestamp when the data was actually deleted + SNode* pLastFunc; // the end timestamp when the data was actually deleted SNode* pTagCond; // pWhere divided into pTagCond and timeRange STimeWindow timeRange; uint8_t precision; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index eb0b604d37..48e21e137f 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -399,6 +399,8 @@ static int32_t logicVnodeModifCopy(const SVnodeModifyLogicNode* pSrc, SVnodeModi COPY_SCALAR_FIELD(modifyType); COPY_SCALAR_FIELD(msgType); CLONE_NODE_FIELD(pAffectedRows); + CLONE_NODE_FIELD(pStartTs); + CLONE_NODE_FIELD(pEndTs); COPY_SCALAR_FIELD(tableId); COPY_SCALAR_FIELD(stableId); COPY_SCALAR_FIELD(tableType); diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index a41462e3fd..afd05eff1d 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -2431,6 +2431,8 @@ static const char* jkDeletePhysiPlanTsColName = "TsColName"; static const char* jkDeletePhysiPlanDeleteTimeRangeStartKey = "DeleteTimeRangeStartKey"; static const char* jkDeletePhysiPlanDeleteTimeRangeEndKey = "DeleteTimeRangeEndKey"; static const char* jkDeletePhysiPlanAffectedRows = "AffectedRows"; +static const char* jkDeletePhysiPlanStartTs = "StartTs"; +static const char* jkDeletePhysiPlanEndTs = "EndTs"; static int32_t physiDeleteNodeToJson(const void* pObj, SJson* pJson) { const SDataDeleterNode* pNode = (const SDataDeleterNode*)pObj; @@ -2457,6 +2459,12 @@ static int32_t physiDeleteNodeToJson(const void* pObj, SJson* pJson) { if (TSDB_CODE_SUCCESS == code) { code = tjsonAddObject(pJson, jkDeletePhysiPlanAffectedRows, nodeToJson, pNode->pAffectedRows); } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkDeletePhysiPlanStartTs, nodeToJson, pNode->pStartTs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tjsonAddObject(pJson, jkDeletePhysiPlanEndTs, nodeToJson, pNode->pEndTs); + } return code; } @@ -2486,6 +2494,12 @@ static int32_t jsonToPhysiDeleteNode(const SJson* pJson, void* pObj) { if (TSDB_CODE_SUCCESS == code) { code = jsonToNodeObject(pJson, jkDeletePhysiPlanAffectedRows, &pNode->pAffectedRows); } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkDeletePhysiPlanStartTs, &pNode->pStartTs); + } + if (TSDB_CODE_SUCCESS == code) { + code = jsonToNodeObject(pJson, jkDeletePhysiPlanEndTs, &pNode->pEndTs); + } return code; } diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c index efe820fee2..202ee6717a 100644 --- a/source/libs/nodes/src/nodesMsgFuncs.c +++ b/source/libs/nodes/src/nodesMsgFuncs.c @@ -2665,7 +2665,9 @@ enum { PHY_DELETER_CODE_TABLE_FNAME, PHY_DELETER_CODE_TS_COL_NAME, PHY_DELETER_CODE_DELETE_TIME_RANGE, - PHY_DELETER_CODE_AFFECTED_ROWS + PHY_DELETER_CODE_AFFECTED_ROWS, + PHY_DELETER_CODE_START_TS, + PHY_DELETER_CODE_END_TS }; static int32_t physiDeleteNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { @@ -2690,6 +2692,12 @@ static int32_t physiDeleteNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { if (TSDB_CODE_SUCCESS == code) { code = tlvEncodeObj(pEncoder, PHY_DELETER_CODE_AFFECTED_ROWS, nodeToMsg, pNode->pAffectedRows); } + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeObj(pEncoder, PHY_DELETER_CODE_START_TS, nodeToMsg, pNode->pStartTs); + } + if (TSDB_CODE_SUCCESS == code) { + code = tlvEncodeObj(pEncoder, PHY_DELETER_CODE_END_TS, nodeToMsg, pNode->pEndTs); + } return code; } @@ -2722,6 +2730,12 @@ static int32_t msgToPhysiDeleteNode(STlvDecoder* pDecoder, void* pObj) { case PHY_DELETER_CODE_AFFECTED_ROWS: code = msgToNodeFromTlv(pTlv, (void**)&pNode->pAffectedRows); break; + case PHY_DELETER_CODE_START_TS: + code = msgToNodeFromTlv(pTlv, (void**)&pNode->pStartTs); + break; + case PHY_DELETER_CODE_END_TS: + code = msgToNodeFromTlv(pTlv, (void**)&pNode->pEndTs); + break; default: break; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 61b2ad954f..805ddb9e42 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -727,6 +727,8 @@ void nodesDestroyNode(SNode* pNode) { nodesDestroyNode(pStmt->pFromTable); nodesDestroyNode(pStmt->pWhere); nodesDestroyNode(pStmt->pCountFunc); + nodesDestroyNode(pStmt->pFirstFunc); + nodesDestroyNode(pStmt->pLastFunc); nodesDestroyNode(pStmt->pTagCond); break; } @@ -791,6 +793,8 @@ void nodesDestroyNode(SNode* pNode) { destroyVgDataBlockArray(pLogicNode->pDataBlocks); // pVgDataBlocks is weak reference nodesDestroyNode(pLogicNode->pAffectedRows); + nodesDestroyNode(pLogicNode->pStartTs); + nodesDestroyNode(pLogicNode->pEndTs); taosMemoryFreeClear(pLogicNode->pVgroupList); nodesDestroyList(pLogicNode->pInsertCols); break; @@ -997,6 +1001,8 @@ void nodesDestroyNode(SNode* pNode) { SDataDeleterNode* pSink = (SDataDeleterNode*)pNode; destroyDataSinkNode((SDataSinkNode*)pSink); nodesDestroyNode(pSink->pAffectedRows); + nodesDestroyNode(pSink->pStartTs); + nodesDestroyNode(pSink->pEndTs); break; } case QUERY_NODE_PHYSICAL_SUBPLAN: { diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index 511ae25810..6f11c653a4 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -1787,10 +1787,10 @@ SNode* createRevokeStmt(SAstCreateContext* pCxt, int64_t privileges, SToken* pDb return (SNode*)pStmt; } -SNode* createCountFuncForDelete(SAstCreateContext* pCxt) { +SNode* createFuncForDelete(SAstCreateContext* pCxt, const char* pFuncName) { SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); CHECK_OUT_OF_MEM(pFunc); - strcpy(pFunc->functionName, "count"); + strcpy(pFunc->functionName, pFuncName); if (TSDB_CODE_SUCCESS != nodesListMakeStrictAppend(&pFunc->pParameterList, createPrimaryKeyCol(pCxt, NULL))) { nodesDestroyNode((SNode*)pFunc); CHECK_OUT_OF_MEM(NULL); @@ -1804,8 +1804,10 @@ SNode* createDeleteStmt(SAstCreateContext* pCxt, SNode* pTable, SNode* pWhere) { CHECK_OUT_OF_MEM(pStmt); pStmt->pFromTable = pTable; pStmt->pWhere = pWhere; - pStmt->pCountFunc = createCountFuncForDelete(pCxt); - if (NULL == pStmt->pCountFunc) { + pStmt->pCountFunc = createFuncForDelete(pCxt, "count"); + pStmt->pFirstFunc = createFuncForDelete(pCxt, "first"); + pStmt->pLastFunc = createFuncForDelete(pCxt, "last"); + if (NULL == pStmt->pCountFunc || NULL == pStmt->pFirstFunc || NULL == pStmt->pLastFunc) { nodesDestroyNode((SNode*)pStmt); CHECK_OUT_OF_MEM(NULL); } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index f1a59ebf51..888d3b6848 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -3347,10 +3347,16 @@ static int32_t translateDelete(STranslateContext* pCxt, SDeleteStmt* pDelete) { if (TSDB_CODE_SUCCESS == code) { code = translateDeleteWhere(pCxt, pDelete); } + pCxt->currClause = SQL_CLAUSE_SELECT; if (TSDB_CODE_SUCCESS == code) { - pCxt->currClause = SQL_CLAUSE_SELECT; code = translateExpr(pCxt, &pDelete->pCountFunc); } + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, &pDelete->pFirstFunc); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, &pDelete->pLastFunc); + } return code; } diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index bf72f52105..fea2be55f9 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -1372,9 +1372,21 @@ static int32_t createDeleteAggLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* pD } int32_t code = nodesListMakeStrictAppend(&pAgg->pAggFuncs, nodesCloneNode(pDelete->pCountFunc)); + if (TSDB_CODE_SUCCESS == code) { + code = nodesListStrictAppend(pAgg->pAggFuncs, nodesCloneNode(pDelete->pFirstFunc)); + } + if (TSDB_CODE_SUCCESS == code) { + code = nodesListStrictAppend(pAgg->pAggFuncs, nodesCloneNode(pDelete->pLastFunc)); + } if (TSDB_CODE_SUCCESS == code) { code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pCountFunc); } + if (TSDB_CODE_SUCCESS == code) { + code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pFirstFunc); + } + if (TSDB_CODE_SUCCESS == code) { + code = rewriteExpr(pAgg->pAggFuncs, &pDelete->pLastFunc); + } // set the output if (TSDB_CODE_SUCCESS == code) { code = createColumnByRewriteExprs(pAgg->pAggFuncs, &pAgg->node.pTargets); @@ -1405,7 +1417,9 @@ static int32_t createVnodeModifLogicNodeByDelete(SLogicPlanContext* pCxt, SDelet strcpy(pModify->tsColName, pRealTable->pMeta->schema->name); pModify->deleteTimeRange = pDelete->timeRange; pModify->pAffectedRows = nodesCloneNode(pDelete->pCountFunc); - if (NULL == pModify->pAffectedRows) { + pModify->pStartTs = nodesCloneNode(pDelete->pFirstFunc); + pModify->pEndTs = nodesCloneNode(pDelete->pLastFunc); + if (NULL == pModify->pAffectedRows || NULL == pModify->pStartTs || NULL == pModify->pEndTs) { nodesDestroyNode((SNode*)pModify); return TSDB_CODE_OUT_OF_MEMORY; } diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index 0cbb833a4d..b0177e61ed 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -1323,9 +1323,9 @@ static int32_t createSortPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren static int32_t createPartitionPhysiNode(SPhysiPlanContext* pCxt, SNodeList* pChildren, SPartitionLogicNode* pPartLogicNode, SPhysiNode** pPhyNode) { - SPartitionPhysiNode* pPart = - (SPartitionPhysiNode*)makePhysiNode(pCxt, (SLogicNode*)pPartLogicNode, - pCxt->pPlanCxt->streamQuery ? QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION : QUERY_NODE_PHYSICAL_PLAN_PARTITION); + SPartitionPhysiNode* pPart = (SPartitionPhysiNode*)makePhysiNode( + pCxt, (SLogicNode*)pPartLogicNode, + pCxt->pPlanCxt->streamQuery ? QUERY_NODE_PHYSICAL_PLAN_STREAM_PARTITION : QUERY_NODE_PHYSICAL_PLAN_PARTITION); if (NULL == pPart) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -1670,6 +1670,12 @@ static int32_t createDataDeleter(SPhysiPlanContext* pCxt, SVnodeModifyLogicNode* int32_t code = setNodeSlotId(pCxt, pRoot->pOutputDataBlockDesc->dataBlockId, -1, pModify->pAffectedRows, &pDeleter->pAffectedRows); + if (TSDB_CODE_SUCCESS == code) { + code = setNodeSlotId(pCxt, pRoot->pOutputDataBlockDesc->dataBlockId, -1, pModify->pStartTs, &pDeleter->pStartTs); + } + if (TSDB_CODE_SUCCESS == code) { + code = setNodeSlotId(pCxt, pRoot->pOutputDataBlockDesc->dataBlockId, -1, pModify->pEndTs, &pDeleter->pEndTs); + } if (TSDB_CODE_SUCCESS == code) { pDeleter->sink.pInputDataBlockDesc = (SDataBlockDescNode*)nodesCloneNode((SNode*)pRoot->pOutputDataBlockDesc); if (NULL == pDeleter->sink.pInputDataBlockDesc) { From 45acc3420bfc337d2af03bd5f6bcd6ec72f4a4b6 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Wed, 14 Sep 2022 18:05:57 +0800 Subject: [PATCH 29/50] more code --- include/common/tdataformat.h | 4 +- source/common/src/tdataformat.c | 104 +++++++++++++++++++++----------- 2 files changed, 70 insertions(+), 38 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index c51eff6a48..159279329b 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -106,14 +106,12 @@ void debugPrintSTag(STag *pTag, const char *tag, int32_t ln); // TODO: remov int32_t parseJsontoTagData(const char *json, SArray *pTagVals, STag **ppTag, void *pMsgBuf); // SColData ================================ +void tColDataDestroy(void *ph); void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); void tColDataClear(SColData *pColData); -void tColDataDestroy(void *ph); int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); void tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); -int32_t tPutColData(uint8_t *p, SColData *pColData); -int32_t tGetColData(uint8_t *p, SColData *pColData); // STRUCT ================================ struct STColumn { diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index ed2d68961f..dd2667b302 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1203,8 +1203,7 @@ static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVa if (code) goto _exit; pColData->aOffset[pColData->nVal] = pColData->nData; - // value - if ((!pColVal->isNone) && (!pColVal->isNull)) { + if (pColVal->value.nData) { code = tRealloc(&pColData->pData, pColData->nData + pColVal->value.nData); if (code) goto _exit; memcpy(pColData->pData + pColData->nData, pColVal->value.pData, pColVal->value.nData); @@ -1240,18 +1239,33 @@ static FORCE_INLINE int32_t tColDataAppendValue1(SColData *pColData, SColVal *pC int32_t code = 0; if (!pColVal->isNone) { - code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + int32_t nBit = BIT1_SIZE(pColData->nVal + 1); + + code = tRealloc(&pColData->pBitMap, nBit); if (code) goto _exit; - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT1(pColData->pBitMap, iVal, 0); - } + memset(pColData->pBitMap, 0, nBit); SET_BIT1(pColData->pBitMap, pColData->nVal, 1); if (pColVal->isNull) { pColData->flag |= HAS_NULL; } else { pColData->flag |= HAS_VALUE; + + if (pColData->nVal) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nOffset = sizeof(int32_t) * pColData->nVal; + code = tRealloc((uint8_t **)(&pColData->aOffset), nOffset); + if (code) goto _exit; + memset(pColData->aOffset, 0, nOffset); + } else { + pColData->nData = tDataTypes[pColData->type].bytes * pColData->nVal; + code = tRealloc(&pColData->pData, pColData->nData); + if (code) goto _exit; + memset(pColData->pData, 0, pColData->nData); + } + } + code = tColDataPutValue(pColData, pColVal); if (code) goto _exit; } @@ -1265,24 +1279,35 @@ static FORCE_INLINE int32_t tColDataAppendValue2(SColData *pColData, SColVal *pC int32_t code = 0; if (!pColVal->isNull) { - code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + int32_t nBit = BIT1_SIZE(pColData->nVal + 1); + code = tRealloc(&pColData->pBitMap, nBit); if (code) goto _exit; if (pColVal->isNone) { pColData->flag |= HAS_NONE; - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT1(pColData->pBitMap, iVal, 1); - } + memset(pColData->pBitMap, 255, nBit); SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else { pColData->flag |= HAS_VALUE; - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT1(pColData->pBitMap, iVal, 0); - } + memset(pColData->pBitMap, 0, nBit); SET_BIT1(pColData->pBitMap, pColData->nVal, 1); + if (pColData->nVal) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nOffset = sizeof(int32_t) * pColData->nVal; + code = tRealloc((uint8_t **)(&pColData->aOffset), nOffset); + if (code) goto _exit; + memset(pColData->aOffset, 0, nOffset); + } else { + pColData->nData = tDataTypes[pColData->type].bytes * pColData->nVal; + code = tRealloc(&pColData->pData, pColData->nData); + if (code) goto _exit; + memset(pColData->pData, 0, pColData->nData); + } + } + code = tColDataPutValue(pColData, pColVal); if (code) goto _exit; } @@ -1320,6 +1345,20 @@ static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pC tFree(pColData->pBitMap); pColData->pBitMap = pBitMap; + if (pColData->nVal) { + if (IS_VAR_DATA_TYPE(pColData->type)) { + int32_t nOffset = sizeof(int32_t) * pColData->nVal; + code = tRealloc((uint8_t **)(&pColData->aOffset), nOffset); + if (code) goto _exit; + memset(pColData->aOffset, 0, nOffset); + } else { + pColData->nData = tDataTypes[pColData->type].bytes * pColData->nVal; + code = tRealloc(&pColData->pData, pColData->nData); + if (code) goto _exit; + memset(pColData->pData, 0, pColData->nData); + } + } + code = tColDataPutValue(pColData, pColVal); if (code) goto _exit; } @@ -1341,6 +1380,9 @@ static FORCE_INLINE int32_t tColDataAppendValue4(SColData *pColData, SColVal *pC SET_BIT1(pColData->pBitMap, iVal, 1); } SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + + code = tColDataPutValue(pColData, &COL_VAL_VALUE(pColData->cid, pColData->type, (SValue){0})); + if (code) goto _exit; } else if (pColVal->isNull) { pColData->flag |= HAS_NULL; @@ -1351,6 +1393,9 @@ static FORCE_INLINE int32_t tColDataAppendValue4(SColData *pColData, SColVal *pC SET_BIT1(pColData->pBitMap, iVal, 1); } SET_BIT1(pColData->pBitMap, pColData->nVal, 0); + + code = tColDataPutValue(pColData, &COL_VAL_VALUE(pColData->cid, pColData->type, (SValue){0})); + if (code) goto _exit; } else { code = tColDataPutValue(pColData, pColVal); if (code) goto _exit; @@ -1385,11 +1430,10 @@ static FORCE_INLINE int32_t tColDataAppendValue5(SColData *pColData, SColVal *pC SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else { SET_BIT1(pColData->pBitMap, pColData->nVal, 1); - - code = tColDataPutValue(pColData, pColVal); - if (code) goto _exit; } } + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; pColData->nVal++; @@ -1421,11 +1465,11 @@ static FORCE_INLINE int32_t tColDataAppendValue6(SColData *pColData, SColVal *pC SET_BIT1(pColData->pBitMap, pColData->nVal, 0); } else { SET_BIT1(pColData->pBitMap, pColData->nVal, 1); - - code = tColDataPutValue(pColData, pColVal); - if (code) goto _exit; } } + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + pColData->nVal++; _exit: @@ -1444,10 +1488,10 @@ static FORCE_INLINE int32_t tColDataAppendValue7(SColData *pColData, SET_BIT2(pColData->pBitMap, pColData->nVal, 1); } else { SET_BIT2(pColData->pBitMap, pColData->nVal, 2); - - code = tColDataPutValue(pColData, pColVal); - if (code) goto _exit; } + code = tColDataPutValue(pColData, pColVal); + if (code) goto _exit; + pColData->nVal++; _exit: @@ -1464,16 +1508,8 @@ static int32_t (*tColDataAppendValueImpl[])(SColData *pColData, SColVal *pColVal tColDataAppendValue7 // HAS_VALUE|HAS_NULL|HAS_NONE }; int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal) { - int32_t code = 0; - - ASSERT(pColData->cid == pColVal->cid); - ASSERT(pColData->type == pColVal->type); - - code = tColDataAppendValueImpl[pColData->flag](pColData, pColVal); - if (code) goto _exit; - -_exit: - return code; + ASSERT(pColData->cid == pColVal->cid && pColData->type == pColVal->type); + return tColDataAppendValueImpl[pColData->flag](pColData, pColVal); } static FORCE_INLINE void tColDataGetValue1(SColData *pColData, int32_t iVal, SColVal *pColVal) { // HAS_NONE @@ -1561,9 +1597,7 @@ static void (*tColDataGetValueImpl[])(SColData *pColData, int32_t iVal, SColVal tColDataGetValue7 // HAS_VALUE | HAS_NULL | HAS_NONE }; void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { - ASSERT(iVal >= 0 && iVal < pColData->nVal); - ASSERT(pColData->flag); - + ASSERT(iVal >= 0 && iVal < pColData->nVal && pColData->flag); tColDataGetValueImpl[pColData->flag](pColData, iVal, pColVal); } From c7efe171775eaf9bee631c22ce9e25ddf8573acf Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 14 Sep 2022 18:08:29 +0800 Subject: [PATCH 30/50] fix: fix task retry and qnode fetch thread num issue --- source/common/src/tglobal.c | 14 ++++++---- source/libs/scheduler/inc/schInt.h | 3 ++- source/libs/scheduler/src/schRemote.c | 2 +- source/libs/scheduler/src/schTask.c | 37 +++++++++++++++++---------- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index c436e4ffd2..ddda8f8c9a 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -63,7 +63,7 @@ int32_t tsNumOfVnodeWriteThreads = 2; int32_t tsNumOfVnodeSyncThreads = 2; int32_t tsNumOfVnodeRsmaThreads = 2; int32_t tsNumOfQnodeQueryThreads = 4; -int32_t tsNumOfQnodeFetchThreads = 4; +int32_t tsNumOfQnodeFetchThreads = 1; int32_t tsNumOfSnodeSharedThreads = 2; int32_t tsNumOfSnodeUniqueThreads = 2; @@ -385,9 +385,9 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { tsNumOfQnodeQueryThreads = TMAX(tsNumOfQnodeQueryThreads, 4); if (cfgAddInt32(pCfg, "numOfQnodeQueryThreads", tsNumOfQnodeQueryThreads, 1, 1024, 0) != 0) return -1; - tsNumOfQnodeFetchThreads = tsNumOfCores / 2; - tsNumOfQnodeFetchThreads = TMAX(tsNumOfQnodeFetchThreads, 4); - if (cfgAddInt32(pCfg, "numOfQnodeFetchThreads", tsNumOfQnodeFetchThreads, 1, 1024, 0) != 0) return -1; +// tsNumOfQnodeFetchThreads = tsNumOfCores / 2; +// tsNumOfQnodeFetchThreads = TMAX(tsNumOfQnodeFetchThreads, 4); +// if (cfgAddInt32(pCfg, "numOfQnodeFetchThreads", tsNumOfQnodeFetchThreads, 1, 1024, 0) != 0) return -1; tsNumOfSnodeSharedThreads = tsNumOfCores / 4; tsNumOfSnodeSharedThreads = TRANGE(tsNumOfSnodeSharedThreads, 2, 4); @@ -527,6 +527,7 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) { pItem->stype = stype; } +/* pItem = cfgGetItem(tsCfg, "numOfQnodeFetchThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { tsNumOfQnodeFetchThreads = numOfCores / 2; @@ -534,6 +535,7 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) { pItem->i32 = tsNumOfQnodeFetchThreads; pItem->stype = stype; } +*/ pItem = cfgGetItem(tsCfg, "numOfSnodeSharedThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { @@ -691,7 +693,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { tsNumOfVnodeSyncThreads = cfgGetItem(pCfg, "numOfVnodeSyncThreads")->i32; tsNumOfVnodeRsmaThreads = cfgGetItem(pCfg, "numOfVnodeRsmaThreads")->i32; tsNumOfQnodeQueryThreads = cfgGetItem(pCfg, "numOfQnodeQueryThreads")->i32; - tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32; +// tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32; tsNumOfSnodeSharedThreads = cfgGetItem(pCfg, "numOfSnodeSharedThreads")->i32; tsNumOfSnodeUniqueThreads = cfgGetItem(pCfg, "numOfSnodeUniqueThreads")->i32; tsRpcQueueMemoryAllowed = cfgGetItem(pCfg, "rpcQueueMemoryAllowed")->i64; @@ -939,8 +941,10 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) { tsNumOfVnodeRsmaThreads = cfgGetItem(pCfg, "numOfVnodeRsmaThreads")->i32; } else if (strcasecmp("numOfQnodeQueryThreads", name) == 0) { tsNumOfQnodeQueryThreads = cfgGetItem(pCfg, "numOfQnodeQueryThreads")->i32; +/* } else if (strcasecmp("numOfQnodeFetchThreads", name) == 0) { tsNumOfQnodeFetchThreads = cfgGetItem(pCfg, "numOfQnodeFetchThreads")->i32; +*/ } else if (strcasecmp("numOfSnodeSharedThreads", name) == 0) { tsNumOfSnodeSharedThreads = cfgGetItem(pCfg, "numOfSnodeSharedThreads")->i32; } else if (strcasecmp("numOfSnodeUniqueThreads", name) == 0) { diff --git a/source/libs/scheduler/inc/schInt.h b/source/libs/scheduler/inc/schInt.h index 957fd46ba5..7fea286732 100644 --- a/source/libs/scheduler/inc/schInt.h +++ b/source/libs/scheduler/inc/schInt.h @@ -283,8 +283,9 @@ typedef struct SSchJob { } SSchJob; typedef struct SSchTaskCtx { - int64_t jobRid; + int64_t jobRid; SSchTask *pTask; + bool asyncLaunch; } SSchTaskCtx; extern SSchedulerMgmt schMgmt; diff --git a/source/libs/scheduler/src/schRemote.c b/source/libs/scheduler/src/schRemote.c index 5a64aaaebb..275fbb8016 100644 --- a/source/libs/scheduler/src/schRemote.c +++ b/source/libs/scheduler/src/schRemote.c @@ -396,7 +396,7 @@ int32_t schHandleCallback(void *param, SDataBuf *pMsg, int32_t rspCode) { tstrerror(rspCode)); SCH_ERR_JRET(schProcessOnCbBegin(&pJob, &pTask, pParam->queryId, pParam->refId, pParam->taskId)); - + code = schHandleResponseMsg(pJob, pTask, pParam->execId, pMsg, rspCode); pMsg->pData = NULL; diff --git a/source/libs/scheduler/src/schTask.c b/source/libs/scheduler/src/schTask.c index 9cab39c301..7ce426e18d 100644 --- a/source/libs/scheduler/src/schTask.c +++ b/source/libs/scheduler/src/schTask.c @@ -138,11 +138,6 @@ int32_t schUpdateTaskExecNode(SSchJob *pJob, SSchTask *pTask, void *handle, int3 return TSDB_CODE_SUCCESS; } - if ((execId != pTask->execId) || pTask->waitRetry) { // ignore it - SCH_TASK_DLOG("handle not updated since execId %d is already not current execId %d, waitRetry %d", execId, pTask->execId, pTask->waitRetry); - return TSDB_CODE_SUCCESS; - } - SSchNodeInfo *nodeInfo = taosHashGet(pTask->execNodes, &execId, sizeof(execId)); if (NULL == nodeInfo) { // ignore it SCH_TASK_DLOG("handle not updated since execId %d already not exist, current execId %d, waitRetry %d", execId, pTask->execId, pTask->waitRetry); @@ -160,11 +155,16 @@ int32_t schUpdateTaskHandle(SSchJob *pJob, SSchTask *pTask, bool dropExecNode, v if (dropExecNode) { SCH_RET(schDropTaskExecNode(pJob, pTask, handle, execId)); } - - SCH_SET_TASK_HANDLE(pTask, handle); - + schUpdateTaskExecNode(pJob, pTask, handle, execId); + if ((execId != pTask->execId) || pTask->waitRetry) { // ignore it + SCH_TASK_DLOG("handle not updated since execId %d is already not current execId %d, waitRetry %d", execId, pTask->execId, pTask->waitRetry); + SCH_ERR_RET(TSDB_CODE_SCH_IGNORE_ERROR); + } + + SCH_SET_TASK_HANDLE(pTask, handle); + return TSDB_CODE_SUCCESS; } @@ -349,7 +349,7 @@ int32_t schDoTaskRedirect(SSchJob *pJob, SSchTask *pTask, SDataBuf *pData, int32 pTask->waitRetry = true; schDropTaskOnExecNode(pJob, pTask); taosHashClear(pTask->execNodes); - SCH_ERR_JRET(schRemoveTaskFromExecList(pJob, pTask)); + schRemoveTaskFromExecList(pJob, pTask); schDeregisterTaskHb(pJob, pTask); atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); taosMemoryFreeClear(pTask->msg); @@ -593,7 +593,7 @@ int32_t schTaskCheckSetRetry(SSchJob *pJob, SSchTask *pTask, int32_t errCode, bo int32_t schHandleTaskRetry(SSchJob *pJob, SSchTask *pTask) { atomic_sub_fetch_32(&pTask->level->taskLaunchedNum, 1); - SCH_ERR_RET(schRemoveTaskFromExecList(pJob, pTask)); + schRemoveTaskFromExecList(pJob, pTask); SCH_SET_TASK_STATUS(pTask, JOB_TASK_STATUS_INIT); if (SCH_TASK_NEED_FLOW_CTRL(pJob, pTask)) { @@ -739,8 +739,7 @@ _return: int32_t schRemoveTaskFromExecList(SSchJob *pJob, SSchTask *pTask) { int32_t code = taosHashRemove(pJob->execTasks, &pTask->taskId, sizeof(pTask->taskId)); if (code) { - SCH_TASK_ELOG("task failed to rm from execTask list, code:%x", code); - SCH_ERR_RET(TSDB_CODE_SCH_INTERNAL_ERROR); + SCH_TASK_WLOG("task already not in execTask list, code:%x", code); } return TSDB_CODE_SUCCESS; @@ -829,6 +828,11 @@ int32_t schLaunchTaskImpl(void *param) { } SSchTask *pTask = pCtx->pTask; + + if (pCtx->asyncLaunch) { + SCH_LOCK_TASK(pTask); + } + int8_t status = 0; int32_t code = 0; @@ -875,8 +879,6 @@ int32_t schLaunchTaskImpl(void *param) { _return: - taosMemoryFree(param); - if (pJob->taskNum >= SCH_MIN_AYSNC_EXEC_NUM) { if (code) { code = schProcessOnTaskFailure(pJob, pTask, code); @@ -886,8 +888,14 @@ _return: } } + if (pCtx->asyncLaunch) { + SCH_UNLOCK_TASK(pTask); + } + schReleaseJob(pJob->refId); + taosMemoryFree(param); + SCH_RET(code); } @@ -902,6 +910,7 @@ int32_t schAsyncLaunchTaskImpl(SSchJob *pJob, SSchTask *pTask) { param->pTask = pTask; if (pJob->taskNum >= SCH_MIN_AYSNC_EXEC_NUM) { + param->asyncLaunch = true; taosAsyncExec(schLaunchTaskImpl, param, NULL); } else { SCH_ERR_RET(schLaunchTaskImpl(param)); From dc8fb900620fe55184f8bef49502dbf40a991cf1 Mon Sep 17 00:00:00 2001 From: Pan YANG Date: Wed, 14 Sep 2022 18:09:20 +0800 Subject: [PATCH 31/50] docs: update latest reserved SQL keywords --- docs/en/12-taos-sql/20-keywords.md | 144 ++++++++++++++++++++++------- docs/zh/12-taos-sql/20-keywords.md | 143 +++++++++++++++++++++------- 2 files changed, 217 insertions(+), 70 deletions(-) diff --git a/docs/en/12-taos-sql/20-keywords.md b/docs/en/12-taos-sql/20-keywords.md index d7b9c73c4f..f7eb067c96 100644 --- a/docs/en/12-taos-sql/20-keywords.md +++ b/docs/en/12-taos-sql/20-keywords.md @@ -5,7 +5,9 @@ title: Reserved Keywords ## Keyword List -There are about 200 keywords reserved by TDengine, they can't be used as the name of database, STable or table with either upper case, lower case or mixed case. The following list shows all reserved keywords: +There are more than 200 keywords reserved by TDengine, they can't be used as the name of database, table, STable, subtable, column or tag with either upper case, lower case or mixed case. If you need to use these keywords, use the symbol `` ` `` to enclose the keywords, e.g. \`ADD\`. + +The following list shows all reserved keywords: ### A @@ -14,15 +16,20 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - ACCOUNTS - ADD - AFTER +- AGGREGATE - ALL - ALTER +- ANALYZE - AND +- APPS - AS - ASC +- AT_ONCE - ATTACH ### B +- BALANCE - BEFORE - BEGIN - BETWEEN @@ -32,19 +39,27 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - BITNOT - BITOR - BLOCKS +- BNODE +- BNODES - BOOL +- BUFFER +- BUFSIZE - BY ### C - CACHE -- CACHELAST +- CACHEMODEL +- CACHESIZE - CASCADE +- CAST - CHANGE +- CLIENT_VERSION - CLUSTER - COLON - COLUMN - COMMA +- COMMENT - COMP - COMPACT - CONCAT @@ -52,15 +67,18 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - CONNECTION - CONNECTIONS - CONNS +- CONSUMER +- CONSUMERS +- CONTAINS - COPY +- COUNT - CREATE -- CTIME +- CURRENT_USER ### D - DATABASE - DATABASES -- DAYS - DBS - DEFERRED - DELETE @@ -69,18 +87,23 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - DESCRIBE - DETACH - DISTINCT +- DISTRIBUTED - DIVIDE - DNODE - DNODES - DOT - DOUBLE - DROP +- DURATION ### E +- EACH +- ENABLE - END -- EQ +- EVERY - EXISTS +- EXPIRED - EXPLAIN ### F @@ -88,18 +111,20 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - FAIL - FILE - FILL +- FIRST - FLOAT +- FLUSH - FOR - FROM -- FSYNC +- FUNCTION +- FUNCTIONS ### G -- GE - GLOB +- GRANT - GRANTS - GROUP -- GT ### H @@ -110,15 +135,18 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - ID - IF - IGNORE -- IMMEDIA +- IMMEDIATE - IMPORT - IN -- INITIAL +- INDEX +- INDEXES +- INITIALLY +- INNER - INSERT - INSTEAD - INT - INTEGER -- INTERVA +- INTERVAL - INTO - IS - ISNULL @@ -126,6 +154,7 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam ### J - JOIN +- JSON ### K @@ -135,46 +164,57 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam ### L -- LE +- LAST +- LAST_ROW +- LICENCES - LIKE - LIMIT - LINEAR - LOCAL -- LP -- LSHIFT -- LT ### M - MATCH +- MAX_DELAY - MAXROWS +- MERGE +- META - MINROWS - MINUS +- MNODE - MNODES - MODIFY - MODULES ### N -- NE +- NCHAR +- NEXT +- NMATCH - NONE - NOT - NOTNULL - NOW - NULL +- NULLS ### O - OF - OFFSET +- ON - OR - ORDER +- OUTPUTTYPE ### P -- PARTITION +- PAGES +- PAGESIZE +- PARTITIONS - PASS - PLUS +- PORT - PPS - PRECISION - PREV @@ -182,47 +222,63 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam ### Q +- QNODE +- QNODES - QTIME -- QUERIE +- QUERIES - QUERY -- QUORUM ### R - RAISE -- REM +- RANGE +- RATIO +- READ +- REDISTRIBUTE +- RENAME - REPLACE - REPLICA - RESET -- RESTRIC +- RESTRICT +- RETENTIONS +- REVOKE +- ROLLUP - ROW -- RP -- RSHIFT ### S +- SCHEMALESS - SCORES - SELECT - SEMI +- SERVER_STATUS +- SERVER_VERSION - SESSION - SET - SHOW -- SLASH +- SINGLE_STABLE - SLIDING - SLIMIT -- SMALLIN +- SMA +- SMALLINT +- SNODE +- SNODES - SOFFSET -- STable -- STableS +- SPLIT +- STABLE +- STABLES - STAR - STATE -- STATEMEN -- STATE_WI +- STATE_WINDOW +- STATEMENT - STORAGE - STREAM - STREAMS +- STRICT - STRING +- SUBSCRIPTIONS - SYNCDB +- SYSINFO ### T @@ -233,20 +289,24 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - TBNAME - TIMES - TIMESTAMP +- TIMEZONE - TINYINT +- TO +- TODAY - TOPIC - TOPICS +- TRANSACTION +- TRANSACTIONS - TRIGGER +- TRIM - TSERIES - TTL ### U -- UMINUS - UNION - UNSIGNED - UPDATE -- UPLUS - USE - USER - USERS @@ -256,8 +316,11 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam - VALUE - VALUES +- VARCHAR - VARIABLE - VARIABLES +- VERBOSE +- VGROUP - VGROUPS - VIEW - VNODES @@ -265,14 +328,25 @@ There are about 200 keywords reserved by TDengine, they can't be used as the nam ### W - WAL +- WAL_FSYNC_PERIOD +- WAL_LEVEL +- WAL_RETENTION_PERIOD +- WAL_RETENTION_SIZE +- WAL_ROLL_PERIOD +- WAL_SEGMENT_SIZE +- WATERMARK - WHERE +- WINDOW_CLOSE +- WITH +- WRITE ### \_ - \_C0 -- \_QSTART -- \_QSTOP - \_QDURATION -- \_WSTART -- \_WSTOP +- \_QEND +- \_QSTART +- \_ROWTS - \_WDURATION +- \_WEND +- \_WSTART diff --git a/docs/zh/12-taos-sql/20-keywords.md b/docs/zh/12-taos-sql/20-keywords.md index 57a45b0a00..7530e803db 100644 --- a/docs/zh/12-taos-sql/20-keywords.md +++ b/docs/zh/12-taos-sql/20-keywords.md @@ -6,7 +6,8 @@ description: TDengine 保留关键字的详细列表 ## 保留关键字 -目前 TDengine 有将近 200 个内部保留关键字,这些关键字无论大小写如果需要用作库名、表名、STable 名、数据列名及标签列名等,需要使用符号 `` ` `` 将关键字括起来使用,例如 \`ADD\`。 +目前 TDengine 有 200 多个内部保留关键字,这些关键字如果需要用作库名、表名、超级表名、子表名、数据列名及标签列名等,无论大小写,需要使用符号 `` ` `` 将关键字括起来使用,例如 \`ADD\`。 + 关键字列表如下: ### A @@ -16,15 +17,20 @@ description: TDengine 保留关键字的详细列表 - ACCOUNTS - ADD - AFTER +- AGGREGATE - ALL - ALTER +- ANALYZE - AND +- APPS - AS - ASC +- AT_ONCE - ATTACH ### B +- BALANCE - BEFORE - BEGIN - BETWEEN @@ -34,19 +40,27 @@ description: TDengine 保留关键字的详细列表 - BITNOT - BITOR - BLOCKS +- BNODE +- BNODES - BOOL +- BUFFER +- BUFSIZE - BY ### C - CACHE -- CACHELAST +- CACHEMODEL +- CACHESIZE - CASCADE +- CAST - CHANGE +- CLIENT_VERSION - CLUSTER - COLON - COLUMN - COMMA +- COMMENT - COMP - COMPACT - CONCAT @@ -54,15 +68,18 @@ description: TDengine 保留关键字的详细列表 - CONNECTION - CONNECTIONS - CONNS +- CONSUMER +- CONSUMERS +- CONTAINS - COPY +- COUNT - CREATE -- CTIME +- CURRENT_USER ### D - DATABASE - DATABASES -- DAYS - DBS - DEFERRED - DELETE @@ -71,18 +88,23 @@ description: TDengine 保留关键字的详细列表 - DESCRIBE - DETACH - DISTINCT +- DISTRIBUTED - DIVIDE - DNODE - DNODES - DOT - DOUBLE - DROP +- DURATION ### E +- EACH +- ENABLE - END -- EQ +- EVERY - EXISTS +- EXPIRED - EXPLAIN ### F @@ -90,18 +112,20 @@ description: TDengine 保留关键字的详细列表 - FAIL - FILE - FILL +- FIRST - FLOAT +- FLUSH - FOR - FROM -- FSYNC +- FUNCTION +- FUNCTIONS ### G -- GE - GLOB +- GRANT - GRANTS - GROUP -- GT ### H @@ -112,15 +136,18 @@ description: TDengine 保留关键字的详细列表 - ID - IF - IGNORE -- IMMEDIA +- IMMEDIATE - IMPORT - IN -- INITIAL +- INDEX +- INDEXES +- INITIALLY +- INNER - INSERT - INSTEAD - INT - INTEGER -- INTERVA +- INTERVAL - INTO - IS - ISNULL @@ -128,6 +155,7 @@ description: TDengine 保留关键字的详细列表 ### J - JOIN +- JSON ### K @@ -137,46 +165,57 @@ description: TDengine 保留关键字的详细列表 ### L -- LE +- LAST +- LAST_ROW +- LICENCES - LIKE - LIMIT - LINEAR - LOCAL -- LP -- LSHIFT -- LT ### M - MATCH +- MAX_DELAY - MAXROWS +- MERGE +- META - MINROWS - MINUS +- MNODE - MNODES - MODIFY - MODULES ### N -- NE +- NCHAR +- NEXT +- NMATCH - NONE - NOT - NOTNULL - NOW - NULL +- NULLS ### O - OF - OFFSET +- ON - OR - ORDER +- OUTPUTTYPE ### P -- PARTITION +- PAGES +- PAGESIZE +- PARTITIONS - PASS - PLUS +- PORT - PPS - PRECISION - PREV @@ -184,47 +223,63 @@ description: TDengine 保留关键字的详细列表 ### Q +- QNODE +- QNODES - QTIME -- QUERIE +- QUERIES - QUERY -- QUORUM ### R - RAISE -- REM +- RANGE +- RATIO +- READ +- REDISTRIBUTE +- RENAME - REPLACE - REPLICA - RESET -- RESTRIC +- RESTRICT +- RETENTIONS +- REVOKE +- ROLLUP - ROW -- RP -- RSHIFT ### S +- SCHEMALESS - SCORES - SELECT - SEMI +- SERVER_STATUS +- SERVER_VERSION - SESSION - SET - SHOW -- SLASH +- SINGLE_STABLE - SLIDING - SLIMIT -- SMALLIN +- SMA +- SMALLINT +- SNODE +- SNODES - SOFFSET -- STable -- STableS +- SPLIT +- STABLE +- STABLES - STAR - STATE -- STATEMEN -- STATE_WI +- STATE_WINDOW +- STATEMENT - STORAGE - STREAM - STREAMS +- STRICT - STRING +- SUBSCRIPTIONS - SYNCDB +- SYSINFO ### T @@ -235,20 +290,24 @@ description: TDengine 保留关键字的详细列表 - TBNAME - TIMES - TIMESTAMP +- TIMEZONE - TINYINT +- TO +- TODAY - TOPIC - TOPICS +- TRANSACTION +- TRANSACTIONS - TRIGGER +- TRIM - TSERIES - TTL ### U -- UMINUS - UNION - UNSIGNED - UPDATE -- UPLUS - USE - USER - USERS @@ -258,8 +317,11 @@ description: TDengine 保留关键字的详细列表 - VALUE - VALUES +- VARCHAR - VARIABLE - VARIABLES +- VERBOSE +- VGROUP - VGROUPS - VIEW - VNODES @@ -267,14 +329,25 @@ description: TDengine 保留关键字的详细列表 ### W - WAL +- WAL_FSYNC_PERIOD +- WAL_LEVEL +- WAL_RETENTION_PERIOD +- WAL_RETENTION_SIZE +- WAL_ROLL_PERIOD +- WAL_SEGMENT_SIZE +- WATERMARK - WHERE +- WINDOW_CLOSE +- WITH +- WRITE ### \_ - \_C0 -- \_QSTART -- \_QSTOP - \_QDURATION -- \_WSTART -- \_WSTOP +- \_QEND +- \_QSTART +- \_ROWTS - \_WDURATION +- \_WEND +- \_WSTART From aa43876665e468f27c81e81331458bfc1304d804 Mon Sep 17 00:00:00 2001 From: Cary Xu Date: Wed, 14 Sep 2022 18:10:51 +0800 Subject: [PATCH 32/50] enh: tsdb retention and fs optimization --- include/libs/tfs/tfs.h | 8 ++++++++ source/dnode/vnode/src/tsdb/tsdbFS.c | 4 ++-- source/dnode/vnode/src/tsdb/tsdbRetention.c | 15 +++++++++++++-- source/libs/tfs/src/tfs.c | 2 ++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/libs/tfs/tfs.h b/include/libs/tfs/tfs.h index 1dc154ce48..6f71fd4cd0 100644 --- a/include/libs/tfs/tfs.h +++ b/include/libs/tfs/tfs.h @@ -69,6 +69,14 @@ void tfsUpdateSize(STfs *pTfs); */ SDiskSize tfsGetSize(STfs *pTfs); +/** + * @brief Get level of multi-tier storage. + * + * @param pTfs + * @return int32_t + */ +int32_t tfsGetLevel(STfs *pTfs); + /** * @brief Allocate an existing available tier level from fs. * diff --git a/source/dnode/vnode/src/tsdb/tsdbFS.c b/source/dnode/vnode/src/tsdb/tsdbFS.c index 31bdb784dd..f02bf2871c 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS.c @@ -58,7 +58,7 @@ static int32_t tsdbGnrtCurrent(STsdb *pTsdb, STsdbFS *pFS, char *fname) { taosCalcChecksumAppend(0, pData, size); // create and write - pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE); + pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_TRUNC); if (pFD == NULL) { code = TAOS_SYSTEM_ERROR(errno); goto _err; @@ -1033,7 +1033,7 @@ int32_t tsdbFSCommit2(STsdb *pTsdb, STsdbFS *pFSNew) { code = TSDB_CODE_OUT_OF_MEMORY; goto _err; } - iOld++; + iNew++; continue; } diff --git a/source/dnode/vnode/src/tsdb/tsdbRetention.c b/source/dnode/vnode/src/tsdb/tsdbRetention.c index d99bf2aa5c..eb4151079b 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRetention.c +++ b/source/dnode/vnode/src/tsdb/tsdbRetention.c @@ -16,9 +16,19 @@ #include "tsdb.h" static bool tsdbShouldDoRetention(STsdb *pTsdb, int64_t now) { + STsdbKeepCfg *keepCfg = &pTsdb->keepCfg; + + if ((keepCfg->keep0 == keepCfg->keep1) && (keepCfg->keep1 == keepCfg->keep2)) { + return false; + } + + if (tfsGetLevel(pTsdb->pVnode->pTfs) <= 1) { + return false; + } + for (int32_t iSet = 0; iSet < taosArrayGetSize(pTsdb->fs.aDFileSet); iSet++) { SDFileSet *pSet = (SDFileSet *)taosArrayGet(pTsdb->fs.aDFileSet, iSet); - int32_t expLevel = tsdbFidLevel(pSet->fid, &pTsdb->keepCfg, now); + int32_t expLevel = tsdbFidLevel(pSet->fid, keepCfg, now); SDiskID did; if (expLevel == pSet->diskId.level) continue; @@ -53,7 +63,7 @@ int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) { if (code) goto _err; for (int32_t iSet = 0; iSet < taosArrayGetSize(fs.aDFileSet); iSet++) { - SDFileSet *pSet = (SDFileSet *)taosArrayGet(pTsdb->fs.aDFileSet, iSet); + SDFileSet *pSet = (SDFileSet *)taosArrayGet(fs.aDFileSet, iSet); int32_t expLevel = tsdbFidLevel(pSet->fid, &pTsdb->keepCfg, now); SDiskID did; @@ -65,6 +75,7 @@ int32_t tsdbDoRetention(STsdb *pTsdb, int64_t now) { taosArrayRemove(fs.aDFileSet, iSet); iSet--; } else { + if (expLevel == 0) continue; if (tfsAllocDisk(pTsdb->pVnode->pTfs, expLevel, &did) < 0) { code = terrno; goto _exit; diff --git a/source/libs/tfs/src/tfs.c b/source/libs/tfs/src/tfs.c index 62aec219df..4600e5e568 100644 --- a/source/libs/tfs/src/tfs.c +++ b/source/libs/tfs/src/tfs.c @@ -113,6 +113,8 @@ SDiskSize tfsGetSize(STfs *pTfs) { return size; } +int32_t tfsGetLevel(STfs *pTfs) { return pTfs->nlevel; } + int32_t tfsAllocDisk(STfs *pTfs, int32_t expLevel, SDiskID *pDiskId) { pDiskId->level = expLevel; pDiskId->id = -1; From 760babe7db64bb479f9f327842e219d043eee838 Mon Sep 17 00:00:00 2001 From: afwerar <1296468573@qq.com> Date: Wed, 14 Sep 2022 18:44:58 +0800 Subject: [PATCH 33/50] os: mac exit error --- source/os/src/osSemaphore.c | 11 +++--- source/os/src/osSysinfo.c | 35 +++++++++---------- tests/system-test/0-others/taosShellNetChk.py | 2 +- tests/system-test/1-insert/mutil_stage.py | 3 ++ 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/source/os/src/osSemaphore.c b/source/os/src/osSemaphore.c index 8cc6f0ef2e..5baba5af1e 100644 --- a/source/os/src/osSemaphore.c +++ b/source/os/src/osSemaphore.c @@ -400,6 +400,9 @@ int tsem_init(tsem_t *psem, int flags, unsigned int count) { } int tsem_destroy(tsem_t *psem) { + if (psem == NULL || *psem == NULL) return -1; + dispatch_release(*psem); + *psem = NULL; return 0; } @@ -421,13 +424,7 @@ int tsem_timewait(tsem_t *psem, int64_t nanosecs) { return 0; } -bool taosCheckPthreadValid(TdThread thread) { - int32_t ret = taosThreadKill(thread, 0); - if (ret == ESRCH) return false; - if (ret == EINVAL) return false; - // alive - return true; -} +bool taosCheckPthreadValid(TdThread thread) { return thread != 0; } int64_t taosGetSelfPthreadId() { TdThread thread = taosThreadSelf(); diff --git a/source/os/src/osSysinfo.c b/source/os/src/osSysinfo.c index 19e9568bbe..6867c1373b 100644 --- a/source/os/src/osSysinfo.c +++ b/source/os/src/osSysinfo.c @@ -344,30 +344,27 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { *numOfCores = si.dwNumberOfProcessors; return 0; #elif defined(_TD_DARWIN_64) - char *line = NULL; - size_t size = 0; + char buf[16]; int32_t done = 0; int32_t code = -1; - TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM); - if (pFile == NULL) return false; - - while (done != 3 && (size = taosGetLineFile(pFile, &line)) != -1) { - line[size - 1] = '\0'; - if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) { - const char *v = strchr(line, ':') + 2; - tstrncpy(cpuModel, v, maxLen); - code = 0; - done |= 1; - } else if (((done & 2) == 0) && strncmp(line, "cpu cores", 9) == 0) { - const char *v = strchr(line, ':') + 2; - *numOfCores = atof(v); - done |= 2; - } + TdCmdPtr pCmd = taosOpenCmd("sysctl -n machdep.cpu.brand_string"); + if (pCmd == NULL) return code; + if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) { + code = 0; + done |= 1; } + taosCloseCmd(&pCmd); - if (line != NULL) taosMemoryFree(line); - taosCloseFile(&pFile); + pCmd = taosOpenCmd("sysctl -n machdep.cpu.core_count"); + if (pCmd == NULL) return code; + memset(buf, 0, sizeof(buf)); + if (taosGetsCmd(pCmd, maxLen, cpuModel) > 0) { + code = 0; + done |= 2; + *numOfCores = atof(buf); + } + taosCloseCmd(&pCmd); return code; #else diff --git a/tests/system-test/0-others/taosShellNetChk.py b/tests/system-test/0-others/taosShellNetChk.py index dd44852d49..80f6a6bc30 100644 --- a/tests/system-test/0-others/taosShellNetChk.py +++ b/tests/system-test/0-others/taosShellNetChk.py @@ -231,7 +231,7 @@ class TDTestCase: if platform.system().lower() == 'windows': os.system('ps -a | grep taos | awk \'{print $2}\' | xargs kill -9') else: - os.system('pkill taos') + os.system('pkill -9 taos') def stop(self): tdSql.close() diff --git a/tests/system-test/1-insert/mutil_stage.py b/tests/system-test/1-insert/mutil_stage.py index 764da1f166..63317e8036 100644 --- a/tests/system-test/1-insert/mutil_stage.py +++ b/tests/system-test/1-insert/mutil_stage.py @@ -1,4 +1,5 @@ from datetime import datetime +from platform import platform import time from typing import List, Any, Tuple @@ -83,6 +84,8 @@ class TDTestCase: def del_old_datadir(self, filename): cmd = f"sed -i '/^dataDir/d' {filename}" + if platform.system().lower() == 'darwin': + cmd = f"sed -i '' '/^dataDir/d' {filename}" if os.system(cmd) != 0: tdLog.exit(cmd) From cd015bae8384ebce3e875fbf83dc6e27e5613470 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Wed, 14 Sep 2022 19:02:26 +0800 Subject: [PATCH 34/50] fix: fix stateduration result error --- source/libs/function/src/builtinsimpl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 470fa8fcd7..9b502eded7 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -4780,7 +4780,7 @@ int32_t stateDurationFunction(SqlFunctionCtx* pCtx) { colDataAppendNULL(pOutput, i); // handle selectivity if (pCtx->subsidiaries.num > 0) { - appendSelectivityValue(pCtx, i, i); + appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1); } continue; } @@ -4797,11 +4797,11 @@ int32_t stateDurationFunction(SqlFunctionCtx* pCtx) { } else { pInfo->durationStart = 0; } - colDataAppend(pOutput, i, (char*)&output, false); + colDataAppend(pOutput, pCtx->offset + numOfElems - 1, (char*)&output, false); // handle selectivity if (pCtx->subsidiaries.num > 0) { - appendSelectivityValue(pCtx, i, i); + appendSelectivityValue(pCtx, i, pCtx->offset + numOfElems - 1); } } From f7fe7a4afb56370b8a872f95598f43c4fc2f244a Mon Sep 17 00:00:00 2001 From: Cary Xu Date: Wed, 14 Sep 2022 19:18:51 +0800 Subject: [PATCH 35/50] fix: remove the code change for commit --- source/dnode/vnode/src/tsdb/tsdbFS.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/dnode/vnode/src/tsdb/tsdbFS.c b/source/dnode/vnode/src/tsdb/tsdbFS.c index f02bf2871c..d80ce9c899 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS.c @@ -1034,6 +1034,7 @@ int32_t tsdbFSCommit2(STsdb *pTsdb, STsdbFS *pFSNew) { goto _err; } + iOld++; iNew++; continue; } From e05fd1615b2793798eb73ce4b67614bb297fb1be Mon Sep 17 00:00:00 2001 From: Cary Xu Date: Wed, 14 Sep 2022 19:19:25 +0800 Subject: [PATCH 36/50] fix: remove the code change for commit --- source/dnode/vnode/src/tsdb/tsdbFS.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbFS.c b/source/dnode/vnode/src/tsdb/tsdbFS.c index d80ce9c899..10926ae6ad 100644 --- a/source/dnode/vnode/src/tsdb/tsdbFS.c +++ b/source/dnode/vnode/src/tsdb/tsdbFS.c @@ -1033,7 +1033,6 @@ int32_t tsdbFSCommit2(STsdb *pTsdb, STsdbFS *pFSNew) { code = TSDB_CODE_OUT_OF_MEMORY; goto _err; } - iOld++; iNew++; continue; From 66bcf1fad695fd4665a58a0d995e6097d6a7efcb Mon Sep 17 00:00:00 2001 From: Minglei Jin Date: Wed, 14 Sep 2022 15:08:33 +0800 Subject: [PATCH 37/50] fix: deep copy ovfl cells to avoid double free --- source/libs/tdb/src/db/tdbBtree.c | 6 +++--- source/libs/tdb/src/db/tdbPage.c | 11 +++++++++-- source/libs/tdb/src/inc/tdbInt.h | 2 +- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/source/libs/tdb/src/db/tdbBtree.c b/source/libs/tdb/src/db/tdbBtree.c index 1480920f90..c6ecd37680 100644 --- a/source/libs/tdb/src/db/tdbBtree.c +++ b/source/libs/tdb/src/db/tdbBtree.c @@ -489,7 +489,7 @@ static int tdbBtreeBalanceDeeper(SBTree *pBt, SPage *pRoot, SPage **ppChild, TXN } // Copy the root page content to the child page - tdbPageCopy(pRoot, pChild); + tdbPageCopy(pRoot, pChild, 0); // Reinitialize the root page zArg.flags = TDB_BTREE_ROOT; @@ -742,7 +742,7 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx for (int i = 0; i < nOlds; i++) { tdbPageCreate(pOlds[0]->pageSize, &pOldsCopy[i], tdbDefaultMalloc, NULL); tdbBtreeInitPage(pOldsCopy[i], &iarg, 0); - tdbPageCopy(pOlds[i], pOldsCopy[i]); + tdbPageCopy(pOlds[i], pOldsCopy[i], 0); } iNew = 0; nNewCells = 0; @@ -840,7 +840,7 @@ static int tdbBtreeBalanceNonRoot(SBTree *pBt, SPage *pParent, int idx, TXN *pTx i8 flags = TDB_BTREE_ROOT | TDB_BTREE_PAGE_IS_LEAF(pNews[0]); // copy content to the parent page tdbBtreeInitPage(pParent, &(SBtreeInitPageArg){.flags = flags, .pBt = pBt}, 0); - tdbPageCopy(pNews[0], pParent); + tdbPageCopy(pNews[0], pParent, 1); } for (int i = 0; i < 3; i++) { diff --git a/source/libs/tdb/src/db/tdbPage.c b/source/libs/tdb/src/db/tdbPage.c index a3f376b929..1e2eefabf4 100644 --- a/source/libs/tdb/src/db/tdbPage.c +++ b/source/libs/tdb/src/db/tdbPage.c @@ -229,7 +229,7 @@ int tdbPageDropCell(SPage *pPage, int idx, TXN *pTxn, SBTree *pBt) { return 0; } -void tdbPageCopy(SPage *pFromPage, SPage *pToPage) { +void tdbPageCopy(SPage *pFromPage, SPage *pToPage, int deepCopyOvfl) { int delta, nFree; pToPage->pFreeStart = pToPage->pPageHdr + (pFromPage->pFreeStart - pFromPage->pPageHdr); @@ -250,8 +250,15 @@ void tdbPageCopy(SPage *pFromPage, SPage *pToPage) { // Copy the overflow cells for (int iOvfl = 0; iOvfl < pFromPage->nOverflow; iOvfl++) { + SCell *pNewCell = pFromPage->apOvfl[iOvfl]; + if (deepCopyOvfl) { + int szCell = (*pFromPage->xCellSize)(pFromPage, pFromPage->apOvfl[iOvfl], 0, NULL, NULL); + pNewCell = (SCell *)tdbOsMalloc(szCell); + memcpy(pNewCell, pFromPage->apOvfl[iOvfl], szCell); + } + + pToPage->apOvfl[iOvfl] = pNewCell; pToPage->aiOvfl[iOvfl] = pFromPage->aiOvfl[iOvfl]; - pToPage->apOvfl[iOvfl] = pFromPage->apOvfl[iOvfl]; } pToPage->nOverflow = pFromPage->nOverflow; } diff --git a/source/libs/tdb/src/inc/tdbInt.h b/source/libs/tdb/src/inc/tdbInt.h index df6ba8b35f..29a9665c15 100644 --- a/source/libs/tdb/src/inc/tdbInt.h +++ b/source/libs/tdb/src/inc/tdbInt.h @@ -333,7 +333,7 @@ void tdbPageInit(SPage *pPage, u8 szAmHdr, int (*xCellSize)(const SPage *, SCell int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell, u8 asOvfl); int tdbPageDropCell(SPage *pPage, int idx, TXN *pTxn, SBTree *pBt); int tdbPageUpdateCell(SPage *pPage, int idx, SCell *pCell, int szCell, TXN *pTxn, SBTree *pBt); -void tdbPageCopy(SPage *pFromPage, SPage *pToPage); +void tdbPageCopy(SPage *pFromPage, SPage *pToPage, int copyOvflCells); int tdbPageCapacity(int pageSize, int amHdrSize); static inline SCell *tdbPageGetCell(SPage *pPage, int idx) { From dcbdc43ff5a22cecad48cded12b6b0668d60cc82 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Wed, 14 Sep 2022 22:38:29 +0800 Subject: [PATCH 38/50] fix some code --- source/common/src/tdataformat.c | 39 +++++++++++++-------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index dd2667b302..fc7d211ab3 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1210,6 +1210,7 @@ static FORCE_INLINE int32_t tColDataPutValue(SColData *pColData, SColVal *pColVa pColData->nData += pColVal->value.nData; } } else { + ASSERT(pColData->nData == tDataTypes[pColData->type].bytes * pColData->nVal); code = tRealloc(&pColData->pData, pColData->nData + tDataTypes[pColData->type].bytes); if (code) goto _exit; pColData->nData += tPutValue(pColData->pData + pColData->nData, &pColVal->value, pColVal->type); @@ -1331,6 +1332,8 @@ static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pC SET_BIT1(pColData->pBitMap, pColData->nVal, 1); } else { + pColData->flag |= HAS_VALUE; + uint8_t *pBitMap = NULL; code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) goto _exit; @@ -1340,8 +1343,6 @@ static FORCE_INLINE int32_t tColDataAppendValue3(SColData *pColData, SColVal *pC } SET_BIT2(pBitMap, pColData->nVal, 2); - pColData->flag |= HAS_VALUE; - tFree(pColData->pBitMap); pColData->pBitMap = pBitMap; @@ -1370,31 +1371,21 @@ _exit: static FORCE_INLINE int32_t tColDataAppendValue4(SColData *pColData, SColVal *pColVal) { // HAS_VALUE int32_t code = 0; - if (pColVal->isNone) { - pColData->flag |= HAS_NONE; + if (pColVal->isNone || pColVal->isNull) { + if (pColVal->isNone) { + pColData->flag |= HAS_NONE; + } else { + pColData->flag |= HAS_NULL; + } - code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); + int32_t nBit = BIT1_SIZE(pColData->nVal + 1); + code = tRealloc(&pColData->pBitMap, nBit); if (code) goto _exit; - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT1(pColData->pBitMap, iVal, 1); - } + memset(pColData->pBitMap, 255, nBit); SET_BIT1(pColData->pBitMap, pColData->nVal, 0); - code = tColDataPutValue(pColData, &COL_VAL_VALUE(pColData->cid, pColData->type, (SValue){0})); - if (code) goto _exit; - } else if (pColVal->isNull) { - pColData->flag |= HAS_NULL; - - code = tRealloc(&pColData->pBitMap, BIT1_SIZE(pColData->nVal + 1)); - if (code) goto _exit; - - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - SET_BIT1(pColData->pBitMap, iVal, 1); - } - SET_BIT1(pColData->pBitMap, pColData->nVal, 0); - - code = tColDataPutValue(pColData, &COL_VAL_VALUE(pColData->cid, pColData->type, (SValue){0})); + code = tColDataPutValue(pColData, pColVal); if (code) goto _exit; } else { code = tColDataPutValue(pColData, pColVal); @@ -1415,7 +1406,7 @@ static FORCE_INLINE int32_t tColDataAppendValue5(SColData *pColData, SColVal *pC code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) goto _exit; - for (int32_t iVal = 0; iVal < pColData->nData; iVal++) { + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 0); } SET_BIT2(pBitMap, pColData->nVal, 1); @@ -1450,7 +1441,7 @@ static FORCE_INLINE int32_t tColDataAppendValue6(SColData *pColData, SColVal *pC code = tRealloc(&pBitMap, BIT2_SIZE(pColData->nVal + 1)); if (code) goto _exit; - for (int32_t iVal = 0; iVal < pColData->nData; iVal++) { + for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { SET_BIT2(pBitMap, iVal, GET_BIT1(pColData->pBitMap, iVal) ? 2 : 1); } SET_BIT2(pBitMap, pColData->nVal, 0); From 3b947f17adcaab5f2b77b06a12eccb3ce2c1d7b2 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Wed, 14 Sep 2022 22:47:44 +0800 Subject: [PATCH 39/50] more code --- source/dnode/vnode/src/tsdb/tsdbUtil.c | 88 ++++---------------------- 1 file changed, 13 insertions(+), 75 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 32fc7b82a1..64c150484b 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -1744,47 +1744,16 @@ int32_t tsdbCmprColData(SColData *pColData, int8_t cmprAlg, SBlockCol *pBlockCol int32_t size = 0; // bitmap if (pColData->flag != HAS_VALUE) { - uint8_t *pBitMap = pColData->pBitMap; - int32_t szBitMap = BIT2_SIZE(pColData->nVal); - - // BIT2 to BIT1 - if (pColData->flag != (HAS_VALUE | HAS_NULL | HAS_NONE)) { + int32_t szBitMap; + if (pColData->flag == (HAS_VALUE | HAS_NULL | HAS_NONE)) { + szBitMap = BIT2_SIZE(pColData->nVal); + } else { szBitMap = BIT1_SIZE(pColData->nVal); - pBitMap = taosMemoryCalloc(1, szBitMap); - if (pBitMap == NULL) { - code = TSDB_CODE_OUT_OF_MEMORY; - goto _exit; - } - - for (int32_t iVal = 0; iVal < pColData->nVal; iVal++) { - uint8_t v = GET_BIT2(pColData->pBitMap, iVal); - switch (pColData->flag) { - case (HAS_NULL | HAS_NONE): - SET_BIT1(pBitMap, iVal, v); - break; - case (HAS_VALUE | HAS_NONE): - if (v) { - SET_BIT1(pBitMap, iVal, 1); - } else { - SET_BIT1(pBitMap, iVal, 0); - } - break; - case (HAS_VALUE | HAS_NULL): - SET_BIT1(pBitMap, iVal, v - 1); - break; - default: - ASSERT(0); - } - } } - code = tsdbCmprData(pBitMap, szBitMap, TSDB_DATA_TYPE_TINYINT, cmprAlg, ppOut, nOut + size, &pBlockCol->szBitmap, - ppBuf); + code = tsdbCmprData(pColData->pBitMap, szBitMap, TSDB_DATA_TYPE_TINYINT, cmprAlg, ppOut, nOut + size, + &pBlockCol->szBitmap, ppBuf); if (code) goto _exit; - - if (pColData->flag != (HAS_VALUE | HAS_NULL | HAS_NONE)) { - taosMemoryFree(pBitMap); - } } size += pBlockCol->szBitmap; @@ -1822,46 +1791,15 @@ int32_t tsdbDecmprColData(uint8_t *pIn, SBlockCol *pBlockCol, int8_t cmprAlg, in uint8_t *p = pIn; // bitmap if (pBlockCol->szBitmap) { - if (pBlockCol->flag != (HAS_VALUE | HAS_NULL | HAS_NONE)) { - uint8_t *pBitMap = NULL; - code = tsdbDecmprData(p, pBlockCol->szBitmap, TSDB_DATA_TYPE_TINYINT, cmprAlg, &pBitMap, - BIT1_SIZE(pColData->nVal), ppBuf); - if (code) goto _exit; - - code = tRealloc(&pColData->pBitMap, BIT2_SIZE(pColData->nVal)); - if (code) { - tFree(pBitMap); - goto _exit; - } - - // BIT1 to BIT2 - for (int32_t iVal = 0; iVal < nVal; iVal++) { - uint8_t v = GET_BIT1(pBitMap, iVal); - switch (pBlockCol->flag) { - case (HAS_NULL | HAS_NONE): - SET_BIT2(pColData->pBitMap, iVal, v); - break; - case (HAS_VALUE | HAS_NONE): - if (v) { - SET_BIT2(pColData->pBitMap, iVal, 2); - } else { - SET_BIT2(pColData->pBitMap, iVal, 0); - } - break; - case (HAS_VALUE | HAS_NULL): - SET_BIT2(pColData->pBitMap, iVal, v + 1); - break; - default: - ASSERT(0); - } - } - - tFree(pBitMap); + int32_t szBitMap; + if (pColData->flag == (HAS_VALUE | HAS_NULL | HAS_NONE)) { + szBitMap = BIT2_SIZE(pColData->nVal); } else { - code = tsdbDecmprData(p, pBlockCol->szBitmap, TSDB_DATA_TYPE_TINYINT, cmprAlg, &pColData->pBitMap, - BIT2_SIZE(pColData->nVal), ppBuf); - if (code) goto _exit; + szBitMap = BIT1_SIZE(pColData->nVal); } + + code = tsdbDecmprData(p, pBlockCol->szBitmap, TSDB_DATA_TYPE_TINYINT, cmprAlg, &pColData->pBitMap, szBitMap, ppBuf); + if (code) goto _exit; } p += pBlockCol->szBitmap; From 26f740f26b544fde7a2f12235c07b5c0c11282a0 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Thu, 15 Sep 2022 09:56:56 +0800 Subject: [PATCH 40/50] fix more --- include/common/tdataformat.h | 3 ++- source/common/src/tdataformat.c | 32 ++++++++++++++++++++++++++ source/dnode/vnode/src/tsdb/tsdbRead.c | 4 ++-- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 159279329b..5b49560175 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -110,7 +110,8 @@ void tColDataDestroy(void *ph); void tColDataInit(SColData *pColData, int16_t cid, int8_t type, int8_t smaOn); void tColDataClear(SColData *pColData); int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal); -void tColDataGetValue(SColData *pColData, int32_t iRow, SColVal *pColVal); +void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal); +uint8_t tColDataGetBitValue(SColData *pColData, int32_t iVal); int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest); // STRUCT ================================ diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index fc7d211ab3..15a369fe40 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1592,6 +1592,38 @@ void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) { tColDataGetValueImpl[pColData->flag](pColData, iVal, pColVal); } +uint8_t tColDataGetBitValue(SColData *pColData, int32_t iVal) { + uint8_t v; + switch (pColData->flag) { + case HAS_NONE: + v = 0; + break; + case HAS_NULL: + v = 1; + break; + case (HAS_NULL | HAS_NONE): + v = GET_BIT1(pColData->pBitMap, iVal); + break; + case HAS_VALUE: + v = 2; + break; + case (HAS_VALUE | HAS_NONE): + v = GET_BIT1(pColData->pBitMap, iVal); + if (v) v = 2; + break; + case (HAS_VALUE | HAS_NULL): + v = GET_BIT1(pColData->pBitMap, iVal) + 1; + break; + case (HAS_VALUE | HAS_NULL | HAS_NONE): + v = GET_BIT2(pColData->pBitMap, iVal); + break; + default: + ASSERT(0); + break; + } + return v; +} + int32_t tColDataCopy(SColData *pColDataSrc, SColData *pColDataDest) { int32_t code = 0; int32_t size; diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c index 60d967681b..baa985fb24 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead.c @@ -903,7 +903,7 @@ static int32_t copyBlockDataToSDataBlock(STsdbReader* pReader, STableBlockScanIn // null value exists, check one-by-one if (pData->flag != HAS_VALUE) { for (int32_t j = pDumpInfo->rowIndex; rowIndex < remain; j += step, rowIndex++) { - uint8_t v = GET_BIT2(pData->pBitMap, j); + uint8_t v = tColDataGetBitValue(pData, j); if (v == 0 || v == 1) { colDataSetNull_f(pColData->nullbitmap, rowIndex); } @@ -4078,4 +4078,4 @@ void tsdbUntakeReadSnap(STsdb* pTsdb, STsdbReadSnap* pSnap) { } tsdbTrace("vgId:%d, untake read snapshot", TD_VID(pTsdb->pVnode)); -} \ No newline at end of file +} From 367552b9146d8d8053baea29d44d24a6480bc940 Mon Sep 17 00:00:00 2001 From: Liu Jicong Date: Thu, 15 Sep 2022 10:08:48 +0800 Subject: [PATCH 41/50] fix delete --- source/dnode/vnode/src/tq/tq.c | 2 +- source/libs/executor/src/dataDeleter.c | 38 ++++++++++++++++---------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c index f9c2757c37..c8841e5e16 100644 --- a/source/dnode/vnode/src/tq/tq.c +++ b/source/dnode/vnode/src/tq/tq.c @@ -832,7 +832,7 @@ int32_t tqProcessDelReq(STQ* pTq, void* pReq, int32_t len, int64_t ver) { tDecoderClear(pCoder); int32_t sz = taosArrayGetSize(pRes->uidList); - if (sz == 0) { + if (sz == 0 || pRes->affectedRows == 0) { taosArrayDestroy(pRes->uidList); return 0; } diff --git a/source/libs/executor/src/dataDeleter.c b/source/libs/executor/src/dataDeleter.c index 40198615ea..55a1a1fdb9 100644 --- a/source/libs/executor/src/dataDeleter.c +++ b/source/libs/executor/src/dataDeleter.c @@ -79,25 +79,33 @@ static void toDataCacheEntry(SDataDeleterHandle* pHandle, const SInputData* pInp pEntry->dataLen = sizeof(SDeleterRes); ASSERT(1 == pEntry->numOfRows); - ASSERT(1 == pEntry->numOfCols); + ASSERT(3 == pEntry->numOfCols); pBuf->useSize = sizeof(SDataCacheEntry); SColumnInfoData* pColRes = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 0); + SColumnInfoData* pColSKey = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 1); + SColumnInfoData* pColEKey = (SColumnInfoData*)taosArrayGet(pInput->pData->pDataBlock, 2); SDeleterRes* pRes = (SDeleterRes*)pEntry->data; pRes->suid = pHandle->pParam->suid; pRes->uidList = pHandle->pParam->pUidList; - pRes->skey = pHandle->pDeleter->deleteTimeRange.skey; - pRes->ekey = pHandle->pDeleter->deleteTimeRange.ekey; strcpy(pRes->tableName, pHandle->pDeleter->tableFName); strcpy(pRes->tsColName, pHandle->pDeleter->tsColName); pRes->affectedRows = *(int64_t*)pColRes->pData; + if (pRes->affectedRows) { + pRes->skey = *(int64_t*)pColSKey->pData; + pRes->ekey = *(int64_t*)pColEKey->pData; + ASSERT(pRes->skey <= pRes->ekey); + } else { + pRes->skey = pHandle->pDeleter->deleteTimeRange.skey; + pRes->ekey = pHandle->pDeleter->deleteTimeRange.ekey; + } pBuf->useSize += pEntry->dataLen; - - atomic_add_fetch_64(&pHandle->cachedSize, pEntry->dataLen); - atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); + + atomic_add_fetch_64(&pHandle->cachedSize, pEntry->dataLen); + atomic_add_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); } static bool allocBuf(SDataDeleterHandle* pDeleter, const SInputData* pInput, SDataDeleterBuf* pBuf) { @@ -172,7 +180,8 @@ static void getDataLength(SDataSinkHandle* pHandle, int64_t* pLen, bool* pQueryE SDataCacheEntry* pEntry = (SDataCacheEntry*)pDeleter->nextOutput.pData; *pLen = pEntry->dataLen; *pQueryEnd = pDeleter->queryEnd; - qDebug("got data len %" PRId64 ", row num %d in sink", *pLen, ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->numOfRows); + qDebug("got data len %" PRId64 ", row num %d in sink", *pLen, + ((SDataCacheEntry*)(pDeleter->nextOutput.pData))->numOfRows); } static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { @@ -186,14 +195,14 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { return TSDB_CODE_SUCCESS; } SDataCacheEntry* pEntry = (SDataCacheEntry*)(pDeleter->nextOutput.pData); - memcpy(pOutput->pData, pEntry->data, pEntry->dataLen); + memcpy(pOutput->pData, pEntry->data, pEntry->dataLen); pDeleter->pParam->pUidList = NULL; pOutput->numOfRows = pEntry->numOfRows; pOutput->numOfCols = pEntry->numOfCols; pOutput->compressed = pEntry->compressed; - atomic_sub_fetch_64(&pDeleter->cachedSize, pEntry->dataLen); - atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); + atomic_sub_fetch_64(&pDeleter->cachedSize, pEntry->dataLen); + atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pEntry->dataLen); taosMemoryFreeClear(pDeleter->nextOutput.pData); // todo persistent pOutput->bufStatus = updateStatus(pDeleter); @@ -202,7 +211,7 @@ static int32_t getDataBlock(SDataSinkHandle* pHandle, SOutputData* pOutput) { pOutput->useconds = pDeleter->useconds; pOutput->precision = pDeleter->pSchema->precision; taosThreadMutexUnlock(&pDeleter->mutex); - + return TSDB_CODE_SUCCESS; } @@ -211,7 +220,7 @@ static int32_t destroyDataSinker(SDataSinkHandle* pHandle) { atomic_sub_fetch_64(&gDataSinkStat.cachedSize, pDeleter->cachedSize); taosMemoryFreeClear(pDeleter->nextOutput.pData); taosArrayDestroy(pDeleter->pParam->pUidList); - taosMemoryFree(pDeleter->pParam); + taosMemoryFree(pDeleter->pParam); while (!taosQueueEmpty(pDeleter->pDataBlocks)) { SDataDeleterBuf* pBuf = NULL; taosReadQitem(pDeleter->pDataBlocks, (void**)&pBuf); @@ -230,14 +239,15 @@ static int32_t getCacheSize(struct SDataSinkHandle* pHandle, uint64_t* size) { return TSDB_CODE_SUCCESS; } -int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, void *pParam) { +int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pDataSink, DataSinkHandle* pHandle, + void* pParam) { SDataDeleterHandle* deleter = taosMemoryCalloc(1, sizeof(SDataDeleterHandle)); if (NULL == deleter) { terrno = TSDB_CODE_QRY_OUT_OF_MEMORY; return TSDB_CODE_QRY_OUT_OF_MEMORY; } - SDataDeleterNode* pDeleterNode = (SDataDeleterNode *)pDataSink; + SDataDeleterNode* pDeleterNode = (SDataDeleterNode*)pDataSink; deleter->sink.fPut = putDataBlock; deleter->sink.fEndPut = endPut; deleter->sink.fGetLen = getDataLength; From cdd46c532e533e5a1de0d461b6ba7e39e0a5efb6 Mon Sep 17 00:00:00 2001 From: Kyno Date: Thu, 15 Sep 2022 10:35:57 +0800 Subject: [PATCH 42/50] fix: spelling error. --- docs/zh/12-taos-sql/06-select.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/12-taos-sql/06-select.md b/docs/zh/12-taos-sql/06-select.md index b0a7d88efe..0d38cb0635 100644 --- a/docs/zh/12-taos-sql/06-select.md +++ b/docs/zh/12-taos-sql/06-select.md @@ -104,7 +104,7 @@ SELECT location, groupid, current FROM d1001 LIMIT 2; ### 结果去重 -`DISINTCT` 关键字可以对结果集中的一列或多列进行去重,去除的列既可以是标签列也可以是数据列。 +`DISTINCT` 关键字可以对结果集中的一列或多列进行去重,去除的列既可以是标签列也可以是数据列。 对标签列去重: From 1530d75f9fa4a9fdb0c8a554de8938eb8f6e08f8 Mon Sep 17 00:00:00 2001 From: huolibo Date: Thu, 15 Sep 2022 13:11:34 +0800 Subject: [PATCH 43/50] Update 14-taosKeeper.md --- docs/zh/14-reference/14-taosKeeper.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/zh/14-reference/14-taosKeeper.md b/docs/zh/14-reference/14-taosKeeper.md index ae0a496f03..7780dc2fe9 100644 --- a/docs/zh/14-reference/14-taosKeeper.md +++ b/docs/zh/14-reference/14-taosKeeper.md @@ -79,7 +79,7 @@ password = "taosdata" # 需要被监控的 taosAdapter [taosAdapter] -address = ["127.0.0.1:6041","192.168.1.95:6041"] +address = ["127.0.0.1:6041"] [metrics] # 监控指标前缀 @@ -92,7 +92,7 @@ cluster = "production" database = "log" # 指定需要监控的普通表 -tables = ["normal_table"] +tables = [] ``` ### 获取监控指标 @@ -141,4 +141,4 @@ taos_cluster_info_dnodes_total{cluster_id="5981392874047724755"} 1 # HELP taos_cluster_info_first_ep # TYPE taos_cluster_info_first_ep gauge taos_cluster_info_first_ep{cluster_id="5981392874047724755",value="hlb:6030"} 1 -``` \ No newline at end of file +``` From 5003725d7ea5c6f1338eed2479449989275ba0be Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Thu, 15 Sep 2022 14:37:40 +0800 Subject: [PATCH 44/50] feat: update taostools e7270c9 for3.0 (#16858) * feat: update taos-tools 9f4c01e for 3.0 * feat: update taos-tools e7270c9 for 3.0 --- cmake/taostools_CMakeLists.txt.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/taostools_CMakeLists.txt.in b/cmake/taostools_CMakeLists.txt.in index 0f7a450920..6fb2a69847 100644 --- a/cmake/taostools_CMakeLists.txt.in +++ b/cmake/taostools_CMakeLists.txt.in @@ -2,7 +2,7 @@ # taos-tools ExternalProject_Add(taos-tools GIT_REPOSITORY https://github.com/taosdata/taos-tools.git - GIT_TAG 3588b3d + GIT_TAG e7270c9 SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools" BINARY_DIR "" #BUILD_IN_SOURCE TRUE From 49f3e3c2c55b785c093adb2da51a02ecdc6ef717 Mon Sep 17 00:00:00 2001 From: Yiqing Liu Date: Thu, 15 Sep 2022 15:26:19 +0800 Subject: [PATCH 45/50] Update 07-tmq.mdx --- docs/zh/07-develop/07-tmq.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/07-develop/07-tmq.mdx b/docs/zh/07-develop/07-tmq.mdx index 2f5c13d9b0..d9a35ab4eb 100644 --- a/docs/zh/07-develop/07-tmq.mdx +++ b/docs/zh/07-develop/07-tmq.mdx @@ -218,7 +218,7 @@ void Close() ```sql DROP DATABASE IF EXISTS tmqdb; CREATE DATABASE tmqdb; -CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16) TAGS(t1 INT, t3 VARCHAR(16)); +CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16)); CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0"); CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1"); INSERT INTO tmqdb.ctb0 VALUES(now, 0, 0, 'a0')(now+1s, 0, 0, 'a00'); From 4ff617ae357499563f4559b0402091daaa914111 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 15 Sep 2022 15:34:29 +0800 Subject: [PATCH 46/50] docs: remove wrong description --- docs/zh/10-deployment/01-deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/10-deployment/01-deploy.md b/docs/zh/10-deployment/01-deploy.md index 03b4ce30f9..5857b9acd3 100644 --- a/docs/zh/10-deployment/01-deploy.md +++ b/docs/zh/10-deployment/01-deploy.md @@ -168,7 +168,7 @@ Query OK, 8 row(s) in set (0.001154s) ## 删除数据节点 -先停止要删除的数据节点的 taosd 进程,然后启动 CLI 程序 taos,执行: +然后启动 CLI 程序 taos,执行: ```sql DROP DNODE "fqdn:port"; From df8d708255012b24ed6bdefe29f79747341a839f Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 15 Sep 2022 15:50:47 +0800 Subject: [PATCH 47/50] docs: remove wrong description --- docs/zh/10-deployment/01-deploy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/zh/10-deployment/01-deploy.md b/docs/zh/10-deployment/01-deploy.md index 5857b9acd3..eecb86ce41 100644 --- a/docs/zh/10-deployment/01-deploy.md +++ b/docs/zh/10-deployment/01-deploy.md @@ -168,7 +168,7 @@ Query OK, 8 row(s) in set (0.001154s) ## 删除数据节点 -然后启动 CLI 程序 taos,执行: +启动 CLI 程序 taos,执行: ```sql DROP DNODE "fqdn:port"; From 83b40713bd786ec9907261e0fa5f60efaf3a64c2 Mon Sep 17 00:00:00 2001 From: gccgdb1234 Date: Thu, 15 Sep 2022 16:33:41 +0800 Subject: [PATCH 48/50] doc: tdinsight english version change --- .../15146-tdengine-monitor-dashboard.json | 8 +- .../assets/TDinsight-1-cluster-status.webp | Bin 27958 -> 19366 bytes .../assets/TDinsight-2-dnodes.webp | Bin 13838 -> 5582 bytes .../assets/TDinsight-3-mnodes.webp | Bin 8256 -> 7056 bytes .../assets/TDinsight-4-requests.webp | Bin 96252 -> 16572 bytes .../assets/TDinsight-5-database.webp | Bin 7674 -> 7244 bytes .../assets/TDinsight-8-taosadapter.webp | Bin 16890 -> 10766 bytes .../assets/howto-add-datasource.webp | Bin 11140 -> 15976 bytes .../07-tdinsight/assets/import_dashboard.webp | Bin 16692 -> 6342 bytes .../assets/import_dashboard_view.webp | Bin 0 -> 5452 bytes .../assets/select_dashboard_db.webp | Bin 0 -> 23862 bytes .../assets/tdengine-grafana-7.x.json | 8 +- docs/en/14-reference/07-tdinsight/index.md | 93 +++++------------- 13 files changed, 35 insertions(+), 74 deletions(-) create mode 100644 docs/en/14-reference/07-tdinsight/assets/import_dashboard_view.webp create mode 100644 docs/en/14-reference/07-tdinsight/assets/select_dashboard_db.webp diff --git a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json index 54dc1062d6..f651983528 100644 --- a/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json +++ b/docs/en/14-reference/07-tdinsight/assets/15146-tdengine-monitor-dashboard.json @@ -211,7 +211,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Leader MNode", + "title": "Master MNode", "transformations": [ { "id": "filterByValue", @@ -221,7 +221,7 @@ "config": { "id": "regex", "options": { - "value": "leader" + "value": "master" } }, "fieldName": "role" @@ -300,7 +300,7 @@ ], "timeFrom": null, "timeShift": null, - "title": "Leader MNode Create Time", + "title": "Master MNode Create Time", "transformations": [ { "id": "filterByValue", @@ -310,7 +310,7 @@ "config": { "id": "regex", "options": { - "value": "leader" + "value": "master" } }, "fieldName": "role" diff --git a/docs/en/14-reference/07-tdinsight/assets/TDinsight-1-cluster-status.webp b/docs/en/14-reference/07-tdinsight/assets/TDinsight-1-cluster-status.webp index a78e18028a94c2f6a783b08d992a25c791527407..3bc0d960f1db45ee8d2adcee26de89334e681956 100644 GIT binary patch literal 19366 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

Wrk4l=@EjCcKKX8lu1N!^)`&CU zPIU7+o5~)%b9b-66QdF<{5in;EtANKlouQ>1SFRQM#?9qlZ`psSury-t|-IP+{cw# z>sFNCj4{Xua=*g~L)(yC0vcj6z&^D>7VR~4N&U64)&MRC9Yy(4o1=_hKu(~?sa%Zy# z%ue;i!PqVS6b;h90^jaKvtTEGTwlhoX4vB9M*t^`)LzMgIHyPe5dNfaf+)oQm~bA;{b*D@5n|B@tgyAB90M; z%{#m#^{vf@Nz@XyB^FapuzJj5s_lAIW#bNny|hWW+vH-NtAI|8D>lUr%ClP0bcHq# z_4HJOTJYuE7OSuc#>&9TtIsYTL|(*l^TN~8>_e`SLp}u@WM!7)D5=fRBU*f^*xu#} z@PVAFn7I$D>ixfr`_zj4gx7dEN4|W$Q9&!j_|$-G9_?$jQ0>$d`0Ks*k@Xr6!2kdN z0}LE1=kXBu{fUJ!GNk0msL@eoF(6^0G#mc)i$iSiYREL`ZOs2q_3oCO7UG*670$`|_mL3_Xe0000)Qr7eU literal 8256 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 literal 96252 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 T@2InULr)yonW*P~T*Utabt@^k literal 7674 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 H4gmZQX{eNy diff --git a/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp b/docs/en/14-reference/07-tdinsight/assets/TDinsight-8-taosadapter.webp index 8666193f59497180574fd2786266e5baabbe9761..942130d4fabf7944c7add10acb3bb42ca7f51e0f 100644 GIT binary patch literal 10766 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 W;6L~e{)7MEKll&+ga6<^r6C44JBOD5 diff --git a/docs/en/14-reference/07-tdinsight/assets/import_dashboard.webp b/docs/en/14-reference/07-tdinsight/assets/import_dashboard.webp index fb7958f1b9fbd43c8f63136024842790e711c490..ae2a1e8e9b7b63a68d56dfcd2187eca614da9a3d 100644 GIT binary patch literal 6342 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 literal 16692 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 literal 0 HcmV?d00001 diff --git a/docs/en/14-reference/07-tdinsight/assets/select_dashboard_db.webp b/docs/en/14-reference/07-tdinsight/assets/select_dashboard_db.webp new file mode 100644 index 0000000000000000000000000000000000000000..956132e37e9df255d3ff82654fd357bec001e695 GIT binary patch literal 23862 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 Apply external notifier uid to TDinsight dashboard. -Alibaba Cloud SMS as Notifier: --s, --sms-enabled To enable tdengine-datasource plugin builtin Alibaba Cloud SMS webhook. --N, --sms-notifier-name Provisioning notifier name.[default: TDinsight Builtin SMS] --U, --sms-notifier-uid Provisioning notifier uid, use lowercase notifier name by default. --D, --sms-notifier-is-default Set notifier as default. --I, --sms-access-key-id Alibaba Cloud SMS access key id --K, --sms-access-key-secret Alibaba Cloud SMS access key secret --S, --sms-sign-name Sign name --C, --sms-template-code Template code --T, --sms-template-param Template param, a escaped JSON string like '{"alarm_level":"%s","time":"%s","name":"%s","content":"%s"}' --B, --sms-phone-numbers Comma-separated numbers list, eg "189xxxxxxxx,132xxxxxxxx" --L, --sms-listen-addr [default: 127.0.0.1:9100] ``` Most command-line options can take effect the same as environment variables. @@ -136,17 +132,6 @@ Most command-line options can take effect the same as environment variables. | -t | --tdinsight-title | TDINSIGHT_DASHBOARD_TITLE | TDinsight dashboard title. [Default: TDinsight] | -e | -tdinsight-title | -e | --tdinsight-editable | TDINSIGHT_DASHBOARD_EDITABLE | If the dashboard is configured to be editable. [Default: false] | -e | --external | -E | --external-notifier | EXTERNAL_NOTIFIER | Apply the external notifier uid to the TDinsight dashboard. | -s -| -s | --sms-enabled | SMS_ENABLED | Enable the tdengine-datasource plugin built into Alibaba Cloud SMS webhook. | -s -| -N | --sms-notifier-name | SMS_NOTIFIER_NAME | The name of the provisioning notifier. [Default: `TDinsight Builtin SMS`] | -U -| -U | --sms-notifier-uid | SMS_NOTIFIER_UID | "Notification Channel" `uid`, lowercase of the program name is used by default, other characters are replaced by "-". |-sms -| -D | --sms-notifier-is-default | SMS_NOTIFIER_IS_DEFAULT | Set built-in SMS notification to default value. |-sms-notifier-is-default -| -I | --sms-access-key-id | SMS_ACCESS_KEY_ID | Alibaba Cloud SMS access key id | -| -K | --sms-access-key-secret | SMS_ACCESS_KEY_SECRET | AliCloud SMS-access-secret-key | -| -S | --sms-sign-name | SMS_SIGN_NAME | Signature | -| -C | --sms-template-code | SMS_TEMPLATE_CODE | Template code | -| -T | --sms-template-param | SMS_TEMPLATE_PARAM | JSON template for template parameters | -| -B | --sms-phone-numbers | SMS_PHONE_NUMBERS | A comma-separated list of phone numbers, e.g. `"189xxxxxxxx,132xxxxxxxx"` | -| -L | --sms-listen-addr | SMS_LISTEN_ADDR | Built-in SMS webhook listener address, default is `127.0.0.1:9100` | Suppose you start a TDengine database on host `tdengine` with HTTP API port `6041`, user `root1`, and password `pass5ord`. Execute the script. @@ -166,24 +151,10 @@ Use the `uid` value obtained above as `-E` input. sudo ./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord -E existing-notifier ``` -If you want to use the [Alibaba Cloud SMS](https://www.aliyun.com/product/sms) service as a notification channel, you should enable it with the `-s` flag add the following parameters. - -- `-N`: Notification Channel name, default is `TDinsight Builtin SMS`. -- `-U`: Channel uid, default is lowercase of `name`, any other character is replaced with -, for the default `-N`, its uid is `tdinsight-builtin-sms`. -- `-I`: Alibaba Cloud SMS access key id. -- `-K`: Alibaba Cloud SMS access secret key. -- `-S`: Alibaba Cloud SMS signature. -- `-C`: Alibaba Cloud SMS template id. -- `-T`: Alibaba Cloud SMS template parameters, for JSON format template, example is as follows `'{"alarm_level":"%s", "time":"%s", "name":"%s", "content":"%s"}'`. There are four parameters: alarm level, time, name and alarm content. -- `-B`: a list of phone numbers, separated by a comma `,`. - If you want to monitor multiple TDengine clusters, you need to set up numerous TDinsight dashboards. Setting up non-default TDinsight requires some changes: the `-n` `-i` `-t` options need to be changed to non-default names, and `-N` and `-L` should also be changed if using the built-in SMS alerting feature. ```bash sudo . /TDengine.sh -n TDengine-Env1 -a http://another:6041 -u root -p taosdata -i tdinsight-env1 -t 'TDinsight Env1' -# If using built-in SMS notifications -sudo . /TDengine.sh -n TDengine-Env1 -a http://another:6041 -u root -p taosdata -i tdinsight-env1 -t 'TDinsight Env1' \ - -s -N 'Env1 SMS' -I xx -K xx -S xx -C SMS_XX -T '' -B 00000000000 -L 127.0.0.01:10611 ``` Please note that the configuration data source, notification channel, and dashboard are not changeable on the front end. You should update the configuration again via this script or manually change the configuration file in the `/etc/grafana/provisioning` directory (this is the default directory for Grafana, use the `-P` option to change it as needed). @@ -249,21 +220,23 @@ Save and test. It will report 'TDengine Data source is working' under normal cir ### Importing dashboards -Point to **+** / **Create** - **import** (or `/dashboard/import` url). +In the page of configuring data source, click **Dashboards** tab. ![TDengine Database TDinsight Import Dashboard and Configuration](./assets/import_dashboard.webp) -Type the dashboard ID `15167` in the **Import via grafana.com** location and **Load**. +Choose `TDengine for 3.x` and click `import`. -![TDengine Database TDinsight Import via grafana.com](./assets/import-dashboard-15167.webp) +After the importing is done, `TDinsight for 3.x` dashboard is available on the page of `search dashboards by name`. -Once the import is complete, the full page view of TDinsight is shown below. +![TDengine Database TDinsight Import via grafana.com](./assets/import_dashboard_view.webp) -![TDengine Database TDinsight show](./assets/TDinsight-full.webp) +In the `TDinsight for 3.x` dashboard, choose the database used by taosKeeper to store monitoring data, you can see the monitoring result. + +![TDengine Database TDinsight 选择数据库](./assets/select_dashboard_db.webp) ## TDinsight dashboard details -The TDinsight dashboard is designed to provide the usage and status of TDengine-related resources [dnodes, mnodes, vnodes](../../taos-sql/node/) or databases. +The TDinsight dashboard is designed to provide the usage and status of TDengine-related resources, e.g. dnodes, mnodes, vnodes and databases. Details of the metrics are as follows. @@ -285,7 +258,6 @@ This section contains the current information and status of the cluster, the ale - **Measuring Points Used**: The number of measuring points used to enable the alert rule (no data available in the community version, healthy by default). - **Grants Expire Time**: the expiration time of the enterprise version of the enabled alert rule (no data available for the community version, healthy by default). - **Error Rate**: Aggregate error rate (average number of errors per second) for alert-enabled clusters. -- **Variables**: `show variables` table display. ### DNodes Status @@ -294,7 +266,6 @@ This section contains the current information and status of the cluster, the ale - **DNodes Status**: simple table view of `show dnodes`. - **DNodes Lifetime**: the time elapsed since the dnode was created. - **DNodes Number**: the number of DNodes changes. -- **Offline Reason**: if any dnode status is offline, the reason for offline is shown as a pie chart. ### MNode Overview @@ -309,7 +280,6 @@ This section contains the current information and status of the cluster, the ale 1. **Requests Rate(Inserts per Second)**: average number of inserts per second. 2. **Requests (Selects)**: number of query requests and change rate (count of second). -3. **Requests (HTTP)**: number of HTTP requests and request rate (count of second). ### Database @@ -319,9 +289,8 @@ Database usage, repeated for each value of the variable `$database` i.e. multipl 1. **STables**: number of super tables. 2. **Total Tables**: number of all tables. -3. **Sub Tables**: the number of all super table subtables. -4. **Tables**: graph of all normal table numbers over time. -5. **Tables Number Foreach VGroups**: The number of tables contained in each VGroups. +3. **Tables**: number of normal tables. +4. **Table number for each vgroup**: number of tables per vgroup. ### DNode Resource Usage @@ -356,12 +325,11 @@ Currently, only the number of logins per minute is reported. Support monitoring taosAdapter request statistics and status details. Includes. -1. **http_request**: contains the total number of requests, the number of failed requests, and the number of requests being processed -2. **top 3 request endpoint**: data of the top 3 requests by endpoint group -3. **Memory Used**: taosAdapter memory usage -4. **latency_quantile(ms)**: quantile of (1, 2, 5, 9, 99) stages -5. **top 3 failed request endpoint**: data of the top 3 failed requests by endpoint grouping -6. **CPU Used**: taosAdapter CPU usage +1. **http_request_inflight**: number of real-time requests. +2. **http_request_total**: number of total requests. +3. **http_request_fail**: number of failed requets. +4. **CPU Used**: CPU usage of taosAdapter. +5. **Memory Used**: Memory usage of taosAdapter. ## Upgrade @@ -403,13 +371,6 @@ services: TDENGINE_API: ${TDENGINE_API} TDENGINE_USER: ${TDENGINE_USER} TDENGINE_PASS: ${TDENGINE_PASS} - SMS_ACCESS_KEY_ID: ${SMS_ACCESS_KEY_ID} - SMS_ACCESS_KEY_SECRET: ${SMS_ACCESS_KEY_SECRET} - SMS_SIGN_NAME: ${SMS_SIGN_NAME} - SMS_TEMPLATE_CODE: ${SMS_TEMPLATE_CODE} - SMS_TEMPLATE_PARAM: '${SMS_TEMPLATE_PARAM}' - SMS_PHONE_NUMBERS: $SMS_PHONE_NUMBERS - SMS_LISTEN_ADDR: ${SMS_LISTEN_ADDR} ports: - 3000:3000 volumes: From e6512296dad1277423ed049a7c164a2fa90c9198 Mon Sep 17 00:00:00 2001 From: gccgdb1234 Date: Thu, 15 Sep 2022 16:38:41 +0800 Subject: [PATCH 49/50] doc: change 10-monitor.md of English version --- docs/en/13-operation/10-monitor.md | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/docs/en/13-operation/10-monitor.md b/docs/en/13-operation/10-monitor.md index a4679983f2..74a5564a2a 100644 --- a/docs/en/13-operation/10-monitor.md +++ b/docs/en/13-operation/10-monitor.md @@ -2,7 +2,7 @@ title: TDengine Monitoring --- -After TDengine is started, a database named `log` is created automatically to help with monitoring. Information that includes CPU, memory and disk usage, bandwidth, number of requests, disk I/O speed, slow queries, is written into the `log` database at a predefined interval. Additionally, some important system operations, like logon, create user, drop database, and alerts and warnings generated in TDengine are written into the `log` database too. A system operator can view the data in `log` database from TDengine CLI or from a web console. +After TDengine is started, it automatically writes monitoring data including CPU, memory and disk usage, bandwidth, number of requests, disk I/O speed, slow queries, into a designated database at a predefined interval through taosKeeper. Additionally, some important system operations, like logon, create user, drop database, and alerts and warnings generated in TDengine are written into the `log` database too. A system operator can view the data in `log` database from TDengine CLI or from a web console. The collection of the monitoring information is enabled by default, but can be disabled by parameter `monitor` in the configuration file. @@ -10,7 +10,7 @@ The collection of the monitoring information is enabled by default, but can be d TDinsight is a complete solution which uses the monitoring database `log` mentioned previously, and Grafana, to monitor a TDengine cluster. -From version 2.3.3.0, more monitoring data has been added in the `log` database. Please refer to [TDinsight Grafana Dashboard](https://grafana.com/grafana/dashboards/15167) to learn more details about using TDinsight to monitor TDengine. +Please refer to [TDinsight Grafana Dashboard](../../reference/tdinsight) to learn more details about using TDinsight to monitor TDengine. A script `TDinsight.sh` is provided to deploy TDinsight automatically. @@ -30,31 +30,14 @@ Prepare: 2. Grafana Alert Notification -There are two ways to setup Grafana alert notification. +You can use below command to setup Grafana alert notification. -- An existing Grafana Notification Channel can be specified with parameter `-E`, the notifier uid of the channel can be obtained by `curl -u admin:admin localhost:3000/api/alert-notifications |jq` +An existing Grafana Notification Channel can be specified with parameter `-E`, the notifier uid of the channel can be obtained by `curl -u admin:admin localhost:3000/api/alert-notifications |jq` ```bash sudo ./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -E ``` -- The AliCloud SMS alert built in TDengine data source plugin can be enabled with parameter `-s`, the parameters of enabling this plugin are listed below: - - - `-I`: AliCloud SMS Key ID - - `-K`: AliCloud SMS Key Secret - - `-S`: AliCloud SMS Signature - - `-C`: SMS notification template - - `-T`: Input parameters in JSON format for the SMS notification template, for example`{"alarm_level":"%s","time":"%s","name":"%s","content":"%s"}` - - `-B`: List of mobile numbers to be notified - - Below is an example of the full command using the AliCloud SMS alert. - - ```bash - sudo ./TDinsight.sh -a http://localhost:6041 -u root -p taosdata -s \ - -I XXXXXXX -K XXXXXXXX -S taosdata -C SMS_1111111 -B 18900000000 \ - -T '{"alarm_level":"%s","time":"%s","name":"%s","content":"%s"}' - ``` - Launch `TDinsight.sh` with the command above and restart Grafana, then open Dashboard `http://localhost:3000/d/tdinsight`. For more use cases and restrictions please refer to [TDinsight](/reference/tdinsight/). From f8bc0693c028e7501e0e1ea28531b4fecf112f27 Mon Sep 17 00:00:00 2001 From: gccgdb1234 Date: Thu, 15 Sep 2022 16:43:41 +0800 Subject: [PATCH 50/50] doc: fix broken links --- docs/en/14-reference/07-tdinsight/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/14-reference/07-tdinsight/index.md b/docs/en/14-reference/07-tdinsight/index.md index ebde820828..d03c16a8bc 100644 --- a/docs/en/14-reference/07-tdinsight/index.md +++ b/docs/en/14-reference/07-tdinsight/index.md @@ -11,8 +11,8 @@ After TDengine starts, it automatically writes many metrics in specific interval To deploy TDinsight, we need - a single-node TDengine server or a multi-node TDengine cluster and a [Grafana] server are required. This dashboard requires TDengine 3.0.1.0 and above, with the monitoring feature enabled. For detailed configuration, please refer to [TDengine monitoring configuration](../config/#monitoring-parameters). -- taosAdapter has been instaleld and running, please refer to [taosAdapter](../../taosadapter). -- taosKeeper has been installed and running, please refer to [taosKeeper](../../taoskeeper). +- taosAdapter has been instaleld and running, please refer to [taosAdapter](../taosadapter). +- taosKeeper has been installed and running, please refer to [taosKeeper](../taoskeeper). Please record - The endpoint of taosAdapter REST service, for example `http://tdengine.local:6041`