From 17a65430cda200c871086b4c25af4c48bbe52dde Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 22 Mar 2024 18:42:54 +0800 Subject: [PATCH 01/32] fix(tsdb): remove assert --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 5 +++++ source/dnode/vnode/src/tsdb/tsdbReadUtil.c | 3 +-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index b05ce0680b..cda8330282 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -3101,6 +3101,7 @@ static void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter) SFileBlockDumpInfo* pDumpInfo = &pStatus->fBlockDumpInfo; if (pBlockInfo) { + // todo handle // STableBlockScanInfo* pScanInfo = tSimpleHashGet(pBlockIter->pTableMap, &pBlockInfo->uid, sizeof(pBlockInfo->uid)); // if (pScanInfo) { // tsdbRowKeyAssign(&pDumpInfo->lastKey, &pScanInfo->lastProcKey); @@ -4666,9 +4667,13 @@ int32_t tsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) { tsdbReleaseReader(pReader); } + tsdbReaderSuspend2(pReader); + tsdbReaderResume2(pReader); + return code; } + if (pReader->step == EXTERNAL_ROWS_MAIN && pReader->innerReader[1] != NULL) { // prepare for the next row scan int32_t step = -1; diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c index c7077a2e71..93bc5ca573 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c @@ -229,8 +229,7 @@ void resetAllDataBlockScanInfo(SSHashObj* pTableMap, int64_t ts, int32_t step) { pInfo->delSkyline = taosArrayDestroy(pInfo->delSkyline); pInfo->lastProcKey.ts = ts; - ASSERT(0); - + // todo check the nextProcKey info pInfo->sttKeyInfo.nextProcKey = ts + step; } } From c35e834141d722d3f4162ed5684eecea3f5c5442 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 23 Mar 2024 00:11:21 +0800 Subject: [PATCH 02/32] fix(tsdb): fix error. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 44 +++++++++++++++---------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index cda8330282..7cd624d7c7 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -148,6 +148,7 @@ static void tRowGetKeyDeepCopy(SRow* pRow, SRowKey* pKey) { } SPrimaryKeyIndex indices[TD_MAX_PK_COLS]; + ASSERT(pKey->numOfPKs <= TD_MAX_PK_COLS); uint8_t *data = pRow->data; for (int32_t i = 0; i < pRow->numOfPKs; i++) { @@ -686,13 +687,14 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN STableBlockScanInfo* pScanInfo = getTableBlockScanInfo(pReader->status.pTableMap, uid, pReader->idStr); // todo: here we should find the first timestamp that is greater than the lastProcKey + // the window is an open interval NOW. if (asc) { - w.skey = pScanInfo->lastProcKey.ts + step; + w.skey = pScanInfo->lastProcKey.ts; } else { - w.ekey = pScanInfo->lastProcKey.ts + step; + w.ekey = pScanInfo->lastProcKey.ts; } - if (isEmptyQueryTimeWindow(&w)) { + if (/*isEmptyQueryTimeWindow(&w)*/ w.ekey - w.skey < 2) { // NOTE: specialized for open interval k += 1; if (k >= numOfTables) { @@ -707,7 +709,11 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN continue; } - // 2. version range check + if (pkCompEx(pReader->pkComparFn, &pRecord->lastKey.key, &pScanInfo->lastProcKey) <= 0) { + continue; + } + + // 2. version range check, version range is an CLOSED interval if (pRecord->minVer > pReader->info.verRange.maxVer || pRecord->maxVer < pReader->info.verRange.minVer) { continue; } @@ -724,6 +730,7 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN if (pScanInfo->filesetWindow.skey > pRecord->firstKey.key.ts) { pScanInfo->filesetWindow.skey = pRecord->firstKey.key.ts; } + if (pScanInfo->filesetWindow.ekey < pRecord->lastKey.key.ts) { pScanInfo->filesetWindow.ekey = pRecord->lastKey.key.ts; } @@ -1637,9 +1644,11 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* __compar_fn_t compFn = pReader->pkComparFn; int32_t pkSrcSlot = pReader->suppInfo.pkSrcSlot; - SRowKey* pSttKey = NULL; + SRowKey* pSttKey = &(SRowKey){0}; if (hasDataInSttBlock(pBlockScanInfo) && (!pBlockScanInfo->cleanSttBlocks)) { - pSttKey = getCurrentKeyInSttBlock(pSttBlockReader); + tRowKeyAssign(pSttKey, getCurrentKeyInSttBlock(pSttBlockReader)); + } else { + pSttKey = NULL; } SRowKey k; @@ -1675,21 +1684,21 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo* if (pReader->info.order == TSDB_ORDER_ASC) { minKey = k; // chosen the minimum value - if (pkCompEx(compFn, pfKey, &minKey) < 0) { + if (pfKey != NULL && pkCompEx(compFn, pfKey, &minKey) < 0) { minKey = *pfKey; } - if (pkCompEx(compFn, pSttKey, &minKey) < 0) { + if (pSttKey != NULL && pkCompEx(compFn, pSttKey, &minKey) < 0) { minKey = *pSttKey; } } else { minKey = k; - if (pkCompEx(compFn, pfKey, &minKey) > 0) { + if (pfKey != NULL && pkCompEx(compFn, pfKey, &minKey) > 0) { minKey = *pfKey; } - if (pkCompEx(compFn, pSttKey, &minKey) > 0) { + if (pSttKey != NULL && pkCompEx(compFn, pSttKey, &minKey) > 0) { minKey = *pSttKey; } } @@ -1888,7 +1897,7 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* minKey = ik; } - if (hasDataInFileBlock(pBlockData, pDumpInfo) && (pkCompEx(compFn, pfKey, &minKey) < 0)) { + if (pfKey != NULL && (pkCompEx(compFn, pfKey, &minKey) < 0)) { minKey = *pfKey; } @@ -1901,7 +1910,7 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* minKey = ik; } - if (hasDataInFileBlock(pBlockData, pDumpInfo) && (pkCompEx(compFn, pfKey, &minKey) > 0)) { + if (pfKey != NULL && (pkCompEx(compFn, pfKey, &minKey) > 0)) { minKey = *pfKey; } @@ -3659,7 +3668,7 @@ int32_t doMergeMemTableMultiRows(TSDBROW* pRow, SRowKey* pKey, uint64_t uid, SIt SRowKey nextRowKey = {0}; tRowGetKeyEx(pNextRow, &nextRowKey); - if (pkCompEx(pReader->pkComparFn, pKey, &nextRowKey) != 0) { + if (pKey->numOfPKs > 0 && pkCompEx(pReader->pkComparFn, pKey, &nextRowKey) != 0) { *pResRow = current; *freeTSRow = false; return TSDB_CODE_SUCCESS; @@ -3966,6 +3975,9 @@ int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t e if (row.type == TSDBROW_ROW_FMT) { code = doAppendRowFromTSRow(pBlock, pReader, row.pTSRow, pBlockScanInfo); + if (code == TSDB_CODE_SUCCESS) { + tRowGetKeyDeepCopy(row.pTSRow, &pBlockScanInfo->lastProcKey); + } if (freeTSRow) { taosMemoryFree(row.pTSRow); @@ -3974,8 +3986,6 @@ int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t e if (code) { return code; } - - tRowGetKeyDeepCopy(row.pTSRow, &pBlockScanInfo->lastProcKey); } else { code = doAppendRowFromFileBlock(pBlock, pReader, row.pBlockData, row.iRow); if (code) { @@ -4667,8 +4677,8 @@ int32_t tsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) { tsdbReleaseReader(pReader); } - tsdbReaderSuspend2(pReader); - tsdbReaderResume2(pReader); +// tsdbReaderSuspend2(pReader); +// tsdbReaderResume2(pReader); return code; } From 447b8ddd32c5ba8002f8daf84efc43a05b2ff311 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 23 Mar 2024 23:33:40 +0800 Subject: [PATCH 03/32] fix(tsdb): remove invalid assert. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 7cd624d7c7..731442af67 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -3628,7 +3628,6 @@ int32_t doMergeRowsInSttBlock(SSttBlockReader* pSttBlockReader, STableBlockScanI TSDBROW* pRow1 = tMergeTreeGetRow(&pSttBlockReader->mergeTree); tsdbRowMergerAdd(pMerger, pRow1, NULL); } else { - ASSERT(ret < 0); tsdbTrace("uid:%" PRIu64 " last del index:%d, del range:%d, lastKeyInStt:%" PRId64 ", %s", pScanInfo->uid, pScanInfo->sttBlockDelIndex, (int32_t)taosArrayGetSize(pScanInfo->delSkyline), pScanInfo->sttKeyInfo.nextProcKey, idStr); From f9a6243859032e210f9b927abea175a683604096 Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 25 Mar 2024 09:38:50 +0800 Subject: [PATCH 04/32] fix: add pk col after ts col to make operator of show table distributed super_table work --- source/libs/planner/src/planLogicCreater.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index c1793bfb90..c79fbd01f0 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -341,10 +341,11 @@ static int32_t addDefaultScanCol(const STableMeta* pMeta, SNodeList** pCols) { if (TSDB_SYSTEM_TABLE == pMeta->tableType) { return addSystableFirstCol(pMeta->uid, pMeta->schema, pCols, pMeta); } - if (hasPkInTable(pMeta)) { - addPkCol(pMeta->uid, pMeta->schema + 1, pCols, pMeta); + int32_t code = addPrimaryKeyCol(pMeta->uid, pMeta->schema, pCols, pMeta); + if (code == TSDB_CODE_SUCCESS && hasPkInTable(pMeta)) { + code = addPkCol(pMeta->uid, pMeta->schema + 1, pCols, pMeta); } - return addPrimaryKeyCol(pMeta->uid, pMeta->schema, pCols, pMeta); + return code; } static int32_t makeScanLogicNode(SLogicPlanContext* pCxt, SRealTableNode* pRealTable, bool hasRepeatScanFuncs, From 073e4d838916cc0450220d6585a79c9ad3f7c986 Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 25 Mar 2024 09:48:54 +0800 Subject: [PATCH 05/32] fix: increase last_row result size since SFirstLastRes has pk info --- tests/script/tsim/query/cache_last.sim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/script/tsim/query/cache_last.sim b/tests/script/tsim/query/cache_last.sim index 65eb46de69..50199117b0 100644 --- a/tests/script/tsim/query/cache_last.sim +++ b/tests/script/tsim/query/cache_last.sim @@ -89,7 +89,7 @@ if $data10 != @ -> Merge (columns=3 width=24 input_order=unknown output_order= return -1 endi sql explain select count(*), last_row(f1), min(f1) from sta interval(1s); -if $data10 != @ -> Merge (columns=4 width=66 input_order=asc output_order=asc mode=sort)@ then +if $data10 != @ -> Merge (columns=4 width=82 input_order=asc output_order=asc mode=sort)@ then return -1 endi sql explain select distinct count(*), last_row(f1), min(f1) from tba1; From 75d6b1edde9d09aceb04d1c30948057169465453 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 25 Mar 2024 09:59:10 +0800 Subject: [PATCH 06/32] fix(tsdb): fix the bug caused by sttKey changing. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 731442af67..6e134698b5 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -1801,6 +1801,7 @@ static int32_t mergeFileBlockAndSttBlock(STsdbReader* pReader, SSttBlockReader* } } + // pKey == pSttKey tRowKeyAssign(&pBlockScanInfo->lastProcKey, pKey); // the following for key == sttKey->key.ts @@ -1819,7 +1820,8 @@ static int32_t mergeFileBlockAndSttBlock(STsdbReader* pReader, SSttBlockReader* return code; } - doMergeRowsInSttBlock(pSttBlockReader, pBlockScanInfo, pSttKey, pMerger, pkSrcSlot, &pReader->info.verRange, + // pSttKey will be changed when sttBlockReader iterates to the next row, so use pKey instead. + doMergeRowsInSttBlock(pSttBlockReader, pBlockScanInfo, pKey, pMerger, pkSrcSlot, &pReader->info.verRange, pReader->idStr); code = tsdbRowMergerGetRow(pMerger, &pTSRow); @@ -4675,10 +4677,6 @@ int32_t tsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) { qTrace("tsdb/read: %p, unlock read mutex", pReader); tsdbReleaseReader(pReader); } - -// tsdbReaderSuspend2(pReader); -// tsdbReaderResume2(pReader); - return code; } @@ -4904,6 +4902,8 @@ SSDataBlock* tsdbRetrieveDataBlock2(STsdbReader* pReader, SArray* pIdList) { qTrace("tsdb/read-retrieve: %p, unlock read mutex", pReader); tsdbReleaseReader(pReader); +// tsdbReaderSuspend2(pReader); +// tsdbReaderResume2(pReader); return ret; } From 9d2c310616aeb6ce7930968c3eea06eac9905533 Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 25 Mar 2024 10:15:50 +0800 Subject: [PATCH 07/32] fix: remove the extract space after column type for none pk column --- source/libs/command/src/command.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/source/libs/command/src/command.c b/source/libs/command/src/command.c index 2136ef7d6d..dc8fa49e27 100644 --- a/source/libs/command/src/command.c +++ b/source/libs/command/src/command.c @@ -501,8 +501,12 @@ void appendColumnFields(char* buf, int32_t* len, STableCfg* pCfg) { } else if (TSDB_DATA_TYPE_NCHAR == pSchema->type) { sprintf(type + strlen(type), "(%d)", (int32_t)((pSchema->bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE)); } - char* pk = (pSchema->flags & COL_IS_KEY) ? "PRIMARY KEY" : ""; - *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s %s", ((i > 0) ? ", " : ""), pSchema->name, type, pk); + if (!(pSchema->flags & COL_IS_KEY)) { + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s", ((i > 0) ? ", " : ""), pSchema->name, type); + } else { + char* pk = "PRIMARY KEY"; + *len += sprintf(buf + VARSTR_HEADER_SIZE + *len, "%s`%s` %s %s", ((i > 0) ? ", " : ""), pSchema->name, type, pk); + } } } From 4d3eb6824c5444b4c83dec982f27167687e87d4a Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 25 Mar 2024 13:38:34 +0800 Subject: [PATCH 08/32] feat: add pk support for last/first/last_row dynDataRequired --- include/libs/function/functionMgt.h | 2 +- source/common/src/tdatablock.c | 4 +- source/libs/executor/src/scanoperator.c | 2 +- source/libs/function/inc/builtins.h | 2 +- source/libs/function/inc/builtinsimpl.h | 4 +- source/libs/function/src/builtinsimpl.c | 50 ++++++++++++++++++++++--- source/libs/function/src/functionMgt.c | 4 +- 7 files changed, 53 insertions(+), 15 deletions(-) diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index f126bb587a..72e2815ade 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -256,7 +256,7 @@ typedef enum EFuncDataRequired { } EFuncDataRequired; EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow); -EFuncDataRequired fmFuncDynDataRequired(int32_t funcId, void* pRes, STimeWindow* pTimeWindow); +EFuncDataRequired fmFuncDynDataRequired(int32_t funcId, void* pRes, SDataBlockInfo* pBlockInfo); int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet); int32_t fmGetScalarFuncExecFuncs(int32_t funcId, SScalarFuncExecFuncs* pFpSet); diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 0d805cb8a4..d2164b024b 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -546,8 +546,8 @@ int32_t blockDataUpdatePkRange(SSDataBlock* pDataBlock, int32_t pkColumnIndex, b } } else { if (IS_NUMERIC_TYPE(pColInfoData->info.type)) { - pDataBlock->info.pks[0].val = *(int64_t*) ekey; - pDataBlock->info.pks[1].val = *(int64_t*) skey; + pDataBlock->info.pks[0].val = *(int32_t*) ekey; + pDataBlock->info.pks[1].val = *(int32_t*) skey; } else { // todo refactor memcpy(pDataBlock->info.pks[0].pData, varDataVal(ekey), varDataLen(ekey)); pDataBlock->info.pks[0].nData = varDataLen(ekey); diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 1e5fa065de..a51e627272 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -201,7 +201,7 @@ static int32_t doDynamicPruneDataBlock(SOperatorInfo* pOperator, SDataBlockInfo* SResultRowEntryInfo* pEntry = getResultEntryInfo(pRow, i, pTableScanInfo->base.pdInfo.pExprSup->rowEntryInfoOffset); - int32_t reqStatus = fmFuncDynDataRequired(functionId, pEntry, &pBlockInfo->window); + int32_t reqStatus = fmFuncDynDataRequired(functionId, pEntry, pBlockInfo); if (reqStatus != FUNC_DATA_REQUIRED_NOT_LOAD) { notLoadBlock = false; break; diff --git a/source/libs/function/inc/builtins.h b/source/libs/function/inc/builtins.h index 4c1e46dbba..af33c3ffa2 100644 --- a/source/libs/function/inc/builtins.h +++ b/source/libs/function/inc/builtins.h @@ -25,7 +25,7 @@ extern "C" { typedef int32_t (*FTranslateFunc)(SFunctionNode* pFunc, char* pErrBuf, int32_t len); typedef EFuncDataRequired (*FFuncDataRequired)(SFunctionNode* pFunc, STimeWindow* pTimeWindow); typedef int32_t (*FCreateMergeFuncParameters)(SNodeList* pRawParameters, SNode* pPartialRes, SNodeList** pParameters); -typedef EFuncDataRequired (*FFuncDynDataRequired)(void* pRes, STimeWindow* pTimeWindow); +typedef EFuncDataRequired (*FFuncDynDataRequired)(void* pRes, SDataBlockInfo* pBlocInfo); typedef EFuncReturnRows (*FEstimateReturnRows)(SFunctionNode* pFunc); typedef struct SBuiltinFuncDefinition { diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index ccb50ff2a8..54bcd26bc3 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -158,8 +158,8 @@ int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pB int32_t firstCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx); int32_t lastCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx); int32_t getFirstLastInfoSize(int32_t resBytes, int32_t pkBytes); -EFuncDataRequired firstDynDataReq(void* pRes, STimeWindow* pTimeWindow); -EFuncDataRequired lastDynDataReq(void* pRes, STimeWindow* pTimeWindow); +EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo); +EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo); int32_t lastRowFunction(SqlFunctionCtx* pCtx); diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 097b263b8e..83f9dcff08 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -2290,7 +2290,31 @@ int32_t apercentileCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) return TSDB_CODE_SUCCESS; } -EFuncDataRequired firstDynDataReq(void* pRes, STimeWindow* pTimeWindow) { +// TODO: change this function when block data info pks changed +static int32_t comparePkDataWithSValue(int8_t pkType, char* pkData, SValue* pVal, int32_t order) { + char numVal[8] = {0}; + switch (pkType) { + case TSDB_DATA_TYPE_INT: + *(int32_t*)numVal = (int32_t)pVal->val; + break; + case TSDB_DATA_TYPE_UINT: + *(uint32_t*)numVal = (uint32_t)pVal->val; + break; + case TSDB_DATA_TYPE_BIGINT: + *(int64_t*)numVal = (int64_t)pVal->val; + break; + case TSDB_DATA_TYPE_UBIGINT: + *(uint64_t*)numVal = (uint64_t)pVal->val; + break; + default: + break; + } + char* blockData = (IS_NUMERIC_TYPE(pkType)) ? (char*) numVal : (char*)pVal->pData; + __compar_fn_t fn = getKeyComparFunc(pkType, order); + return fn(pkData, blockData); +} + +EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) { SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes; // not initialized yet, data is required @@ -2299,14 +2323,21 @@ EFuncDataRequired firstDynDataReq(void* pRes, STimeWindow* pTimeWindow) { } SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry); - if (pResult->hasResult && pResult->ts <= pTimeWindow->skey) { - return FUNC_DATA_REQUIRED_NOT_LOAD; + if (pResult->hasResult) { + if (pResult->ts < pBlockInfo->window.skey) { + return FUNC_DATA_REQUIRED_NOT_LOAD; + } else if (pResult->ts == pBlockInfo->window.skey && pResult->pkData) { + if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 0, TSDB_ORDER_ASC) < 0) { + return FUNC_DATA_REQUIRED_NOT_LOAD; + } + } + return FUNC_DATA_REQUIRED_DATA_LOAD; } else { return FUNC_DATA_REQUIRED_DATA_LOAD; } } -EFuncDataRequired lastDynDataReq(void* pRes, STimeWindow* pTimeWindow) { +EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) { SResultRowEntryInfo* pEntry = (SResultRowEntryInfo*)pRes; // not initialized yet, data is required @@ -2315,8 +2346,15 @@ EFuncDataRequired lastDynDataReq(void* pRes, STimeWindow* pTimeWindow) { } SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry); - if (pResult->hasResult && pResult->ts >= pTimeWindow->ekey) { - return FUNC_DATA_REQUIRED_NOT_LOAD; + if (pResult->hasResult) { + if (pResult->ts > pBlockInfo->window.ekey) { + return FUNC_DATA_REQUIRED_NOT_LOAD; + } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) { + if (comparePkDataWithSValue(pResult->pkType, pResult->pkData, pBlockInfo->pks + 1, TSDB_ORDER_DESC) < 0) { + return FUNC_DATA_REQUIRED_NOT_LOAD; + } + } + return FUNC_DATA_REQUIRED_DATA_LOAD; } else { return FUNC_DATA_REQUIRED_DATA_LOAD; } diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index ae3958647b..697efb63fd 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -115,7 +115,7 @@ EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWin return funcMgtBuiltins[pFunc->funcId].dataRequiredFunc(pFunc, pTimeWindow); } -EFuncDataRequired fmFuncDynDataRequired(int32_t funcId, void* pRes, STimeWindow* pTimeWindow) { +EFuncDataRequired fmFuncDynDataRequired(int32_t funcId, void* pRes, SDataBlockInfo* pBlockInfo) { if (fmIsUserDefinedFunc(funcId) || funcId < 0 || funcId >= funcMgtBuiltinsNum) { return TSDB_CODE_FAILED; } @@ -128,7 +128,7 @@ EFuncDataRequired fmFuncDynDataRequired(int32_t funcId, void* pRes, STimeWindow* if (funcMgtBuiltins[funcId].dynDataRequiredFunc == NULL) { return FUNC_DATA_REQUIRED_DATA_LOAD; } else { - return funcMgtBuiltins[funcId].dynDataRequiredFunc(pRes, pTimeWindow); + return funcMgtBuiltins[funcId].dynDataRequiredFunc(pRes, pBlockInfo); } } From 750ea5789f4246be2874d0ac305d7f65a0ed1af0 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 25 Mar 2024 14:20:46 +0800 Subject: [PATCH 09/32] fix(tsdb): fix errors identified by CI. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 69 +++++++++++++++++-------- source/dnode/vnode/src/tsdb/tsdbUtil.c | 2 +- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 6e134698b5..891fd823e7 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -141,7 +141,7 @@ static int32_t tGetPrimaryKeyIndex(uint8_t *p, SPrimaryKeyIndex *index) { } static void tRowGetKeyDeepCopy(SRow* pRow, SRowKey* pKey) { - pKey->ts = pKey->ts; + pKey->ts = pRow->ts; pKey->numOfPKs = pRow->numOfPKs; if (pKey->numOfPKs == 0) { return; @@ -164,7 +164,7 @@ static void tRowGetKeyDeepCopy(SRow* pRow, SRowKey* pKey) { pKey->pks[i].pData = memcpy(pKey->pks[i].pData, data + indices[i].offset, pKey->pks[i].nData); pKey->pks[i].pData += pKey->pks[i].nData; } else { - pKey->pks[i].val = *(int64_t*) data + indices[i].offset; + pKey->pks[i].val = *(int64_t*) (data + indices[i].offset); } } } @@ -694,7 +694,7 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN w.ekey = pScanInfo->lastProcKey.ts; } - if (/*isEmptyQueryTimeWindow(&w)*/ w.ekey - w.skey < 2) { // NOTE: specialized for open interval + if (/*isEmptyQueryTimeWindow(&w)*/ w.ekey - w.skey < 1) { // NOTE: specialized for open interval k += 1; if (k >= numOfTables) { @@ -2012,41 +2012,58 @@ int32_t doInitMemDataIter(STsdbReader* pReader, STbData** pData, STableBlockScan return code; } +static void doForwardDataIter(SRowKey* pKey, SIterInfo* pIter, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) { + SRowKey rowKey; + + while (1) { + TSDBROW* pRow = getValidMemRow(pIter, pBlockScanInfo->delSkyline, pReader); + if (!pIter->hasVal) { + break; + } + + tRowGetKeyEx(pRow, &rowKey); + int32_t ret = pkCompEx(pReader->pkComparFn, pKey, &rowKey); + if (ret == 0) { + pIter->hasVal = tsdbTbDataIterNext(pIter->iter); + } else { + break; + } + } +} + +// handle the open interval issue. Find the first row key that is greater than the given one. +static int32_t forwardDataIter(SRowKey* pKey, STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) { + doForwardDataIter(pKey, &pBlockScanInfo->iter, pBlockScanInfo, pReader); + doForwardDataIter(pKey, &pBlockScanInfo->iiter, pBlockScanInfo, pReader); + return TSDB_CODE_SUCCESS; +} + static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbReader* pReader) { + STbData* d = NULL; + STbData* di = NULL; + bool asc = ASCENDING_TRAVERSE(pReader->info.order); + STsdbReadSnap* pSnap = pReader->pReadSnap; + if (pBlockScanInfo->iterInit) { return TSDB_CODE_SUCCESS; } - STbData* d = NULL; STsdbRowKey startKey = {0}; - if (ASCENDING_TRAVERSE(pReader->info.order)) { - startKey = (STsdbRowKey){.version = pReader->info.verRange.minVer, - .key = { - .ts = pBlockScanInfo->lastProcKey.ts + 1, - .numOfPKs = pReader->suppInfo.numOfPks, - }}; - } else { - startKey = (STsdbRowKey){.version = pReader->info.verRange.maxVer, - .key = { - .ts = pBlockScanInfo->lastProcKey.ts - 1, - .numOfPKs = pReader->suppInfo.numOfPks, - }}; - } + tRowKeyAssign(&startKey.key, &pBlockScanInfo->lastProcKey); + startKey.version = asc ? pReader->info.verRange.minVer : pReader->info.verRange.maxVer; - int32_t code = - doInitMemDataIter(pReader, &d, pBlockScanInfo, &startKey, pReader->pReadSnap->pMem, &pBlockScanInfo->iter, "mem"); + int32_t code = doInitMemDataIter(pReader, &d, pBlockScanInfo, &startKey, pSnap->pMem, &pBlockScanInfo->iter, "mem"); if (code != TSDB_CODE_SUCCESS) { return code; } - STbData* di = NULL; - code = doInitMemDataIter(pReader, &di, pBlockScanInfo, &startKey, pReader->pReadSnap->pIMem, &pBlockScanInfo->iiter, - "imem"); + code = doInitMemDataIter(pReader, &di, pBlockScanInfo, &startKey, pSnap->pIMem, &pBlockScanInfo->iiter, "imem"); if (code != TSDB_CODE_SUCCESS) { return code; } loadMemTombData(&pBlockScanInfo->pMemDelData, d, di, pReader->info.verRange.maxVer); + forwardDataIter(&startKey.key, pBlockScanInfo, pReader); pBlockScanInfo->iterInit = true; return TSDB_CODE_SUCCESS; @@ -4128,6 +4145,9 @@ int32_t tsdbReaderOpen2(void* pVnode, SQueryTableDataCond* pCond, void* pTableLi blockDataEnsureCapacity(pResBlock, capacity); } + // for debug purpose +// capacity = 7; + int32_t code = tsdbReaderCreate(pVnode, pCond, ppReader, capacity, pResBlock, idstr); if (code != TSDB_CODE_SUCCESS) { goto _err; @@ -4894,6 +4914,10 @@ SSDataBlock* tsdbRetrieveDataBlock2(STsdbReader* pReader, SArray* pIdList) { SReaderStatus* pStatus = &pTReader->status; if (pStatus->composedDataBlock || pReader->info.execMode == READER_EXEC_ROWS) { + +// tsdbReaderSuspend2(pReader); +// tsdbReaderResume2(pReader); + return pTReader->resBlockInfo.pResBlock; } @@ -4904,6 +4928,7 @@ SSDataBlock* tsdbRetrieveDataBlock2(STsdbReader* pReader, SArray* pIdList) { // tsdbReaderSuspend2(pReader); // tsdbReaderResume2(pReader); + return ret; } diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index fe7a3457bd..59452ebb9d 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -633,7 +633,7 @@ int32_t tRowKeyAssign(SRowKey *pDst, SRowKey* pSrc) { pDst->numOfPKs = pSrc->numOfPKs; if (pSrc->numOfPKs > 0) { - for (int32_t i = 0; i < pDst->numOfPKs; ++i) { + for (int32_t i = 0; i < pSrc->numOfPKs; ++i) { SValue *pVal = &pDst->pks[i]; pVal->type = pSrc->pks[i].type; From a5ba546bd4d54a06913fdfb354e890a0e7717ca0 Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 25 Mar 2024 15:10:25 +0800 Subject: [PATCH 10/32] fix: add pk to funcInputGetNextRow --- include/libs/function/function.h | 5 ++- source/libs/function/src/builtinsimpl.c | 53 +++++++++++++++---------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 4ee0989118..78bd1d807b 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -185,6 +185,7 @@ typedef struct SFuncInputRow { TSKEY ts; bool isDataNull; char* pData; + char* pPk; SSDataBlock* block; // prev row block or src block int32_t rowIndex; // prev row block ? 0 : rowIndex in srcBlock @@ -198,7 +199,8 @@ typedef struct SFuncInputRowIter { bool hasPrev; SInputColumnInfoData* pInput; - SColumnInfoData* pData; + SColumnInfoData* pDataCol; + SColumnInfoData* pPkCol; TSKEY* tsList; int32_t rowIndex; int32_t inputEndIndex; @@ -207,6 +209,7 @@ typedef struct SFuncInputRowIter { TSKEY prevBlockTsEnd; bool prevIsDataNull; char* pPrevData; + char* pPrevPk; SSDataBlock* pPrevRowBlock; // pre one row block //TODO: diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 83f9dcff08..2907c096fe 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -424,7 +424,8 @@ int32_t funcInputUpdate(SqlFunctionCtx* pCtx) { if (!pCtx->bInputFinished) { pIter->pInput = &pCtx->input; pIter->tsList = (TSKEY*)pIter->pInput->pPTS->pData; - pIter->pData = pIter->pInput->pData[0]; + pIter->pDataCol = pIter->pInput->pData[0]; + pIter->pPkCol = pIter->pInput->pPrimaryKey; pIter->rowIndex = pIter->pInput->startRowIndex; pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1; pIter->pSrcBlock = pCtx->pSrcBlock; @@ -454,10 +455,16 @@ bool funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) { if (pIter->prevBlockTsEnd == pIter->tsList[pIter->inputEndIndex]) { blockDataDestroy(pIter->pPrevRowBlock); pIter->pPrevRowBlock = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1); - pIter->prevIsDataNull = colDataIsNull_f(pIter->pData->nullbitmap, pIter->inputEndIndex); - pIter->pPrevData = taosMemoryMalloc(pIter->pData->info.bytes); - char* srcData = colDataGetData(pIter->pData, pIter->inputEndIndex); - memcpy(pIter->pPrevData, srcData, pIter->pData->info.bytes); + pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex); + + pIter->pPrevData = taosMemoryMalloc(pIter->pDataCol->info.bytes); + char* srcData = colDataGetData(pIter->pDataCol, pIter->inputEndIndex); + memcpy(pIter->pPrevData, srcData, pIter->pDataCol->info.bytes); + + pIter->pPrevPk = taosMemoryMalloc(pIter->pPkCol->info.bytes); + char* pkData = colDataGetData(pIter->pPkCol, pIter->inputEndIndex); + memcpy(pIter->pPrevPk, pkData, pIter->pPkCol->info.bytes); + pIter->pPrevRowBlock = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1); pIter->hasPrev = true; @@ -475,8 +482,9 @@ bool funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) { pRow->rowIndex = 0; } else { pRow->ts = pIter->tsList[idx - 1]; - pRow->isDataNull = colDataIsNull_f(pIter->pData->nullbitmap, idx - 1); - pRow->pData = colDataGetData(pIter->pData, idx - 1); + pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, idx - 1); + pRow->pData = colDataGetData(pIter->pDataCol, idx - 1); + pRow->pPk = colDataGetData(pIter->pPkCol, idx - 1); pRow->block = pIter->pSrcBlock; pRow->rowIndex = idx - 1; } @@ -492,20 +500,22 @@ bool funcInputGetNextRowDescPk(SFuncInputRowIter* pIter, SFuncInputRow* pRow) { ++idx; } pRow->ts = pIter->tsList[idx]; - pRow->isDataNull = colDataIsNull_f(pIter->pData->nullbitmap, idx); - pRow->pData = colDataGetData(pIter->pData, pIter->rowIndex); + pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, idx); + pRow->pData = colDataGetData(pIter->pDataCol, idx); + pRow->pPk = colDataGetData(pIter->pPkCol, idx); pRow->block = pIter->pSrcBlock; - pRow->rowIndex = idx; pIter->rowIndex = idx + 1; return true; } else { pIter->hasPrev = true; pIter->prevBlockTsEnd = tsEnd; - // TODO - pIter->prevIsDataNull = colDataIsNull_f(pIter->pData->nullbitmap, pIter->inputEndIndex); - pIter->pPrevData = taosMemoryMalloc(pIter->pData->info.bytes); - memcpy(pIter->pPrevData, colDataGetData(pIter->pData, pIter->inputEndIndex), pIter->pData->info.bytes); + pIter->prevIsDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->inputEndIndex); + pIter->pPrevData = taosMemoryMalloc(pIter->pDataCol->info.bytes); + memcpy(pIter->pPrevData, colDataGetData(pIter->pDataCol, pIter->inputEndIndex), pIter->pDataCol->info.bytes); + pIter->pPrevPk = taosMemoryMalloc(pIter->pPkCol->info.bytes); + memcpy(pIter->pPrevPk, colDataGetData(pIter->pPkCol, pIter->inputEndIndex), pIter->pPkCol->info.bytes); + pIter->pPrevRowBlock = blockDataExtractBlock(pIter->pSrcBlock, pIter->inputEndIndex, 1); return false; } @@ -523,8 +533,9 @@ bool funcInputGetNextRowAscPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) { ++idx; } pRow->ts = pIter->tsList[idx]; - pRow->isDataNull = colDataIsNull_f(pIter->pData->nullbitmap, idx); - pRow->pData = colDataGetData(pIter->pData, idx); + pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, idx); + pRow->pData = colDataGetData(pIter->pDataCol, idx); + pRow->pPk = colDataGetData(pIter->pPkCol, idx); pRow->block = pIter->pSrcBlock; pRow->rowIndex = idx; @@ -535,8 +546,9 @@ bool funcInputGetNextRowAscPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) { } else { if (pIter->rowIndex <= pIter->inputEndIndex) { pRow->ts = pIter->tsList[pIter->rowIndex]; - pRow->isDataNull = colDataIsNull_f(pIter->pData->nullbitmap, pIter->rowIndex); - pRow->pData = colDataGetData(pIter->pData, pIter->rowIndex); + pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->rowIndex); + pRow->pData = colDataGetData(pIter->pDataCol, pIter->rowIndex); + pRow->pPk = colDataGetData(pIter->pPkCol, pIter->rowIndex); pRow->block = pIter->pSrcBlock; pRow->rowIndex = pIter->rowIndex; @@ -563,8 +575,9 @@ bool funcInputGetNextRowAscPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) { bool funcInputGetNextRowNoPk(SFuncInputRowIter *pIter, SFuncInputRow* pRow) { if (pIter->rowIndex <= pIter->inputEndIndex) { pRow->ts = pIter->tsList[pIter->rowIndex]; - pRow->isDataNull = colDataIsNull_f(pIter->pData->nullbitmap, pIter->rowIndex); - pRow->pData = colDataGetData(pIter->pData, pIter->rowIndex); + pRow->isDataNull = colDataIsNull_f(pIter->pDataCol->nullbitmap, pIter->rowIndex); + pRow->pData = colDataGetData(pIter->pDataCol, pIter->rowIndex); + pRow->pPk = NULL; pRow->block = pIter->pSrcBlock; pRow->rowIndex = pIter->rowIndex; From 5c729cc836f2d9eac23bceb83c9b26c43dd541a4 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Mon, 25 Mar 2024 17:57:59 +0800 Subject: [PATCH 11/32] refactor: do some internal refactor. --- source/dnode/vnode/src/inc/tsdb.h | 6 +- source/dnode/vnode/src/tsdb/tsdbMergeTree.c | 37 ++++++++++-- source/dnode/vnode/src/tsdb/tsdbRead2.c | 62 ++++++++++++++------- source/dnode/vnode/src/tsdb/tsdbReadUtil.c | 47 +++++++++++----- source/dnode/vnode/src/tsdb/tsdbReadUtil.h | 5 +- 5 files changed, 117 insertions(+), 40 deletions(-) diff --git a/source/dnode/vnode/src/inc/tsdb.h b/source/dnode/vnode/src/inc/tsdb.h index 2b806e95a5..761e74b9cf 100644 --- a/source/dnode/vnode/src/inc/tsdb.h +++ b/source/dnode/vnode/src/inc/tsdb.h @@ -836,6 +836,8 @@ struct SLDataIter { STimeWindow timeWindow; SVersionRange verRange; SSttBlockLoadInfo *pBlockLoadInfo; + SRowKey startRowKey; // current row key + __compar_fn_t comparFn; bool ignoreEarlierTs; struct SSttFileReader *pReader; }; @@ -846,7 +848,7 @@ struct SSttFileReader; typedef int32_t (*_load_tomb_fn)(STsdbReader *pReader, struct SSttFileReader *pSttFileReader, SSttBlockLoadInfo *pLoadInfo); -typedef struct { +typedef struct SMergeTreeConf { int8_t backward; STsdb *pTsdb; uint64_t suid; @@ -859,7 +861,9 @@ typedef struct { STSchema *pSchema; int16_t *pCols; int32_t numOfCols; + SRowKey *pCurRowKey; _load_tomb_fn loadTombFn; + __compar_fn_t comparFn; void *pReader; void *idstr; bool rspRows; // response the rows in stt-file, if possible diff --git a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c index 61c610538e..97194acb00 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c +++ b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c @@ -479,6 +479,9 @@ int32_t tLDataIterOpen2(SLDataIter *pIter, SSttFileReader *pSttFileReader, int32 pIter->verRange.maxVer = pConf->verRange.maxVer; pIter->timeWindow.skey = pConf->timewindow.skey; pIter->timeWindow.ekey = pConf->timewindow.ekey; + pIter->comparFn = pConf->comparFn; + + tRowKeyAssign(&pIter->startRowKey, pConf->pCurRowKey); pIter->pReader = pSttFileReader; pIter->pBlockLoadInfo = pBlockLoadInfo; @@ -618,17 +621,39 @@ static void findNextValidRow(SLDataIter *pIter, const char *idStr) { } int64_t ts = pData->aTSKEY[i]; - if (!pIter->backward) { // asc + if (!pIter->backward) { // asc if (ts > pIter->timeWindow.ekey) { // no more data break; - } else if (ts < pIter->timeWindow.skey) { - continue; + } else { + if (ts < pIter->timeWindow.skey) { + continue; + } + + if (ts == pIter->timeWindow.skey && pIter->startRowKey.numOfPKs > 0) { + SRowKey key; + tColRowGetKey(pData, i, &key); + int32_t ret = pkCompEx(pIter->comparFn, &key, &pIter->startRowKey); + if (ret < 0) { + continue; + } + } } } else { if (ts < pIter->timeWindow.skey) { break; - } else if (ts > pIter->timeWindow.ekey) { - continue; + } else { + if (ts > pIter->timeWindow.ekey) { + continue; + } + + if (ts == pIter->timeWindow.ekey && pIter->startRowKey.numOfPKs > 0) { + SRowKey key; + tColRowGetKey(pData, i, &key); + int32_t ret = pkCompEx(pIter->comparFn, &key, &pIter->startRowKey); + if (ret > 0) { + continue; + } + } } } @@ -802,8 +827,8 @@ int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf, SSttDataInfoF STimeWindow w = {0}; int64_t numOfRows = 0; + int64_t cid = pSttLevel->fobjArr->data[i]->f->cid; - int64_t cid = pSttLevel->fobjArr->data[i]->f->cid; code = tLDataIterOpen2(pIter, pSttFileReader, cid, pMTree->backward, pConf, pLoadInfo, &w, &numOfRows, pMTree->idStr); if (code != TSDB_CODE_SUCCESS) { diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 891fd823e7..80c4514579 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -89,7 +89,7 @@ static bool outOfTimeWindow(int64_t ts, STimeWindow* pWindow) { return (ts > pWi static void resetPreFilesetMemTableListIndex(SReaderStatus* pStatus); -static int32_t pkCompEx(__compar_fn_t comparFn, SRowKey* p1, SRowKey* p2) { +int32_t pkCompEx(__compar_fn_t comparFn, SRowKey* p1, SRowKey* p2) { if (p2 == NULL) { return 1; } @@ -118,12 +118,13 @@ static void tColRowGetKeyDeepCopy(SBlockData* pBlock, int32_t irow, int32_t slot return; } - pKey->numOfPKs = 1; - SColData* pColData = &pBlock->aColData[slotId]; SColVal cv; tColDataGetValue(pColData, irow, &cv); + pKey->numOfPKs = 1; + pKey->pks[0].type = cv.value.type; + if (IS_NUMERIC_TYPE(cv.value.type)) { pKey->pks[0].val = cv.value.val; } else { @@ -1394,7 +1395,7 @@ static int64_t getBoarderKeyInFiles(SFileDataBlockInfo* pBlock, STableBlockScanI int64_t key = 0; if (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA) { - int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey; + int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts; key = ascScan ? TMIN(pBlock->firstKey, keyInStt) : TMAX(pBlock->lastKey, keyInStt); } else { key = ascScan ? pBlock->firstKey : pBlock->lastKey; @@ -1437,9 +1438,10 @@ static void getBlockToLoadInfo(SDataBlockToLoadInfo* pInfo, SFileDataBlockInfo* pInfo->hasDupTs = (pBlockInfo->numRow > pBlockInfo->count) || (pBlockInfo->count <= 0); pInfo->overlapWithDelInfo = overlapWithDelSkyline(pScanInfo, &pRecord, pReader->info.order); + // todo handle the primary key overlap case ASSERT(pScanInfo->sttKeyInfo.status != STT_FILE_READER_UNINIT); if (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA) { - int64_t nextProcKeyInStt = pScanInfo->sttKeyInfo.nextProcKey; + int64_t nextProcKeyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts; pInfo->overlapWithSttBlock = !(pBlockInfo->lastKey < nextProcKeyInStt || pBlockInfo->firstKey > nextProcKeyInStt); } @@ -1536,8 +1538,9 @@ static bool tryCopyDistinctRowFromFileBlock(STsdbReader* pReader, SBlockData* pB static bool nextRowFromSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, int32_t pkSrcSlot, SVersionRange* pVerRange) { - int32_t order = pSttBlockReader->order; - int32_t step = ASCENDING_TRAVERSE(order) ? 1 : -1; + int32_t order = pSttBlockReader->order; + int32_t step = ASCENDING_TRAVERSE(order) ? 1 : -1; + SRowKey* pNextProc = &pScanInfo->sttKeyInfo.nextProcKey; while (1) { bool hasVal = tMergeTreeNext(&pSttBlockReader->mergeTree); @@ -1545,7 +1548,14 @@ static bool nextRowFromSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockSc pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA; // next file, the timestamps in the next file must be greater than those in current - pScanInfo->sttKeyInfo.nextProcKey += step; + pNextProc->ts += step; + if (pSttBlockReader->numOfPks > 0) { + if (IS_NUMERIC_TYPE(pNextProc->pks[0].type)) { + pNextProc->pks[0].val = INT64_MIN; + } else { + memset(pNextProc->pks[0].pData, 0, pNextProc->pks[0].nData); + } + } return false; } @@ -1559,7 +1569,8 @@ static bool nextRowFromSttBlocks(SSttBlockReader* pSttBlockReader, STableBlockSc tColRowGetKeyDeepCopy(pRow->pBlockData, pRow->iRow, pkSrcSlot, &pSttBlockReader->currentKey); } - pScanInfo->sttKeyInfo.nextProcKey = key; + tColRowGetKeyDeepCopy(pRow->pBlockData, pRow->iRow, pkSrcSlot, pNextProc); + if (pScanInfo->delSkyline != NULL && TARRAY_SIZE(pScanInfo->delSkyline) > 0) { if (!hasBeenDropped(pScanInfo->delSkyline, &pScanInfo->sttBlockDelIndex, key, ver, order, pVerRange)) { pScanInfo->sttKeyInfo.status = STT_FILE_HAS_DATA; @@ -2042,7 +2053,9 @@ static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbRea STbData* d = NULL; STbData* di = NULL; bool asc = ASCENDING_TRAVERSE(pReader->info.order); + bool forward = true; STsdbReadSnap* pSnap = pReader->pReadSnap; + STimeWindow* pWindow = &pReader->info.window; if (pBlockScanInfo->iterInit) { return TSDB_CODE_SUCCESS; @@ -2051,6 +2064,10 @@ static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbRea STsdbRowKey startKey = {0}; tRowKeyAssign(&startKey.key, &pBlockScanInfo->lastProcKey); startKey.version = asc ? pReader->info.verRange.minVer : pReader->info.verRange.maxVer; + if ((asc && (startKey.key.ts < pWindow->skey)) || ((!asc) && startKey.key.ts > pWindow->ekey)) { + startKey.key.ts = asc? pWindow->skey:pWindow->ekey; + forward = false; + } int32_t code = doInitMemDataIter(pReader, &d, pBlockScanInfo, &startKey, pSnap->pMem, &pBlockScanInfo->iter, "mem"); if (code != TSDB_CODE_SUCCESS) { @@ -2063,7 +2080,10 @@ static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbRea } loadMemTombData(&pBlockScanInfo->pMemDelData, d, di, pReader->info.verRange.maxVer); - forwardDataIter(&startKey.key, pBlockScanInfo, pReader); + + if (forward) { + forwardDataIter(&startKey.key, pBlockScanInfo, pReader); + } pBlockScanInfo->iterInit = true; return TSDB_CODE_SUCCESS; @@ -2115,6 +2135,7 @@ static bool isValidFileBlockRow(SBlockData* pBlockData, int32_t rowIndex, STable static bool initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) { bool hasData = true; + bool asc = ASCENDING_TRAVERSE(pReader->info.order); // the stt block reader has been initialized for this table. if (pSttBlockReader->uid == pScanInfo->uid) { @@ -2133,10 +2154,10 @@ static bool initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScan } STimeWindow w = pSttBlockReader->window; - if (ASCENDING_TRAVERSE(pSttBlockReader->order)) { - w.skey = pScanInfo->sttKeyInfo.nextProcKey; + if (asc) { + w.skey = pScanInfo->sttKeyInfo.nextProcKey.ts; } else { - w.ekey = pScanInfo->sttKeyInfo.nextProcKey; + w.ekey = pScanInfo->sttKeyInfo.nextProcKey.ts; } int64_t st = taosGetTimestampUs(); @@ -2157,6 +2178,8 @@ static bool initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScan .pCols = pReader->suppInfo.colId, .numOfCols = pReader->suppInfo.numOfCols, .loadTombFn = loadSttTombDataForAll, + .pCurRowKey = &pScanInfo->sttKeyInfo.nextProcKey, + .comparFn = pReader->pkComparFn, .pReader = pReader, .idstr = pReader->idStr, .rspRows = (pReader->info.execMode == READER_EXEC_ROWS), @@ -2193,8 +2216,9 @@ static bool initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScan } pScanInfo->sttKeyInfo.status = taosArrayGetSize(info.pTimeWindowList) ? STT_FILE_HAS_DATA : STT_FILE_NO_DATA; - pScanInfo->sttKeyInfo.nextProcKey = - ASCENDING_TRAVERSE(pReader->info.order) ? pScanInfo->sttWindow.skey : pScanInfo->sttWindow.ekey; + + // todo set the primary key value + pScanInfo->sttKeyInfo.nextProcKey.ts = asc ? pScanInfo->sttWindow.skey : pScanInfo->sttWindow.ekey; hasData = (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA); } else { // not clean stt blocks INIT_TIMEWINDOW(&pScanInfo->sttWindow); //reset the time window @@ -2755,7 +2779,7 @@ static void buildCleanBlockFromSttFiles(STsdbReader* pReader, STableBlockScanInf setComposedBlockFlag(pReader, true); - pScanInfo->sttKeyInfo.nextProcKey = asc ? pScanInfo->sttWindow.ekey + 1 : pScanInfo->sttWindow.skey - 1; + pScanInfo->sttKeyInfo.nextProcKey.ts = asc ? pScanInfo->sttWindow.ekey + 1 : pScanInfo->sttWindow.skey - 1; pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA; pScanInfo->lastProcKey.ts = asc ? pScanInfo->sttWindow.ekey : pScanInfo->sttWindow.skey; @@ -2915,7 +2939,7 @@ static bool notOverlapWithFiles(SFileDataBlockInfo* pBlockInfo, STableBlockScanI if ((!hasDataInSttBlock(pScanInfo)) || (pScanInfo->cleanSttBlocks == true)) { return true; } else { - int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey; + int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts; return (asc && pBlockInfo->lastKey < keyInStt) || (!asc && pBlockInfo->firstKey > keyInStt); } } @@ -2963,7 +2987,7 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) { code = buildDataBlockFromBuf(pReader, pScanInfo, endKey); } else { if (notOverlapWithFiles(pBlockInfo, pScanInfo, asc)) { - int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey; + int64_t keyInStt = pScanInfo->sttKeyInfo.nextProcKey.ts; if ((!hasDataInSttBlock(pScanInfo)) || (asc && pBlockInfo->lastKey < keyInStt) || (!asc && pBlockInfo->firstKey > keyInStt)) { @@ -3649,7 +3673,7 @@ int32_t doMergeRowsInSttBlock(SSttBlockReader* pSttBlockReader, STableBlockScanI } else { tsdbTrace("uid:%" PRIu64 " last del index:%d, del range:%d, lastKeyInStt:%" PRId64 ", %s", pScanInfo->uid, pScanInfo->sttBlockDelIndex, (int32_t)taosArrayGetSize(pScanInfo->delSkyline), - pScanInfo->sttKeyInfo.nextProcKey, idStr); + pScanInfo->sttKeyInfo.nextProcKey.ts, idStr); break; } } diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c index 93bc5ca573..99f0e42261 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c @@ -130,25 +130,46 @@ STableBlockScanInfo* getTableBlockScanInfo(SSHashObj* pTableMap, uint64_t uid, c return *p; } +static int32_t initSRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, int32_t len) { + pKey->numOfPKs = numOfPks; + pKey->ts = ts; + + if (numOfPks > 0) { + pKey->pks[0].type = type; + if (IS_NUMERIC_TYPE(pKey->pks[0].type)) { + pKey->pks[0].val = INT64_MIN; + } else { + pKey->pks[0].pData = taosMemoryCalloc(1, len); + pKey->pks[0].nData = 0; + + if (pKey->pks[0].pData == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + return terrno; + } + } + } + + return TSDB_CODE_SUCCESS; +} + static void initLastProcKey(STableBlockScanInfo *pScanInfo, STsdbReader* pReader) { + int32_t numOfPks = pReader->suppInfo.numOfPks; + SRowKey* pRowKey = &pScanInfo->lastProcKey; if (ASCENDING_TRAVERSE(pReader->info.order)) { int64_t skey = pReader->info.window.skey; - pRowKey->ts = (skey > INT64_MIN) ? (skey - 1) : skey; - pScanInfo->sttKeyInfo.nextProcKey = skey; + int64_t ts = (skey > INT64_MIN) ? (skey - 1) : skey; + + initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes); + initSRowKey(&pScanInfo->sttKeyInfo.nextProcKey, skey, numOfPks, pReader->suppInfo.pk.type, + pReader->suppInfo.pk.bytes); } else { int64_t ekey = pReader->info.window.ekey; - pRowKey->ts = (ekey < INT64_MAX) ? (ekey + 1) : ekey; - pScanInfo->sttKeyInfo.nextProcKey = ekey; - } + int64_t ts = (ekey < INT64_MAX) ? (ekey + 1) : ekey; - // only handle the first primary key. - pRowKey->numOfPKs = pReader->suppInfo.numOfPks; - if (pReader->suppInfo.numOfPks > 0) { - if (IS_VAR_DATA_TYPE(pReader->suppInfo.pk.type)) { - pRowKey->pks[0].pData = taosMemoryCalloc(1, pReader->suppInfo.pk.bytes); - } - pRowKey->pks[0].type = pReader->suppInfo.pk.type; + initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes); + initSRowKey(&pScanInfo->sttKeyInfo.nextProcKey, ekey, numOfPks, pReader->suppInfo.pk.type, + pReader->suppInfo.pk.bytes); } } @@ -230,7 +251,7 @@ void resetAllDataBlockScanInfo(SSHashObj* pTableMap, int64_t ts, int32_t step) { pInfo->delSkyline = taosArrayDestroy(pInfo->delSkyline); pInfo->lastProcKey.ts = ts; // todo check the nextProcKey info - pInfo->sttKeyInfo.nextProcKey = ts + step; + pInfo->sttKeyInfo.nextProcKey.ts = ts + step; } } diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.h b/source/dnode/vnode/src/tsdb/tsdbReadUtil.h index 4131bb1b86..9cdb36e648 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.h +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.h @@ -77,7 +77,9 @@ typedef enum ESttKeyStatus { typedef struct SSttKeyInfo { ESttKeyStatus status; // this value should be updated when switch to the next fileset - int64_t nextProcKey; // todo remove this attribute, since it is impossible to set correct nextProcKey value + SRowKey nextProcKey; + // int64_t nextProcKey; // todo remove this attribute, since it is impossible to set correct nextProcKey + // value } SSttKeyInfo; // clean stt file blocks: @@ -333,6 +335,7 @@ int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArra const char* pstr); bool isCleanSttBlock(SArray* pTimewindowList, STimeWindow* pQueryWindow, STableBlockScanInfo* pScanInfo, int32_t order); bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order); +int32_t pkCompEx(__compar_fn_t comparFn, SRowKey* p1, SRowKey* p2); typedef struct { SArray* pTombData; From 9638f8d7fcb345d563f605c7d04cf03acc7f2afb Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 26 Mar 2024 00:14:46 +0800 Subject: [PATCH 12/32] fix(tsdb): set the correct sttkey --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 80c4514579..27e7da11df 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -1861,9 +1861,11 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* TSDBROW* pRow = getValidMemRow(&pBlockScanInfo->iter, pDelList, pReader); TSDBROW* piRow = getValidMemRow(&pBlockScanInfo->iiter, pDelList, pReader); - SRowKey* pSttKey = NULL; + SRowKey* pSttKey = &(SRowKey){0}; if (hasDataInSttBlock(pBlockScanInfo) && (!pBlockScanInfo->cleanSttBlocks)) { - pSttKey = getCurrentKeyInSttBlock(pSttBlockReader); + tRowKeyAssign(pSttKey, getCurrentKeyInSttBlock(pSttBlockReader)); + } else { + pSttKey = NULL; } SRowKey* pfKey = &(SRowKey){0}; @@ -1902,7 +1904,7 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* } } - SRowKey minKey; + SRowKey minKey = {0}; if (ASCENDING_TRAVERSE(pReader->info.order)) { minKey = k; // let's find the minimum @@ -1910,11 +1912,11 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* minKey = ik; } - if (pfKey != NULL && (pkCompEx(compFn, pfKey, &minKey) < 0)) { + if ((pfKey != NULL) && (pkCompEx(compFn, pfKey, &minKey) < 0)) { minKey = *pfKey; } - if (pSttKey != NULL && (pkCompEx(compFn, pSttKey, &minKey) < 0)) { + if ((pSttKey != NULL) && (pkCompEx(compFn, pSttKey, &minKey) < 0)) { minKey = *pSttKey; } } else { @@ -1923,11 +1925,11 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo* minKey = ik; } - if (pfKey != NULL && (pkCompEx(compFn, pfKey, &minKey) > 0)) { + if ((pfKey != NULL) && (pkCompEx(compFn, pfKey, &minKey) > 0)) { minKey = *pfKey; } - if (pSttKey != NULL && (pkCompEx(compFn, pSttKey, &minKey) > 0)) { + if ((pSttKey != NULL) && (pkCompEx(compFn, pSttKey, &minKey) > 0)) { minKey = *pSttKey; } } From 5fe03fe3f4985ba7b9fdbd5fe48f6ea6a8212b26 Mon Sep 17 00:00:00 2001 From: slzhou Date: Tue, 26 Mar 2024 09:18:45 +0800 Subject: [PATCH 13/32] feat: irate support pk --- source/libs/function/inc/builtinsimpl.h | 2 +- source/libs/function/src/builtins.c | 3 +- source/libs/function/src/builtinsimpl.c | 86 ++++++++++++++++++------- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index 54bcd26bc3..ecc64fcd00 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -144,7 +144,7 @@ int32_t irateFunction(SqlFunctionCtx* pCtx); int32_t irateFunctionMerge(SqlFunctionCtx* pCtx); int32_t irateFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); -int32_t getIrateInfoSize(); +int32_t getIrateInfoSize(int32_t pkBytes); int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx); diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index cb2a979909..0f88572dbc 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -1638,7 +1638,8 @@ static int32_t translateIrateImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t l if (!IS_NUMERIC_TYPE(colType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } - pFunc->node.resType = (SDataType){.bytes = getIrateInfoSize() + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; + int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0; + pFunc->node.resType = (SDataType){.bytes = getIrateInfoSize(pkBytes) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_BINARY}; } else { if (1 != LIST_LENGTH(pFunc->pParameterList)) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 2907c096fe..70fe2b19df 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -269,6 +269,12 @@ typedef struct SRateInfo { double lastValue; TSKEY lastKey; int8_t hasResult; // flag to denote has value + + char* firstPk; + char* lastPk; + int8_t pkType; + int32_t pkBytes; + char pkData[]; } SRateInfo; typedef struct SGroupKeyInfo { @@ -6165,10 +6171,11 @@ int32_t derivativeFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; } -int32_t getIrateInfoSize() { return (int32_t)sizeof(SRateInfo); } +int32_t getIrateInfoSize(int32_t pkBytes) { return (int32_t)sizeof(SRateInfo) + 2 * pkBytes; } bool getIrateFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv) { - pEnv->calcMemSize = sizeof(SRateInfo); + int32_t pkBytes = (pFunc->hasPk) ? pFunc->pkBytes : 0; + pEnv->calcMemSize = getIrateInfoSize(pkBytes); return true; } @@ -6188,6 +6195,36 @@ bool irateFuncSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) { return true; } +static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* pk, double v) { + if (isFirst) { + pRateInfo->firstValue = v; + pRateInfo->firstKey = ts; + if (pRateInfo->firstPk) { + int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes; + memcpy(pRateInfo->firstPk, pk, pkBytes); + } + } else { + pRateInfo->lastValue = v; + pRateInfo->lastKey = ts; + if (pRateInfo->lastPk) { + int32_t pkBytes = IS_VAR_DATA_TYPE(pRateInfo->pkType) ? varDataTLen(pk) : pRateInfo->pkBytes; + memcpy(pRateInfo->lastPk, pk, pkBytes); + } + } +} + +static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo) { + if (pCtx->hasPrimaryKey) { + pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type; + pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes; + pRateInfo->firstPk = pRateInfo->pkData; + pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes; + } else { + pRateInfo->firstPk = NULL; + pRateInfo->lastPk = NULL; + } +} + int32_t irateFunction(SqlFunctionCtx* pCtx) { SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SRateInfo* pRateInfo = GET_ROWCELL_INTERBUF(pResInfo); @@ -6198,6 +6235,8 @@ int32_t irateFunction(SqlFunctionCtx* pCtx) { SColumnInfoData* pOutput = (SColumnInfoData*)pCtx->pOutput; funcInputUpdate(pCtx); + + initializeRateInfo(pCtx, pRateInfo); int32_t numOfElems = 0; int32_t type = pInputCol->info.type; @@ -6212,21 +6251,16 @@ int32_t irateFunction(SqlFunctionCtx* pCtx) { GET_TYPED_DATA(v, double, type, data); if (INT64_MIN == pRateInfo->lastKey) { - pRateInfo->lastValue = v; - pRateInfo->lastKey = row.ts; + doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v); pRateInfo->hasResult = 1; continue; } if (row.ts > pRateInfo->lastKey) { if ((INT64_MIN == pRateInfo->firstKey) || pRateInfo->lastKey > pRateInfo->firstKey) { - pRateInfo->firstValue = pRateInfo->lastValue; - pRateInfo->firstKey = pRateInfo->lastKey; + doSaveRateInfo(pRateInfo, true, pRateInfo->lastKey, pRateInfo->lastPk, pRateInfo->lastValue); } - - pRateInfo->lastValue = v; - pRateInfo->lastKey = row.ts; - + doSaveRateInfo(pRateInfo, false, row.ts, row.pPk, v); continue; } else if (row.ts == pRateInfo->lastKey) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; @@ -6234,8 +6268,7 @@ int32_t irateFunction(SqlFunctionCtx* pCtx) { if ((INT64_MIN == pRateInfo->firstKey) || row.ts > pRateInfo->firstKey) { - pRateInfo->firstValue = v; - pRateInfo->firstKey = row.ts; + doSaveRateInfo(pRateInfo, true, row.ts, row.pPk, v); } else if (row.ts == pRateInfo->firstKey) { return TSDB_CODE_FUNC_DUP_TIMESTAMP; } @@ -6271,25 +6304,26 @@ static double doCalcRate(const SRateInfo* pRateInfo, double tickPerSec) { static void irateTransferInfoImpl(TSKEY inputKey, SRateInfo* pInput, SRateInfo* pOutput, bool isFirstKey) { if (inputKey > pOutput->lastKey) { - pOutput->firstKey = pOutput->lastKey; - pOutput->firstValue = pOutput->lastValue; - - pOutput->lastKey = isFirstKey ? pInput->firstKey : pInput->lastKey; - pOutput->lastValue = isFirstKey ? pInput->firstValue : pInput->lastValue; + doSaveRateInfo(pOutput, true, pOutput->lastKey, pOutput->lastPk, pOutput->lastValue); + if (isFirstKey) { + doSaveRateInfo(pOutput, false, pInput->firstKey, pInput->firstPk, pInput->firstValue); + } else { + doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue); + } } else if ((inputKey < pOutput->lastKey) && (inputKey > pOutput->firstKey)) { - pOutput->firstKey = isFirstKey ? pInput->firstKey : pInput->lastKey; - pOutput->firstValue = isFirstKey ? pInput->firstValue : pInput->lastValue; + if (isFirstKey) { + doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue); + } else { + doSaveRateInfo(pOutput, true, pInput->lastKey, pInput->lastPk, pInput->lastValue); + } } else { // inputKey < pOutput->firstKey } } static void irateCopyInfo(SRateInfo* pInput, SRateInfo* pOutput) { - pOutput->firstKey = pInput->firstKey; - pOutput->lastKey = pInput->lastKey; - - pOutput->firstValue = pInput->firstValue; - pOutput->lastValue = pInput->lastValue; + doSaveRateInfo(pOutput, true, pInput->firstKey, pInput->firstPk, pInput->firstValue); + doSaveRateInfo(pOutput, false, pInput->lastKey, pInput->lastPk, pInput->lastValue); } static int32_t irateTransferInfo(SRateInfo* pInput, SRateInfo* pOutput) { @@ -6324,11 +6358,13 @@ int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) { } SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + initializeRateInfo(pCtx, pInfo); int32_t start = pInput->startRowIndex; for (int32_t i = start; i < start + pInput->numOfRows; ++i) { char* data = colDataGetData(pCol, i); SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data); + initializeRateInfo(pCtx, pInfo); if (pInputInfo->hasResult) { int32_t code = irateTransferInfo(pInputInfo, pInfo); if (code != TSDB_CODE_SUCCESS) { @@ -6347,7 +6383,7 @@ int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) { int32_t iratePartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); - int32_t resultBytes = getIrateInfoSize(); + int32_t resultBytes = getIrateInfoSize(pInfo->pkBytes); char* res = taosMemoryCalloc(resultBytes + VARSTR_HEADER_SIZE, sizeof(char)); memcpy(varDataVal(res), pInfo, resultBytes); From a70d5a49476a19e45f3717e5f9188ccf13f75c36 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 26 Mar 2024 09:50:06 +0800 Subject: [PATCH 14/32] fix(tsdb): fix bug during filtering brin records. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 27e7da11df..7505230eca 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -650,7 +650,6 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN int32_t k = 0; int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap); bool asc = ASCENDING_TRAVERSE(pReader->info.order); - int32_t step = asc ? 1 : -1; STimeWindow w = pReader->info.window; SBrinRecord* pRecord = NULL; @@ -710,7 +709,8 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN continue; } - if (pkCompEx(pReader->pkComparFn, &pRecord->lastKey.key, &pScanInfo->lastProcKey) <= 0) { + int32_t ret = pkCompEx(pReader->pkComparFn, &pRecord->lastKey.key, &pScanInfo->lastProcKey); + if ((asc && ret <= 0) || (!asc && ret >= 0)) { continue; } From 52a04cd00822576b90dc38ed80c40211285cbd3b Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 26 Mar 2024 10:55:56 +0800 Subject: [PATCH 15/32] fix(tsdb): fix bug for filter brin record. --- source/dnode/vnode/src/tsdb/tsdbRead2.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index 7505230eca..c7164d43de 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -709,9 +709,14 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN continue; } - int32_t ret = pkCompEx(pReader->pkComparFn, &pRecord->lastKey.key, &pScanInfo->lastProcKey); - if ((asc && ret <= 0) || (!asc && ret >= 0)) { - continue; + if (asc) { + if (pkCompEx(pReader->pkComparFn, &pRecord->lastKey.key, &pScanInfo->lastProcKey) <= 0) { + continue; + } + } else { + if (pkCompEx(pReader->pkComparFn, &pRecord->firstKey.key, &pScanInfo->lastProcKey) >= 0) { + continue; + } } // 2. version range check, version range is an CLOSED interval From f778dce52d04220e375c384cf0ce4bcf19e3f202 Mon Sep 17 00:00:00 2001 From: slzhou Date: Tue, 26 Mar 2024 14:13:00 +0800 Subject: [PATCH 16/32] fix: add pk for merge generated during merge scan node split --- source/libs/planner/src/planSpliter.c | 59 ++++++++++++++++++++------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index 34be489333..dd0cb5a964 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -690,19 +690,23 @@ static int32_t stbSplCreateExchangeNode(SSplitContext* pCxt, SLogicNode* pParent return code; } +static int32_t stbSplCreateMergeKeysByExpr(SNode* pExpr, EOrder order, SNodeList** pMergeKeys) { + SOrderByExprNode* pOrderByExpr = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR); + if (NULL == pOrderByExpr) { + return TSDB_CODE_OUT_OF_MEMORY; + } + pOrderByExpr->pExpr = nodesCloneNode(pExpr); + if (NULL == pOrderByExpr->pExpr) { + nodesDestroyNode((SNode*)pOrderByExpr); + return TSDB_CODE_OUT_OF_MEMORY; + } + pOrderByExpr->order = order; + pOrderByExpr->nullOrder = (order == ORDER_ASC) ? NULL_ORDER_FIRST : NULL_ORDER_LAST; + return nodesListMakeStrictAppend(pMergeKeys, (SNode*)pOrderByExpr); +} + static int32_t stbSplCreateMergeKeysByPrimaryKey(SNode* pPrimaryKey, EOrder order, SNodeList** pMergeKeys) { - SOrderByExprNode* pMergeKey = (SOrderByExprNode*)nodesMakeNode(QUERY_NODE_ORDER_BY_EXPR); - if (NULL == pMergeKey) { - return TSDB_CODE_OUT_OF_MEMORY; - } - pMergeKey->pExpr = nodesCloneNode(pPrimaryKey); - if (NULL == pMergeKey->pExpr) { - nodesDestroyNode((SNode*)pMergeKey); - return TSDB_CODE_OUT_OF_MEMORY; - } - pMergeKey->order = order; - pMergeKey->nullOrder = NULL_ORDER_FIRST; - return nodesListMakeStrictAppend(pMergeKeys, (SNode*)pMergeKey); + return stbSplCreateMergeKeysByExpr(pPrimaryKey, order, pMergeKeys); } static int32_t stbSplSplitIntervalForBatch(SSplitContext* pCxt, SStableSplitInfo* pInfo) { @@ -1357,6 +1361,28 @@ static SNode* stbSplFindPrimaryKeyFromScan(SScanLogicNode* pScan) { return pCol; } +static SNode* stbSplFindPkFromScan(SScanLogicNode* pScan) { + bool find = false; + SNode* pCol = NULL; + FOREACH(pCol, pScan->pScanCols) { + if (((SColumnNode*)pCol)->isPk) { + find = true; + break; + } + } + if (!find) { + return NULL; + } + SNode* pTarget = NULL; + FOREACH(pTarget, pScan->node.pTargets) { + if (nodesEqualNode(pTarget, pCol)) { + return pCol; + } + } + nodesListStrictAppend(pScan->node.pTargets, nodesCloneNode(pCol)); + return pCol; +} + static int32_t stbSplCreateMergeScanNode(SScanLogicNode* pScan, SLogicNode** pOutputMergeScan, SNodeList** pOutputMergeKeys) { SNodeList* pChildren = pScan->node.pChildren; @@ -1374,8 +1400,13 @@ static int32_t stbSplCreateMergeScanNode(SScanLogicNode* pScan, SLogicNode** pOu pMergeScan->filesetDelimited = true; pMergeScan->node.pChildren = pChildren; splSetParent((SLogicNode*)pMergeScan); - code = stbSplCreateMergeKeysByPrimaryKey(stbSplFindPrimaryKeyFromScan(pMergeScan), - pMergeScan->scanSeq[0] > 0 ? ORDER_ASC : ORDER_DESC, &pMergeKeys); + + SNode* pTs = stbSplFindPrimaryKeyFromScan(pMergeScan); + code = stbSplCreateMergeKeysByPrimaryKey(pTs, pMergeScan->scanSeq[0] > 0 ? ORDER_ASC : ORDER_DESC, &pMergeKeys); + SNode* pPk = stbSplFindPkFromScan(pMergeScan); + if (TSDB_CODE_SUCCESS == code && NULL != pPk) { + code = stbSplCreateMergeKeysByExpr(pPk, pMergeScan->scanSeq[0] > 0 ? ORDER_ASC : ORDER_DESC, &pMergeKeys); + } } if (TSDB_CODE_SUCCESS == code) { From ee4dda56c12d43c8a9b2c9a539fa1575a2884843 Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 26 Mar 2024 14:43:28 +0800 Subject: [PATCH 17/32] more code --- source/common/src/tdataformat.c | 22 ++++++++-------- source/dnode/vnode/src/vnd/vnodeSvr.c | 36 ++++++++++++++++++++------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index af124f7a02..cf8e28bf9a 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -557,13 +557,10 @@ void tRowDestroy(SRow *pRow) { } static int32_t tRowPCmprFn(const void *p1, const void *p2) { - if ((*(SRow **)p1)->ts < (*(SRow **)p2)->ts) { - return -1; - } else if ((*(SRow **)p1)->ts > (*(SRow **)p2)->ts) { - return 1; - } - - return 0; + SRowKey key1, key2; + tRowGetKey(*(SRow **)p1, &key1); + tRowGetKey(*(SRow **)p2, &key2); + return tRowKeyCompare(&key1, &key2); } static void tRowPDestroy(SRow **ppRow) { tRowDestroy(*ppRow); } static int32_t tRowMergeImpl(SArray *aRowP, STSchema *pTSchema, int32_t iStart, int32_t iEnd, int8_t flag) { @@ -645,13 +642,18 @@ int32_t tRowMerge(SArray *aRowP, STSchema *pTSchema, int8_t flag) { int32_t iStart = 0; while (iStart < aRowP->size) { - SRow *pRow = (SRow *)taosArrayGetP(aRowP, iStart); + SRowKey key1; + SRow *row1 = (SRow *)taosArrayGetP(aRowP, iStart); + + tRowGetKey(row1, &key1); int32_t iEnd = iStart + 1; while (iEnd < aRowP->size) { - SRow *pRowT = (SRow *)taosArrayGetP(aRowP, iEnd); + SRowKey key2; + SRow *row2 = (SRow *)taosArrayGetP(aRowP, iEnd); + tRowGetKey(row2, &key2); - if (pRow->ts != pRowT->ts) break; + if (tRowKeyCompare(&key1, &key2) != 0) break; iEnd++; } diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c index a03adb164b..a4af782ad7 100644 --- a/source/dnode/vnode/src/vnd/vnodeSvr.c +++ b/source/dnode/vnode/src/vnd/vnodeSvr.c @@ -32,14 +32,14 @@ static int32_t vnodeProcessAlterTbReq(SVnode *pVnode, int64_t ver, void *pReq, i static int32_t vnodeProcessDropTbReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp, SRpcMsg *pOriginRpc); static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp, - SRpcMsg *pOriginalMsg); + SRpcMsg *pOriginalMsg); static int32_t vnodeProcessCreateTSmaReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessAlterConfirmReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessAlterConfigReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessDropTtlTbReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessTrimReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp, - SRpcMsg *pOriginalMsg); + SRpcMsg *pOriginalMsg); static int32_t vnodeProcessBatchDeleteReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessCreateIndexReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); static int32_t vnodeProcessDropIndexReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp); @@ -1516,7 +1516,7 @@ static int32_t vnodeRebuildSubmitReqMsg(SSubmitReq2 *pSubmitReq, void **ppMsg) { } static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp, - SRpcMsg *pOriginalMsg) { + SRpcMsg *pOriginalMsg) { int32_t code = 0; terrno = 0; @@ -1586,12 +1586,26 @@ static int32_t vnodeProcessSubmitReq(SVnode *pVnode, int64_t ver, void *pReq, in } else { int32_t nRow = TARRAY_SIZE(pSubmitTbData->aRowP); SRow **aRow = (SRow **)TARRAY_DATA(pSubmitTbData->aRowP); + SRowKey lastRowKey; for (int32_t iRow = 0; iRow < nRow; ++iRow) { - if (aRow[iRow]->ts < minKey || aRow[iRow]->ts > maxKey || (iRow > 0 && aRow[iRow]->ts <= aRow[iRow - 1]->ts)) { + if (aRow[iRow]->ts < minKey || aRow[iRow]->ts > maxKey) { code = TSDB_CODE_INVALID_MSG; vError("vgId:%d %s failed since %s, version:%" PRId64, TD_VID(pVnode), __func__, tstrerror(code), ver); goto _exit; } + if (iRow == 0) { + tRowGetKey(aRow[iRow], &lastRowKey); + } else { + SRowKey rowKey; + tRowGetKey(aRow[iRow], &rowKey); + + if (tRowKeyCompare(&lastRowKey, &rowKey) >= 0) { + code = TSDB_CODE_INVALID_MSG; + vError("vgId:%d %s failed since %s, version:%" PRId64, TD_VID(pVnode), __func__, tstrerror(code), ver); + goto _exit; + } + lastRowKey = rowKey; + } } } } @@ -1735,10 +1749,14 @@ _exit: atomic_add_fetch_64(&pVnode->statis.nInsertSuccess, pSubmitRsp->affectedRows); atomic_add_fetch_64(&pVnode->statis.nBatchInsert, 1); - if(tsEnableMonitor && pSubmitRsp->affectedRows > 0 && strlen(pOriginalMsg->info.conn.user) > 0){ - const char *sample_labels[] = {VNODE_METRIC_TAG_VALUE_INSERT_AFFECTED_ROWS, pVnode->monitor.strClusterId, - pVnode->monitor.strDnodeId, tsLocalEp, pVnode->monitor.strVgId, - pOriginalMsg->info.conn.user, "Success"}; + if (tsEnableMonitor && pSubmitRsp->affectedRows > 0 && strlen(pOriginalMsg->info.conn.user) > 0) { + const char *sample_labels[] = {VNODE_METRIC_TAG_VALUE_INSERT_AFFECTED_ROWS, + pVnode->monitor.strClusterId, + pVnode->monitor.strDnodeId, + tsLocalEp, + pVnode->monitor.strVgId, + pOriginalMsg->info.conn.user, + "Success"}; taos_counter_add(pVnode->monitor.insertCounter, pSubmitRsp->affectedRows, sample_labels); } @@ -2019,7 +2037,7 @@ static int32_t vnodeProcessBatchDeleteReq(SVnode *pVnode, int64_t ver, void *pRe } static int32_t vnodeProcessDeleteReq(SVnode *pVnode, int64_t ver, void *pReq, int32_t len, SRpcMsg *pRsp, - SRpcMsg *pOriginalMsg) { + SRpcMsg *pOriginalMsg) { int32_t code = 0; SDecoder *pCoder = &(SDecoder){0}; SDeleteRes *pRes = &(SDeleteRes){0}; From 93ca55954fcd6f9d209ea204af8030e09d6ef32f Mon Sep 17 00:00:00 2001 From: Hongze Cheng Date: Tue, 26 Mar 2024 15:11:15 +0800 Subject: [PATCH 18/32] more code change --- include/libs/qcom/query.h | 2 +- source/libs/parser/inc/parInsertUtil.h | 4 +- source/libs/parser/src/parInsertSml.c | 31 ++-- source/libs/parser/src/parInsertSql.c | 194 ++++++++++++------------- source/libs/parser/src/parInsertUtil.c | 60 ++++---- 5 files changed, 148 insertions(+), 143 deletions(-) diff --git a/include/libs/qcom/query.h b/include/libs/qcom/query.h index 8d6cd6a3c0..0b192d5593 100644 --- a/include/libs/qcom/query.h +++ b/include/libs/qcom/query.h @@ -197,7 +197,7 @@ typedef struct STableDataCxt { SBoundColInfo boundColsInfo; SArray* pValues; SSubmitTbData* pData; - TSKEY lastTs; + SRowKey lastKey; bool ordered; bool duplicateTs; } STableDataCxt; diff --git a/source/libs/parser/inc/parInsertUtil.h b/source/libs/parser/inc/parInsertUtil.h index b20587dd43..1988620539 100644 --- a/source/libs/parser/inc/parInsertUtil.h +++ b/source/libs/parser/inc/parInsertUtil.h @@ -45,8 +45,8 @@ int16_t insFindCol(struct SToken *pColname, int16_t start, int16_t end, SSchema void insBuildCreateTbReq(SVCreateTbReq *pTbReq, const char *tname, STag *pTag, int64_t suid, const char *sname, SArray *tagName, uint8_t tagNum, int32_t ttl); int32_t insInitBoundColsInfo(int32_t numOfBound, SBoundColInfo *pInfo); -void insInitColValues(STableMeta* pTableMeta, SArray* aColValues); -void insCheckTableDataOrder(STableDataCxt *pTableCxt, TSKEY tsKey); +void insInitColValues(STableMeta *pTableMeta, SArray *aColValues); +void insCheckTableDataOrder(STableDataCxt *pTableCxt, SRowKey *rowKey); int32_t insGetTableDataCxt(SHashObj *pHash, void *id, int32_t idLen, STableMeta *pTableMeta, SVCreateTbReq **pCreateTbReq, STableDataCxt **pTableCxt, bool colMode, bool ignoreColVals); int32_t initTableColSubmitData(STableDataCxt *pTableCxt); diff --git a/source/libs/parser/src/parInsertSml.c b/source/libs/parser/src/parInsertSml.c index c2ce77f02b..fcb5588717 100644 --- a/source/libs/parser/src/parInsertSml.c +++ b/source/libs/parser/src/parInsertSml.c @@ -113,7 +113,8 @@ static int32_t smlBuildTagRow(SArray* cols, SBoundColInfo* tags, SSchema* pSchem SSchema* pTagSchema = &pSchema[tags->pColIndex[i]]; SSmlKv* kv = taosArrayGet(cols, i); - if(kv->keyLen != strlen(pTagSchema->name) || memcmp(kv->key, pTagSchema->name, kv->keyLen) != 0 || kv->type != pTagSchema->type){ + if (kv->keyLen != strlen(pTagSchema->name) || memcmp(kv->key, pTagSchema->name, kv->keyLen) != 0 || + kv->type != pTagSchema->type) { code = TSDB_CODE_SML_INVALID_DATA; uError("SML smlBuildTagRow error col not same %s", pTagSchema->name); goto end; @@ -200,7 +201,9 @@ int32_t smlBuildRow(STableDataCxt* pTableCxt) { if (TSDB_CODE_SUCCESS != ret) { return ret; } - insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); + SRowKey key; + tRowGetKey(*pRow, &key); + insCheckTableDataOrder(pTableCxt, &key); return TSDB_CODE_SUCCESS; } @@ -209,15 +212,16 @@ int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* data, int32 SSchema* pColSchema = schema + index; SColVal* pVal = taosArrayGet(pTableCxt->pValues, index); SSmlKv* kv = (SSmlKv*)data; - if(kv->keyLen != strlen(pColSchema->name) || memcmp(kv->key, pColSchema->name, kv->keyLen) != 0 || kv->type != pColSchema->type){ + if (kv->keyLen != strlen(pColSchema->name) || memcmp(kv->key, pColSchema->name, kv->keyLen) != 0 || + kv->type != pColSchema->type) { ret = TSDB_CODE_SML_INVALID_DATA; char* tmp = taosMemoryCalloc(kv->keyLen + 1, 1); - if(tmp){ + if (tmp) { memcpy(tmp, kv->key, kv->keyLen); - uInfo("SML data(name:%s type:%s) is not same like the db data(name:%s type:%s)", - tmp, tDataTypes[kv->type].name, pColSchema->name, tDataTypes[pColSchema->type].name); + uInfo("SML data(name:%s type:%s) is not same like the db data(name:%s type:%s)", tmp, tDataTypes[kv->type].name, + pColSchema->name, tDataTypes[pColSchema->type].name); taosMemoryFree(tmp); - }else{ + } else { uError("SML smlBuildCol out of memory"); } goto end; @@ -225,11 +229,11 @@ int32_t smlBuildCol(STableDataCxt* pTableCxt, SSchema* schema, void* data, int32 if (kv->type == TSDB_DATA_TYPE_NCHAR) { int32_t len = 0; int64_t size = pColSchema->bytes - VARSTR_HEADER_SIZE; - if(size <= 0){ + if (size <= 0) { ret = TSDB_CODE_SML_INVALID_DATA; goto end; } - char* pUcs4 = taosMemoryCalloc(1, size); + char* pUcs4 = taosMemoryCalloc(1, size); if (NULL == pUcs4) { ret = TSDB_CODE_OUT_OF_MEMORY; goto end; @@ -351,7 +355,7 @@ int32_t smlBindData(SQuery* query, bool dataFormat, SArray* tags, SArray* colsSc continue; } SSmlKv* kv = *(SSmlKv**)p; - if(kv->type != pColSchema->type){ + if (kv->type != pColSchema->type) { ret = buildInvalidOperationMsg(&pBuf, "kv type not equal to col type"); goto end; } @@ -367,7 +371,8 @@ int32_t smlBindData(SQuery* query, bool dataFormat, SArray* tags, SArray* colsSc } if (!taosMbsToUcs4(kv->value, kv->length, (TdUcs4*)pUcs4, pColSchema->bytes - VARSTR_HEADER_SIZE, &len)) { if (errno == E2BIG) { - uError("sml bind taosMbsToUcs4 error, kv length:%d, bytes:%d, kv->value:%s", (int)kv->length, pColSchema->bytes, kv->value); + uError("sml bind taosMbsToUcs4 error, kv length:%d, bytes:%d, kv->value:%s", (int)kv->length, + pColSchema->bytes, kv->value); buildInvalidOperationMsg(&pBuf, "value too long"); ret = TSDB_CODE_PAR_VALUE_TOO_LONG; goto end; @@ -396,7 +401,9 @@ int32_t smlBindData(SQuery* query, bool dataFormat, SArray* tags, SArray* colsSc buildInvalidOperationMsg(&pBuf, "tRowBuild error"); goto end; } - insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); + SRowKey key; + tRowGetKey(*pRow, &key); + insCheckTableDataOrder(pTableCxt, &key); clearColValArraySml(pTableCxt->pValues); } diff --git a/source/libs/parser/src/parInsertSql.c b/source/libs/parser/src/parInsertSql.c index 77c63c38d8..1a41ba5fb9 100644 --- a/source/libs/parser/src/parInsertSql.c +++ b/source/libs/parser/src/parInsertSql.c @@ -13,12 +13,12 @@ * along with this program. If not, see . */ +#include "geosWrapper.h" #include "parInsertUtil.h" #include "parToken.h" #include "scalar.h" #include "tglobal.h" #include "ttime.h" -#include "geosWrapper.h" typedef struct SInsertParseContext { SParseContext* pComCxt; @@ -29,7 +29,7 @@ typedef struct SInsertParseContext { bool usingDuplicateTable; bool forceUpdate; bool needTableTagVal; - bool needRequest; // whether or not request server + bool needRequest; // whether or not request server } SInsertParseContext; typedef int32_t (*_row_append_fn_t)(SMsgBuf* pMsgBuf, const void* value, int32_t len, void* param); @@ -154,19 +154,15 @@ static int32_t parseDuplicateUsingClause(SInsertParseContext* pCxt, SVnodeModify return code; } -typedef enum { - BOUND_TAGS, - BOUND_COLUMNS, - BOUND_ALL_AND_TBNAME -} EBoundColumnsType; +typedef enum { BOUND_TAGS, BOUND_COLUMNS, BOUND_ALL_AND_TBNAME } EBoundColumnsType; static int32_t getTbnameSchemaIndex(STableMeta* pTableMeta) { return pTableMeta->tableInfo.numOfTags + pTableMeta->tableInfo.numOfColumns; } // pStmt->pSql -> field1_name, ...) -static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, EBoundColumnsType boundColsType, STableMeta* pTableMeta, - SBoundColInfo* pBoundInfo) { +static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, EBoundColumnsType boundColsType, + STableMeta* pTableMeta, SBoundColInfo* pBoundInfo) { SSchema* pSchema = NULL; if (boundColsType == BOUND_TAGS) { pSchema = getTableTagSchema(pTableMeta); @@ -202,8 +198,7 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, E token.z = tmpTokenBuf; token.n = strdequote(token.z); - if (boundColsType == BOUND_ALL_AND_TBNAME && - token.n == strlen("tbname") && (strcasecmp(token.z, "tbname") == 0)) { + if (boundColsType == BOUND_ALL_AND_TBNAME && token.n == strlen("tbname") && (strcasecmp(token.z, "tbname") == 0)) { pBoundInfo->pColIndex[pBoundInfo->numOfBound] = tbnameSchemaIndex; pUseCols[tbnameSchemaIndex] = true; ++pBoundInfo->numOfBound; @@ -230,7 +225,7 @@ static int32_t parseBoundColumns(SInsertParseContext* pCxt, const char** pSql, E if (TSDB_CODE_SUCCESS == code && (BOUND_TAGS != boundColsType) && !pUseCols[0]) { code = buildInvalidOperationMsg(&pCxt->msg, "primary timestamp column can not be null"); } - if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) &&!pUseCols[tbnameSchemaIndex]) { + if (TSDB_CODE_SUCCESS == code && (BOUND_ALL_AND_TBNAME == boundColsType) && !pUseCols[tbnameSchemaIndex]) { code = buildInvalidOperationMsg(&pCxt->msg, "tbname column can not be null"); } taosMemoryFree(pUseCols); @@ -285,10 +280,11 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t int32_t index = 0, i = 0; int64_t interval = 0, tempInterval = 0; int64_t ts = 0, tempTs = 0; - bool firstIsTS = false, secondIsTs = false; + bool firstIsTS = false, secondIsTs = false; const char* pTokenEnd = *end; - if (TSDB_CODE_SUCCESS != parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS)) { + if (TSDB_CODE_SUCCESS != + parseTimestampOrInterval(&pTokenEnd, pToken, timePrec, &ts, &interval, pMsgBuf, &firstIsTS)) { return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); } @@ -330,8 +326,7 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t if (pTokenEnd[i] == ' ' || pTokenEnd[i] == '\t') { i++; continue; - } - else if (pTokenEnd[i] == ',' || pTokenEnd[i] == ')') { + } else if (pTokenEnd[i] == ',' || pTokenEnd[i] == ')') { *end = pTokenEnd + i; if (!firstIsTS) { return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); @@ -362,7 +357,8 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t valueToken.n = len; } - if (TSDB_CODE_SUCCESS != parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs)) { + if (TSDB_CODE_SUCCESS != + parseTimestampOrInterval(&pTokenEnd, &valueToken, timePrec, &tempTs, &tempInterval, pMsgBuf, &secondIsTs)) { return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); } @@ -376,7 +372,7 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); } ts = tempTs; - }else { + } else { // not support operator between tow interval, such as 2h + 3s if (!firstIsTS) { return buildSyntaxErrMsg(pMsgBuf, "invalid timestamp format", pToken->z); @@ -413,7 +409,7 @@ static int parseTime(const char** end, SToken* pToken, int16_t timePrec, int64_t } // need to call geosFreeBuffer(*output) later -static int parseGeometry(SToken *pToken, unsigned char **output, size_t *size) { +static int parseGeometry(SToken* pToken, unsigned char** output, size_t* size) { int32_t code = TSDB_CODE_FAILED; //[ToDo] support to parse WKB as well as WKT @@ -432,19 +428,19 @@ static int parseGeometry(SToken *pToken, unsigned char **output, size_t *size) { return code; } -static int32_t parseVarbinary(SToken* pToken, uint8_t **pData, uint32_t *nData, int32_t bytes){ - if(pToken->type != TK_NK_STRING){ +static int32_t parseVarbinary(SToken* pToken, uint8_t** pData, uint32_t* nData, int32_t bytes) { + if (pToken->type != TK_NK_STRING) { return TSDB_CODE_PAR_INVALID_VARBINARY; } - if(isHex(pToken->z + 1, pToken->n - 2)){ - if(!isValidateHex(pToken->z + 1, pToken->n - 2)){ + if (isHex(pToken->z + 1, pToken->n - 2)) { + if (!isValidateHex(pToken->z + 1, pToken->n - 2)) { return TSDB_CODE_PAR_INVALID_VARBINARY; } - void* data = NULL; + void* data = NULL; uint32_t size = 0; - if(taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0){ + if (taosHex2Ascii(pToken->z + 1, pToken->n - 2, &data, &size) < 0) { return TSDB_CODE_OUT_OF_MEMORY; } @@ -454,7 +450,7 @@ static int32_t parseVarbinary(SToken* pToken, uint8_t **pData, uint32_t *nData, } *pData = data; *nData = size; - }else{ + } else { *pData = taosMemoryCalloc(1, pToken->n); int32_t len = trimString(pToken->z, pToken->n, *pData, pToken->n); *nData = len; @@ -633,7 +629,7 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema, } case TSDB_DATA_TYPE_VARBINARY: { code = parseVarbinary(pToken, &val->pData, &val->nData, pSchema->bytes); - if(code != TSDB_CODE_SUCCESS){ + if (code != TSDB_CODE_SUCCESS) { return generateSyntaxErrMsg(pMsgBuf, code, pSchema->name); } break; @@ -759,8 +755,8 @@ static int32_t buildCreateTbReq(SVnodeModifyOpStmt* pStmt, STag* pTag, SArray* p int32_t checkAndTrimValue(SToken* pToken, char* tmpTokenBuf, SMsgBuf* pMsgBuf, int8_t type) { if ((pToken->type != TK_NOW && pToken->type != TK_TODAY && pToken->type != TK_NK_INTEGER && pToken->type != TK_NK_STRING && pToken->type != TK_NK_FLOAT && pToken->type != TK_NK_BOOL && - pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && - pToken->type != TK_NK_BIN && pToken->type != TK_NK_VARIABLE) || + pToken->type != TK_NULL && pToken->type != TK_NK_HEX && pToken->type != TK_NK_OCT && pToken->type != TK_NK_BIN && + pToken->type != TK_NK_VARIABLE) || (pToken->n == 0) || (pToken->type == TK_NK_RP)) { return buildSyntaxErrMsg(pMsgBuf, "invalid data or symbol", pToken->z); } @@ -1114,8 +1110,8 @@ static int32_t checkAuth(SParseContext* pCxt, SName* pTbName, bool* pMissCache, return code; } -static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, - bool* pMissCache, bool bUsingTable) { +static int32_t getTableMeta(SInsertParseContext* pCxt, SName* pTbName, STableMeta** pTableMeta, bool* pMissCache, + bool bUsingTable) { SParseContext* pComCxt = pCxt->pComCxt; int32_t code = TSDB_CODE_SUCCESS; if (pComCxt->async) { @@ -1220,7 +1216,7 @@ static int32_t getTargetTableSchema(SInsertParseContext* pCxt, SVnodeModifyOpStm pCxt->missCache = true; return TSDB_CODE_SUCCESS; } - SNode* pTagCond = NULL; + SNode* pTagCond = NULL; int32_t code = checkAuth(pCxt->pComCxt, &pStmt->targetTableName, &pCxt->missCache, &pTagCond); if (TSDB_CODE_SUCCESS == code && !pCxt->missCache) { code = getTargetTableMetaAndVgroup(pCxt, pStmt, &pCxt->missCache); @@ -1365,13 +1361,11 @@ static int32_t parseBoundColumnsClause(SInsertParseContext* pCxt, SVnodeModifyOp return buildSyntaxErrMsg(&pCxt->msg, "keyword VALUES or FILE is expected", token.z); } // pStmt->pSql -> field1_name, ...) - return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, - &pTableCxt->boundColsInfo); + return parseBoundColumns(pCxt, &pStmt->pSql, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo); } if (NULL != pStmt->pBoundCols) { - return parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta, - &pTableCxt->boundColsInfo); + return parseBoundColumns(pCxt, &pStmt->pBoundCols, BOUND_COLUMNS, pStmt->pTableMeta, &pTableCxt->boundColsInfo); } return TSDB_CODE_SUCCESS; @@ -1679,34 +1673,35 @@ static void clearColValArray(SArray* pCols) { typedef struct SStbRowsDataContext { SName stbName; - STableMeta* pStbMeta; - SNode* pTagCond; + STableMeta* pStbMeta; + SNode* pTagCond; SBoundColInfo boundColsInfo; // the following fields are for each stb row - SArray* aTagVals; - SArray* aColVals; - SArray* aTagNames; - SName ctbName; - STag* pTag; - STableMeta* pCtbMeta; + SArray* aTagVals; + SArray* aColVals; + SArray* aTagNames; + SName ctbName; + STag* pTag; + STableMeta* pCtbMeta; SVCreateTbReq* pCreateCtbReq; bool hasTimestampTag; bool isJsonTag; } SStbRowsDataContext; -typedef union SRowsDataContext{ - STableDataCxt* pTableDataCxt; +typedef union SRowsDataContext { + STableDataCxt* pTableDataCxt; SStbRowsDataContext* pStbRowsCxt; } SRowsDataContext; -static int32_t parseTbnameToken(SInsertParseContext* pCxt, SStbRowsDataContext* pStbRowsCxt, SToken* pToken, bool* pFoundCtbName) { +static int32_t parseTbnameToken(SInsertParseContext* pCxt, SStbRowsDataContext* pStbRowsCxt, SToken* pToken, + bool* pFoundCtbName) { *pFoundCtbName = false; int32_t code = checkAndTrimValue(pToken, pCxt->tmpTokenBuf, &pCxt->msg, TSDB_DATA_TYPE_BINARY); if (TK_NK_VARIABLE == pToken->type) { code = buildInvalidOperationMsg(&pCxt->msg, "not expected tbname"); } - if (code == TSDB_CODE_SUCCESS){ + if (code == TSDB_CODE_SUCCESS) { if (isNullValue(TSDB_DATA_TYPE_BINARY, pToken)) { return buildInvalidOperationMsg(&pCxt->msg, "tbname can not be null value"); } @@ -1717,7 +1712,7 @@ static int32_t parseTbnameToken(SInsertParseContext* pCxt, SStbRowsDataContext* if (pToken->z[i] == '.') { return buildInvalidOperationMsg(&pCxt->msg, "tbname can not contain '.'"); } else { - pStbRowsCxt->ctbName.tname[i] = pToken->z[i]; + pStbRowsCxt->ctbName.tname[i] = pToken->z[i]; } } pStbRowsCxt->ctbName.tname[pToken->n] = '\0'; @@ -1733,9 +1728,8 @@ static int32_t parseTbnameToken(SInsertParseContext* pCxt, SStbRowsDataContext* } static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, - SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, - const SToken* tagTokens, SSchema* const* tagSchemas, - int numOfTagTokens) { + SStbRowsDataContext* pStbRowsCxt, bool ctbFirst, const SToken* tagTokens, + SSchema* const* tagSchemas, int numOfTagTokens) { int32_t code = TSDB_CODE_SUCCESS; uint8_t precision = pStmt->pTableMeta->tableInfo.precision; @@ -1749,8 +1743,8 @@ static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModif } if (code == TSDB_CODE_SUCCESS) { - code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames, pStbRowsCxt->aTagVals, - &pStbRowsCxt->pTag); + code = parseTagValue(&pCxt->msg, NULL, precision, pTagSchema, pTagToken, pStbRowsCxt->aTagNames, + pStbRowsCxt->aTagVals, &pStbRowsCxt->pTag); } } if (code == TSDB_CODE_SUCCESS && !pStbRowsCxt->isJsonTag) { @@ -1765,9 +1759,9 @@ static int32_t processCtbTagsAfterCtbName(SInsertParseContext* pCxt, SVnodeModif } static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, - SStbRowsDataContext* pStbRowsCxt, SToken* pToken, - const SBoundColInfo* pCols, const SSchema* pSchemas, - SToken* tagTokens, SSchema** tagSchemas, int* pNumOfTagTokens, bool* bFoundTbName) { + SStbRowsDataContext* pStbRowsCxt, SToken* pToken, const SBoundColInfo* pCols, + const SSchema* pSchemas, SToken* tagTokens, SSchema** tagSchemas, int* pNumOfTagTokens, + bool* bFoundTbName) { int32_t code = TSDB_CODE_SUCCESS; SArray* pTagNames = pStbRowsCxt->aTagNames; SArray* pTagVals = pStbRowsCxt->aTagVals; @@ -1791,10 +1785,10 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* } if (pCols->pColIndex[i] < numOfCols) { const SSchema* pSchema = &pSchemas[pCols->pColIndex[i]]; - SColVal* pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]); + SColVal* pVal = taosArrayGet(pStbRowsCxt->aColVals, pCols->pColIndex[i]); code = parseValueToken(pCxt, ppSql, pToken, (SSchema*)pSchema, precision, pVal); if (TK_NK_VARIABLE == pToken->type) { - code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value"); + code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value"); } } else if (pCols->pColIndex[i] < tbnameIdx) { const SSchema* pTagSchema = &pSchemas[pCols->pColIndex[i]]; @@ -1808,11 +1802,11 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* code = buildInvalidOperationMsg(&pCxt->msg, "not expected row value"); } if (code == TSDB_CODE_SUCCESS) { - code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals, &pStbRowsCxt->pTag); + code = parseTagValue(&pCxt->msg, ppSql, precision, (SSchema*)pTagSchema, pToken, pTagNames, pTagVals, + &pStbRowsCxt->pTag); } } - } - else if (pCols->pColIndex[i] == tbnameIdx) { + } else if (pCols->pColIndex[i] == tbnameIdx) { code = parseTbnameToken(pCxt, pStbRowsCxt, pToken, bFoundTbName); } @@ -1826,22 +1820,21 @@ static int32_t doGetStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* return code; } -static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, - SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, - SToken* pToken, bool *pCtbFirst) { +static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, const char** ppSql, + SStbRowsDataContext* pStbRowsCxt, bool* pGotRow, SToken* pToken, bool* pCtbFirst) { SBoundColInfo* pCols = &pStbRowsCxt->boundColsInfo; SSchema* pSchemas = getTableColumnSchema(pStbRowsCxt->pStbMeta); - bool bFoundTbName = false; + bool bFoundTbName = false; const char* pOrigSql = *ppSql; - int32_t code = TSDB_CODE_SUCCESS; - SToken tagTokens[TSDB_MAX_TAGS] = {0}; + int32_t code = TSDB_CODE_SUCCESS; + SToken tagTokens[TSDB_MAX_TAGS] = {0}; SSchema* tagSchemas[TSDB_MAX_TAGS] = {0}; - int numOfTagTokens = 0; + int numOfTagTokens = 0; - code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, tagTokens, - tagSchemas, &numOfTagTokens, &bFoundTbName); + code = doGetStbRowValues(pCxt, pStmt, ppSql, pStbRowsCxt, pToken, pCols, pSchemas, tagTokens, tagSchemas, + &numOfTagTokens, &bFoundTbName); if (code == TSDB_CODE_SUCCESS && !bFoundTbName) { code = buildSyntaxErrMsg(&pCxt->msg, "tbname value expected", pOrigSql); @@ -1870,7 +1863,8 @@ static int32_t getStbRowValues(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pS return code; } -static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SStbRowsDataContext* pStbRowsCxt) { +static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, + SStbRowsDataContext* pStbRowsCxt) { int32_t code = TSDB_CODE_SUCCESS; pStbRowsCxt->pCreateCtbReq = taosMemoryCalloc(1, sizeof(SVCreateTbReq)); @@ -1878,16 +1872,16 @@ static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnod code = TSDB_CODE_OUT_OF_MEMORY; } if (code == TSDB_CODE_SUCCESS) { - insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag, pStbRowsCxt->pStbMeta->uid, - pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames, getNumOfTags(pStbRowsCxt->pStbMeta), - TSDB_DEFAULT_TABLE_TTL); + insBuildCreateTbReq(pStbRowsCxt->pCreateCtbReq, pStbRowsCxt->ctbName.tname, pStbRowsCxt->pTag, + pStbRowsCxt->pStbMeta->uid, pStbRowsCxt->stbName.tname, pStbRowsCxt->aTagNames, + getNumOfTags(pStbRowsCxt->pStbMeta), TSDB_DEFAULT_TABLE_TTL); pStbRowsCxt->pTag = NULL; } if (code == TSDB_CODE_SUCCESS) { char ctbFName[TSDB_TABLE_FNAME_LEN]; tNameExtractFullName(&pStbRowsCxt->ctbName, ctbFName); - SVgroupInfo vg; + SVgroupInfo vg; SRequestConnInfo conn = {.pTrans = pCxt->pComCxt->pTransporter, .requestId = pCxt->pComCxt->requestId, .requestObjRefId = pCxt->pComCxt->requestRid, @@ -1907,7 +1901,6 @@ static int32_t processCtbAutoCreationAndCtbMeta(SInsertParseContext* pCxt, SVnod return code; } - static void clearStbRowsDataContext(SStbRowsDataContext* pStbRowsCxt) { if (pStbRowsCxt == NULL) return; @@ -1938,7 +1931,7 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt } if (code == TSDB_CODE_SUCCESS && bFirstTable) { - code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt); + code = processCtbAutoCreationAndCtbMeta(pCxt, pStmt, pStbRowsCxt); } code = insGetTableDataCxt(pStmt->pTableBlockHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid), @@ -1948,7 +1941,9 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt SRow** pRow = taosArrayReserve((*ppTableDataCxt)->pData->aRowP, 1); code = tRowBuild(pStbRowsCxt->aColVals, (*ppTableDataCxt)->pSchema, pRow); if (TSDB_CODE_SUCCESS == code) { - insCheckTableDataOrder(*ppTableDataCxt, TD_ROW_KEY(*pRow)); + SRowKey key; + tRowGetKey(*pRow, &key); + insCheckTableDataOrder(*ppTableDataCxt, &key); } } @@ -1957,11 +1952,12 @@ static int32_t parseOneStbRow(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pSt } clearStbRowsDataContext(pStbRowsCxt); - + return TSDB_CODE_SUCCESS; } -static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow, SToken* pToken) { +static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataCxt* pTableCxt, bool* pGotRow, + SToken* pToken) { SBoundColInfo* pCols = &pTableCxt->boundColsInfo; bool isParseBindParam = false; SSchema* pSchemas = getTableColumnSchema(pTableCxt->pMeta); @@ -2014,7 +2010,9 @@ static int parseOneRow(SInsertParseContext* pCxt, const char** pSql, STableDataC SRow** pRow = taosArrayReserve(pTableCxt->pData->aRowP, 1); code = tRowBuild(pTableCxt->pValues, pTableCxt->pSchema, pRow); if (TSDB_CODE_SUCCESS == code) { - insCheckTableDataOrder(pTableCxt, TD_ROW_KEY(*pRow)); + SRowKey key; + tRowGetKey(*pRow, &key); + insCheckTableDataOrder(pTableCxt, &key); } } @@ -2112,10 +2110,11 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt code = parseOneRow(pCxt, (const char**)&pRow, rowsDataCxt.pTableDataCxt, &gotRow, &token); } else { STableDataCxt* pTableDataCxt = NULL; - code = parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt); + code = + parseOneStbRow(pCxt, pStmt, (const char**)&pRow, rowsDataCxt.pStbRowsCxt, &gotRow, &token, &pTableDataCxt); if (code == TSDB_CODE_SUCCESS) { SStbRowsDataContext* pStbRowsCxt = rowsDataCxt.pStbRowsCxt; - void* pData = pTableDataCxt; + void* pData = pTableDataCxt; taosHashPut(pStmt->pTableCxtHashObj, &pStbRowsCxt->pCtbMeta->uid, sizeof(pStbRowsCxt->pCtbMeta->uid), &pData, POINTER_BYTES); } @@ -2149,11 +2148,11 @@ static int32_t parseCsvFile(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt return code; } -static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, SRowsDataContext rowsDataCxt) { +static int32_t parseDataFromFileImpl(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt, + SRowsDataContext rowsDataCxt) { // init only for file if (NULL == pStmt->pTableCxtHashObj) { - pStmt->pTableCxtHashObj = - taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); + pStmt->pTableCxtHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK); } int32_t numOfRows = 0; int32_t code = parseCsvFile(pCxt, pStmt, rowsDataCxt, &numOfRows); @@ -2267,7 +2266,7 @@ static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDa cloneTableMeta(pStbRowsCxt->pStbMeta, &pStbRowsCxt->pCtbMeta); pStbRowsCxt->pCtbMeta->tableType = TSDB_CHILD_TABLE; pStbRowsCxt->pCtbMeta->suid = pStbRowsCxt->pStbMeta->uid; - + pStbRowsCxt->aTagNames = taosArrayInit(8, TSDB_COL_NAME_LEN); pStbRowsCxt->aTagVals = taosArrayInit(8, sizeof(STagVal)); @@ -2285,7 +2284,8 @@ static int32_t constructStbRowsDataContext(SVnodeModifyOpStmt* pStmt, SStbRowsDa static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { int32_t code = TSDB_CODE_SUCCESS; if (!pStmt->pBoundCols) { - return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion", pStmt->pSql); + return buildSyntaxErrMsg(&pCxt->msg, "(...tbname, ts...) bounded cols is expected for supertable insertion", + pStmt->pSql); } SStbRowsDataContext* pStbRowsCxt = NULL; @@ -2297,7 +2297,7 @@ static int32_t parseInsertStbClauseBottom(SInsertParseContext* pCxt, SVnodeModif pStbRowsCxt->hasTimestampTag = false; for (int32_t i = 0; i < pStbRowsCxt->boundColsInfo.numOfBound; ++i) { int16_t schemaIndex = pStbRowsCxt->boundColsInfo.pColIndex[i]; - if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta) ) { + if (schemaIndex != getTbnameSchemaIndex(pStmt->pTableMeta) && schemaIndex >= getNumOfColumns(pStmt->pTableMeta)) { if (pStmt->pTableMeta->schema[schemaIndex].type == TSDB_DATA_TYPE_TIMESTAMP) { pStbRowsCxt->hasTimestampTag = true; } @@ -2326,8 +2326,8 @@ static int32_t parseInsertTableClauseBottom(SInsertParseContext* pCxt, SVnodeMod return buildInvalidOperationMsg(&pCxt->msg, "insert into super table syntax is not supported for stmt"); } if (!pStmt->stbSyntax) { - STableDataCxt* pTableCxt = NULL; - int32_t code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt); + STableDataCxt* pTableCxt = NULL; + int32_t code = parseSchemaClauseBottom(pCxt, pStmt, &pTableCxt); SRowsDataContext rowsDataCxt; rowsDataCxt.pTableDataCxt = pTableCxt; if (TSDB_CODE_SUCCESS == code) { @@ -2442,7 +2442,7 @@ static int32_t parseInsertBodyBottom(SInsertParseContext* pCxt, SVnodeModifyOpSt bool fileOnly = (pStmt->insertType == TSDB_QUERY_TYPE_FILE_INSERT); if (fileOnly) { - // none data, skip merge & buildvgdata + // none data, skip merge & buildvgdata if (0 == taosHashGetSize(pStmt->pTableCxtHashObj)) { pCxt->needRequest = false; return TSDB_CODE_SUCCESS; @@ -2503,7 +2503,7 @@ static int32_t createVnodeModifOpStmt(SInsertParseContext* pCxt, bool reentry, S pStmt->freeHashFunc = insDestroyTableDataCxtHashMap; pStmt->freeArrayFunc = insDestroyVgroupDataCxtList; pStmt->freeStbRowsCxtFunc = destroyStbRowsDataContext; - + if (!reentry) { pStmt->pVgroupsHashObj = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), true, HASH_NO_LOCK); pStmt->pTableBlockHashObj = @@ -2625,7 +2625,7 @@ static int32_t checkSubtablePrivilegeForTable(const SArray* pTables, SVnodeModif } static int32_t processTableSchemaFromMetaData(SInsertParseContext* pCxt, const SMetaData* pMetaData, - SVnodeModifyOpStmt* pStmt, bool isStb) { + SVnodeModifyOpStmt* pStmt, bool isStb) { int32_t code = TSDB_CODE_SUCCESS; if (!isStb && TSDB_SUPER_TABLE == pStmt->pTableMeta->tableType) { code = buildInvalidOperationMsg(&pCxt->msg, "insert data into super table is not supported"); @@ -2767,11 +2767,11 @@ static int32_t parseInsertSqlFromStart(SInsertParseContext* pCxt, SVnodeModifyOp } static int32_t parseInsertSqlFromCsv(SInsertParseContext* pCxt, SVnodeModifyOpStmt* pStmt) { - int32_t code = TSDB_CODE_SUCCESS; + int32_t code = TSDB_CODE_SUCCESS; SRowsDataContext rowsDataCxt; if (!pStmt->stbSyntax) { - STableDataCxt* pTableCxt = NULL; + STableDataCxt* pTableCxt = NULL; code = getTableDataCxt(pCxt, pStmt, &pTableCxt); rowsDataCxt.pTableDataCxt = pTableCxt; } else { diff --git a/source/libs/parser/src/parInsertUtil.c b/source/libs/parser/src/parInsertUtil.c index 3f87f79301..7e99867b2a 100644 --- a/source/libs/parser/src/parInsertUtil.c +++ b/source/libs/parser/src/parInsertUtil.c @@ -170,9 +170,7 @@ static void initColValues(STableMeta* pTableMeta, SArray* pValues) { } } -void insInitColValues(STableMeta* pTableMeta, SArray* aColValues) { - initColValues(pTableMeta, aColValues); -} +void insInitColValues(STableMeta* pTableMeta, SArray* aColValues) { initColValues(pTableMeta, aColValues); } int32_t insInitBoundColsInfo(int32_t numOfBound, SBoundColInfo* pInfo) { pInfo->numOfCols = numOfBound; @@ -187,21 +185,22 @@ int32_t insInitBoundColsInfo(int32_t numOfBound, SBoundColInfo* pInfo) { return TSDB_CODE_SUCCESS; } -void insCheckTableDataOrder(STableDataCxt* pTableCxt, TSKEY tsKey) { +void insCheckTableDataOrder(STableDataCxt* pTableCxt, SRowKey* rowKey) { // once the data block is disordered, we do NOT keep last timestamp any more if (!pTableCxt->ordered) { return; } - if (tsKey < pTableCxt->lastTs) { + if (tRowKeyCompare(rowKey, &pTableCxt->lastKey) < 0) { pTableCxt->ordered = false; } - if (tsKey == pTableCxt->lastTs) { + if (tRowKeyCompare(rowKey, &pTableCxt->lastKey) == 0) { pTableCxt->duplicateTs = true; } - pTableCxt->lastTs = tsKey; + // TODO: for variable length data type, we need to copy it out + pTableCxt->lastKey = *rowKey; return; } @@ -217,7 +216,7 @@ static int32_t createTableDataCxt(STableMeta* pTableMeta, SVCreateTbReq** pCreat int32_t code = TSDB_CODE_SUCCESS; - pTableCxt->lastTs = 0; + pTableCxt->lastKey = (SRowKey){0}; pTableCxt->ordered = true; pTableCxt->duplicateTs = false; @@ -254,7 +253,7 @@ static int32_t createTableDataCxt(STableMeta* pTableMeta, SVCreateTbReq** pCreat pTableCxt->pData->uid = pTableMeta->uid; pTableCxt->pData->sver = pTableMeta->sversion; pTableCxt->pData->pCreateTbReq = pCreateTbReq != NULL ? *pCreateTbReq : NULL; - if(pCreateTbReq != NULL) *pCreateTbReq = NULL; + if (pCreateTbReq != NULL) *pCreateTbReq = NULL; if (pTableCxt->pData->flags & SUBMIT_REQ_COLUMN_DATA_FORMAT) { pTableCxt->pData->aCol = taosArrayInit(128, sizeof(SColData)); if (NULL == pTableCxt->pData->aCol) { @@ -276,7 +275,7 @@ static int32_t createTableDataCxt(STableMeta* pTableMeta, SVCreateTbReq** pCreat } static int32_t rebuildTableData(SSubmitTbData* pSrc, SSubmitTbData** pDst) { - int32_t code = TSDB_CODE_SUCCESS; + int32_t code = TSDB_CODE_SUCCESS; SSubmitTbData* pTmp = taosMemoryCalloc(1, sizeof(SSubmitTbData)); if (NULL == pTmp) { code = TSDB_CODE_OUT_OF_MEMORY; @@ -313,11 +312,10 @@ static int32_t rebuildTableData(SSubmitTbData* pSrc, SSubmitTbData** pDst) { if (TSDB_CODE_SUCCESS == code) { *pDst = pTmp; } - + return code; } - static void resetColValues(SArray* pValues) { int32_t num = taosArrayGetSize(pValues); for (int32_t i = 0; i < num; ++i) { @@ -463,7 +461,7 @@ static int32_t createVgroupDataCxt(STableDataCxt* pTableCxt, SHashObj* pVgroupHa int32_t code = taosHashPut(pVgroupHash, &pVgCxt->vgId, sizeof(pVgCxt->vgId), &pVgCxt, POINTER_BYTES); if (TSDB_CODE_SUCCESS == code) { taosArrayPush(pVgroupList, &pVgCxt); -// uDebug("td23101 2vgId:%d, uid:%" PRIu64, pVgCxt->vgId, pTableCxt->pMeta->uid); + // uDebug("td23101 2vgId:%d, uid:%" PRIu64, pVgCxt->vgId, pTableCxt->pMeta->uid); *pOutput = pVgCxt; } else { insDestroyVgroupDataCxt(pVgCxt); @@ -613,7 +611,7 @@ int32_t insBuildVgDataBlocks(SHashObj* pVgroupsHashObj, SArray* pVgDataCxtList, if (TSDB_CODE_SUCCESS == code) { dst->numOfTables = taosArrayGetSize(src->pData->aSubmitTbData); code = taosHashGetDup(pVgroupsHashObj, (const char*)&src->vgId, sizeof(src->vgId), &dst->vg); -// uError("td23101 3vgId:%d, numEps:%d", src->vgId, dst->vg.epSet.numOfEps); + // uError("td23101 3vgId:%d, numEps:%d", src->vgId, dst->vg.epSet.numOfEps); } if (TSDB_CODE_SUCCESS == code) { code = buildSubmitReq(src->vgId, src->pData, &dst->pData, &dst->size); @@ -634,7 +632,7 @@ int32_t insBuildVgDataBlocks(SHashObj* pVgroupsHashObj, SArray* pVgDataCxtList, static bool findFileds(SSchema* pSchema, TAOS_FIELD* fields, int numFields) { for (int i = 0; i < numFields; i++) { - if(strcmp(pSchema->name, fields[i].name) == 0){ + if (strcmp(pSchema->name, fields[i].name) == 0) { return true; } } @@ -644,7 +642,8 @@ static bool findFileds(SSchema* pSchema, TAOS_FIELD* fields, int numFields) { int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreateTbReq** pCreateTb, TAOS_FIELD* tFields, int numFields, bool needChangeLength) { - void* tmp = taosHashGet(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, sizeof(pTableMeta->uid)); + void* tmp = + taosHashGet(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, sizeof(pTableMeta->uid)); STableDataCxt* pTableCxt = NULL; int ret = insGetTableDataCxt(((SVnodeModifyOpStmt*)(query->pRoot))->pTableBlockHashObj, &pTableMeta->uid, sizeof(pTableMeta->uid), pTableMeta, pCreateTb, &pTableCxt, true, false); @@ -654,7 +653,7 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate } pTableCxt->pData->flags |= TD_REQ_FROM_TAOX; - if(tmp == NULL){ + if (tmp == NULL) { ret = initTableColSubmitData(pTableCxt); if (ret != TSDB_CODE_SUCCESS) { uError("initTableColSubmitData error"); @@ -663,8 +662,8 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate } char* p = (char*)data; - // | version | total length | total rows | blankFill | total columns | flag seg| block group id | column schema | each column - // length | + // | version | total length | total rows | blankFill | total columns | flag seg| block group id | column schema | each + // column length | int32_t version = *(int32_t*)data; p += sizeof(int32_t); p += sizeof(int32_t); @@ -699,8 +698,8 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate ret = TSDB_CODE_INVALID_PARA; goto end; } - if(tFields == NULL){ - for (int j = 0; j < boundInfo->numOfBound; j++){ + if (tFields == NULL) { + for (int j = 0; j < boundInfo->numOfBound; j++) { SSchema* pColSchema = &pSchema[j]; SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, j); if (*fields != pColSchema->type && *(int32_t*)(fields + sizeof(int8_t)) != pColSchema->bytes) { @@ -717,7 +716,7 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate } char* pData = pStart; ret = tColDataAddValueByDataBlock(pCol, pColSchema->type, pColSchema->bytes, numOfRows, offset, pData); - if(ret != 0){ + if (ret != 0) { goto end; } fields += sizeof(int8_t) + sizeof(int32_t); @@ -727,11 +726,11 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate pStart += colLength[j]; } } - }else{ + } else { for (int i = 0; i < numFields; i++) { - for (int j = 0; j < boundInfo->numOfBound; j++){ - SSchema* pColSchema = &pSchema[j]; - if(strcmp(pColSchema->name, tFields[i].name) == 0){ + for (int j = 0; j < boundInfo->numOfBound; j++) { + SSchema* pColSchema = &pSchema[j]; + if (strcmp(pColSchema->name, tFields[i].name) == 0) { if (*fields != pColSchema->type && *(int32_t*)(fields + sizeof(int8_t)) != pColSchema->bytes) { uError("type or bytes not equal"); ret = TSDB_CODE_INVALID_PARA; @@ -748,7 +747,7 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, j); ret = tColDataAddValueByDataBlock(pCol, pColSchema->type, pColSchema->bytes, numOfRows, offset, pData); - if(ret != 0){ + if (ret != 0) { goto end; } fields += sizeof(int8_t) + sizeof(int32_t); @@ -761,17 +760,16 @@ int rawBlockBindData(SQuery* query, STableMeta* pTableMeta, void* data, SVCreate break; } } - } for (int c = 0; c < boundInfo->numOfBound; ++c) { - if( boundInfo->pColIndex[c] != -1){ + if (boundInfo->pColIndex[c] != -1) { SColData* pCol = taosArrayGet(pTableCxt->pData->aCol, c); ret = tColDataAddValueByDataBlock(pCol, 0, 0, numOfRows, NULL, NULL); - if(ret != 0){ + if (ret != 0) { goto end; } - }else{ + } else { boundInfo->pColIndex[c] = c; // restore for next block } } From 47410db46aab6548de286368b1477addf95a6407 Mon Sep 17 00:00:00 2001 From: slzhou Date: Tue, 26 Mar 2024 16:30:53 +0800 Subject: [PATCH 19/32] fix: set hasPk and pkBytes for partial func and merge func --- source/libs/function/src/builtinsimpl.c | 10 ++++++++++ source/libs/function/src/functionMgt.c | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 70fe2b19df..b63fa6a167 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -2343,6 +2343,11 @@ EFuncDataRequired firstDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) { SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry); if (pResult->hasResult) { + if (pResult->pkBytes > 0) { + pResult->pkData = pResult->buf + pResult->bytes; + } else { + pResult->pkData = NULL; + } if (pResult->ts < pBlockInfo->window.skey) { return FUNC_DATA_REQUIRED_NOT_LOAD; } else if (pResult->ts == pBlockInfo->window.skey && pResult->pkData) { @@ -2366,6 +2371,11 @@ EFuncDataRequired lastDynDataReq(void* pRes, SDataBlockInfo* pBlockInfo) { SFirstLastRes* pResult = GET_ROWCELL_INTERBUF(pEntry); if (pResult->hasResult) { + if (pResult->pkBytes > 0) { + pResult->pkData = pResult->buf + pResult->bytes; + } else { + pResult->pkData = NULL; + } if (pResult->ts > pBlockInfo->window.ekey) { return FUNC_DATA_REQUIRED_NOT_LOAD; } else if (pResult->ts == pBlockInfo->window.ekey && pResult->pkData) { diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 697efb63fd..03bc1b4e59 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -415,6 +415,8 @@ static int32_t createPartialFunction(const SFunctionNode* pSrcFunc, SFunctionNod int32_t len = snprintf(name, sizeof(name) - 1, "%s.%p", (*pPartialFunc)->functionName, pSrcFunc); taosCreateMD5Hash(name, len); strncpy((*pPartialFunc)->node.aliasName, name, TSDB_COL_NAME_LEN - 1); + (*pPartialFunc)->hasPk = pSrcFunc->hasPk; + (*pPartialFunc)->pkBytes = pSrcFunc->pkBytes; return TSDB_CODE_SUCCESS; } @@ -453,7 +455,8 @@ static int32_t createMidFunction(const SFunctionNode* pSrcFunc, const SFunctionN } else { nodesDestroyList(pParameterList); } - + (*pMidFunc)->hasPk = pPartialFunc->hasPk; + (*pMidFunc)->pkBytes = pPartialFunc->pkBytes; return code; } @@ -482,7 +485,8 @@ static int32_t createMergeFunction(const SFunctionNode* pSrcFunc, const SFunctio } else { nodesDestroyList(pParameterList); } - + (*pMergeFunc)->hasPk = pPartialFunc->hasPk; + (*pMergeFunc)->pkBytes = pPartialFunc->pkBytes; return code; } From 595ae2c5b811bf3526ea8c975290c8a41dab582b Mon Sep 17 00:00:00 2001 From: slzhou Date: Tue, 26 Mar 2024 17:05:40 +0800 Subject: [PATCH 20/32] fix: irate on super table merge phase and translate --- source/libs/function/src/builtins.c | 2 +- source/libs/function/src/builtinsimpl.c | 21 +++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 0f88572dbc..2476449383 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -1632,7 +1632,7 @@ static int32_t translateIrate(SFunctionNode* pFunc, char* pErrBuf, int32_t len) static int32_t translateIrateImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len, bool isPartial) { uint8_t colType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; if (isPartial) { - if (3 != LIST_LENGTH(pFunc->pParameterList)) { + if (3 != LIST_LENGTH(pFunc->pParameterList) && 4 != LIST_LENGTH(pFunc->pParameterList)) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); } if (!IS_NUMERIC_TYPE(colType)) { diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index b63fa6a167..c029a809eb 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -6223,12 +6223,17 @@ static void doSaveRateInfo(SRateInfo* pRateInfo, bool isFirst, int64_t ts, char* } } -static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo) { +static void initializeRateInfo(SqlFunctionCtx* pCtx, SRateInfo* pRateInfo, bool isMerge) { if (pCtx->hasPrimaryKey) { - pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type; - pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes; - pRateInfo->firstPk = pRateInfo->pkData; - pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes; + if (!isMerge) { + pRateInfo->pkType = pCtx->input.pPrimaryKey->info.type; + pRateInfo->pkBytes = pCtx->input.pPrimaryKey->info.bytes; + pRateInfo->firstPk = pRateInfo->pkData; + pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes; + } else { + pRateInfo->firstPk = pRateInfo->pkData; + pRateInfo->lastPk = pRateInfo->pkData + pRateInfo->pkBytes; + } } else { pRateInfo->firstPk = NULL; pRateInfo->lastPk = NULL; @@ -6246,7 +6251,7 @@ int32_t irateFunction(SqlFunctionCtx* pCtx) { funcInputUpdate(pCtx); - initializeRateInfo(pCtx, pRateInfo); + initializeRateInfo(pCtx, pRateInfo, false); int32_t numOfElems = 0; int32_t type = pInputCol->info.type; @@ -6368,13 +6373,13 @@ int32_t irateFunctionMerge(SqlFunctionCtx* pCtx) { } SRateInfo* pInfo = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); - initializeRateInfo(pCtx, pInfo); + initializeRateInfo(pCtx, pInfo, true); int32_t start = pInput->startRowIndex; for (int32_t i = start; i < start + pInput->numOfRows; ++i) { char* data = colDataGetData(pCol, i); SRateInfo* pInputInfo = (SRateInfo*)varDataVal(data); - initializeRateInfo(pCtx, pInfo); + initializeRateInfo(pCtx, pInfo, true); if (pInputInfo->hasResult) { int32_t code = irateTransferInfo(pInputInfo, pInfo); if (code != TSDB_CODE_SUCCESS) { From f61596706d5345ff44bbf33096601f036ce2541c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Tue, 26 Mar 2024 17:34:30 +0800 Subject: [PATCH 21/32] fix(tsdb): add attributes for cache scan optr. --- include/libs/executor/storageapi.h | 2 +- source/dnode/vnode/inc/vnode.h | 2 +- source/dnode/vnode/src/tsdb/tsdbCache.c | 2 ++ source/dnode/vnode/src/tsdb/tsdbCacheRead.c | 16 +++++++++++++--- source/dnode/vnode/src/tsdb/tsdbReadUtil.h | 2 ++ source/libs/executor/src/cachescanoperator.c | 17 +++++++++++++++-- 6 files changed, 34 insertions(+), 7 deletions(-) diff --git a/include/libs/executor/storageapi.h b/include/libs/executor/storageapi.h index b47a162a1a..cdc978ae08 100644 --- a/include/libs/executor/storageapi.h +++ b/include/libs/executor/storageapi.h @@ -191,7 +191,7 @@ typedef struct TsdReader { typedef struct SStoreCacheReader { int32_t (*openReader)(void *pVnode, int32_t type, void *pTableIdList, int32_t numOfTables, int32_t numOfCols, SArray *pCidList, int32_t *pSlotIds, uint64_t suid, void **pReader, const char *idstr, - SArray *pFuncTypeList); + SArray *pFuncTypeList, SColumnInfo* pPkCol, int32_t numOfPks); void *(*closeReader)(void *pReader); int32_t (*retrieveRows)(void *pReader, SSDataBlock *pResBlock, const int32_t *slotIds, const int32_t *dstSlotIds, SArray *pTableUidList); diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h index 8ae7e9706d..87a0db1e71 100644 --- a/source/dnode/vnode/inc/vnode.h +++ b/source/dnode/vnode/inc/vnode.h @@ -181,7 +181,7 @@ void tsdbReaderSetNotifyCb(STsdbReader* pReader, TsdReaderNotifyCbFn not int32_t tsdbReuseCacherowsReader(void *pReader, void *pTableIdList, int32_t numOfTables); int32_t tsdbCacherowsReaderOpen(void *pVnode, int32_t type, void *pTableIdList, int32_t numOfTables, int32_t numOfCols, SArray *pCidList, int32_t *pSlotIds, uint64_t suid, void **pReader, const char *idstr, - SArray* pFuncTypeList); + SArray* pFuncTypeList, SColumnInfo* pkCol, int32_t numOfPks); int32_t tsdbRetrieveCacheRows(void *pReader, SSDataBlock *pResBlock, const int32_t *slotIds, const int32_t *dstSlotIds, SArray *pTableUids); void *tsdbCacherowsReaderClose(void *pReader); diff --git a/source/dnode/vnode/src/tsdb/tsdbCache.c b/source/dnode/vnode/src/tsdb/tsdbCache.c index 4c88242fee..c293b63f5d 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCache.c +++ b/source/dnode/vnode/src/tsdb/tsdbCache.c @@ -2288,6 +2288,8 @@ static int32_t lastIterOpen(SFSLastIter *iter, STFileSet *pFileSet, STsdb *pTsdb .loadTombFn = loadSttTomb, .pReader = pr, .idstr = pr->idstr, + .comparFn = pr->pkComparFn, + .pCurRowKey = &pr->rowKey, }; code = tMergeTreeOpen2(&iter->mergeTree, &conf, NULL); diff --git a/source/dnode/vnode/src/tsdb/tsdbCacheRead.c b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c index b7fe92c2c5..195ca59e9a 100644 --- a/source/dnode/vnode/src/tsdb/tsdbCacheRead.c +++ b/source/dnode/vnode/src/tsdb/tsdbCacheRead.c @@ -209,7 +209,7 @@ int32_t tsdbReuseCacherowsReader(void* reader, void* pTableIdList, int32_t numOf int32_t tsdbCacherowsReaderOpen(void* pVnode, int32_t type, void* pTableIdList, int32_t numOfTables, int32_t numOfCols, SArray* pCidList, int32_t* pSlotIds, uint64_t suid, void** pReader, const char* idstr, - SArray* pFuncTypeList) { + SArray* pFuncTypeList, SColumnInfo* pPkCol, int32_t numOfPks) { *pReader = NULL; SCacheRowsReader* p = taosMemoryCalloc(1, sizeof(SCacheRowsReader)); if (p == NULL) { @@ -226,6 +226,15 @@ int32_t tsdbCacherowsReaderOpen(void* pVnode, int32_t type, void* pTableIdList, p->pSlotIds = pSlotIds; p->pFuncTypeList = pFuncTypeList; + p->rowKey.numOfPKs = numOfPks; + if (numOfPks > 0) { + p->pkComparFn = getComparFunc(pPkCol->type, 0); + p->rowKey.pks[0].type = pPkCol->type; + if (IS_VAR_DATA_TYPE(pPkCol->type)) { + p->rowKey.pks[0].pData = taosMemoryCalloc(1, pPkCol->bytes); + } + } + if (numOfTables == 0) { *pReader = p; return TSDB_CODE_SUCCESS; @@ -359,10 +368,11 @@ int32_t tsdbRetrieveCacheRows(void* pReader, SSDataBlock* pResBlock, const int32 for (int32_t j = 0; j < pr->numOfCols; ++j) { int32_t bytes; - if (slotIds[j] == -1) + if (slotIds[j] == -1) { bytes = 1; - else + } else { bytes = pr->pSchema->columns[slotIds[j]].bytes; + } pRes[j] = taosMemoryCalloc(1, sizeof(SFirstLastRes) + bytes + VARSTR_HEADER_SIZE); SFirstLastRes* p = (SFirstLastRes*)varDataVal(pRes[j]); diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.h b/source/dnode/vnode/src/tsdb/tsdbReadUtil.h index 9cdb36e648..c48b7479dc 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.h +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.h @@ -369,6 +369,8 @@ typedef struct SCacheRowsReader { char* idstr; int64_t lastTs; SArray* pFuncTypeList; + __compar_fn_t pkComparFn; + SRowKey rowKey; } SCacheRowsReader; int32_t tsdbCacheGetBatch(STsdb* pTsdb, tb_uid_t uid, SArray* pLastArray, SCacheRowsReader* pr, int8_t ltype); diff --git a/source/libs/executor/src/cachescanoperator.c b/source/libs/executor/src/cachescanoperator.c index e4fa9f7580..56052434a4 100644 --- a/source/libs/executor/src/cachescanoperator.c +++ b/source/libs/executor/src/cachescanoperator.c @@ -46,6 +46,8 @@ typedef struct SCacheRowsScanInfo { int32_t indexOfBufferedRes; STableListInfo* pTableList; SArray* pFuncTypeList; + int32_t numOfPks; + SColumnInfo pkCol; } SCacheRowsScanInfo; static SSDataBlock* doScanCache(SOperatorInfo* pOperator); @@ -106,6 +108,16 @@ SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pScanNode, SRe goto _error; } + for(int32_t i = 0; i < taosArrayGetSize(pInfo->matchInfo.pList); ++i) { + SColMatchItem* pItem = taosArrayGet(pInfo->matchInfo.pList, i); + if (pItem->isPk) { + pInfo->numOfPks += 1; + pInfo->pkCol.type = pItem->dataType.type; // only record one primary key + pInfo->pkCol.bytes = pItem->dataType.bytes; // only record one primary key + pInfo->pkCol.pk = 1; + } + } + SArray* pCidList = taosArrayInit(numOfCols, sizeof(int16_t)); pInfo->pFuncTypeList = taosArrayInit(taosArrayGetSize(pScanNode->pFuncTypes), sizeof(int32_t)); taosArrayAddAll(pInfo->pFuncTypeList, pScanNode->pFuncTypes); @@ -140,7 +152,8 @@ SOperatorInfo* createCacherowsScanOperator(SLastRowScanPhysiNode* pScanNode, SRe uint64_t suid = tableListGetSuid(pTableListInfo); code = pInfo->readHandle.api.cacheFn.openReader(pInfo->readHandle.vnode, pInfo->retrieveType, pList, totalTables, taosArrayGetSize(pInfo->matchInfo.pList), pCidList, pInfo->pSlotIds, - suid, &pInfo->pLastrowReader, pTaskInfo->id.str, pScanNode->pFuncTypes); + suid, &pInfo->pLastrowReader, pTaskInfo->id.str, pScanNode->pFuncTypes, + &pInfo->pkCol, pInfo->numOfPks); if (code != TSDB_CODE_SUCCESS) { goto _error; } @@ -282,7 +295,7 @@ SSDataBlock* doScanCache(SOperatorInfo* pOperator) { if (NULL == pInfo->pLastrowReader) { code = pInfo->readHandle.api.cacheFn.openReader(pInfo->readHandle.vnode, pInfo->retrieveType, pList, num, taosArrayGetSize(pInfo->matchInfo.pList), pInfo->pCidList, pInfo->pSlotIds, suid, &pInfo->pLastrowReader, - pTaskInfo->id.str, pInfo->pFuncTypeList); + pTaskInfo->id.str, pInfo->pFuncTypeList, &pInfo->pkCol, pInfo->numOfPks); if (code != TSDB_CODE_SUCCESS) { pInfo->currentGroupIndex += 1; taosArrayClear(pInfo->pUidList); From 6e8bc410054b977f6029f8059db590e8975c3087 Mon Sep 17 00:00:00 2001 From: slzhou Date: Wed, 27 Mar 2024 09:43:41 +0800 Subject: [PATCH 22/32] feat: add test case pk func --- tests/parallel_test/cases.task | 1 + tests/system-test/2-query/pk_func.py | 652 +++++++++++++++++++++++++++ 2 files changed, 653 insertions(+) create mode 100644 tests/system-test/2-query/pk_func.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index 2402f6a94a..b33f0050d1 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -45,6 +45,7 @@ #,,n,system-test,python3 ./test.py -f 8-stream/snode_restart.py -N 4 ,,n,system-test,python3 ./test.py -f 8-stream/snode_restart_with_checkpoint.py -N 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_func.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/partition_expr.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/project_group.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbname_vgroup.py diff --git a/tests/system-test/2-query/pk_func.py b/tests/system-test/2-query/pk_func.py new file mode 100644 index 0000000000..30b6671f98 --- /dev/null +++ b/tests/system-test/2-query/pk_func.py @@ -0,0 +1,652 @@ +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import tdDnodes +from math import inf + +class TDTestCase: + def caseDescription(self): + ''' + case1: [TD-] + ''' + return + + def init(self, conn, logSql, replicaVer=1): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + self.conn = conn + + def restartTaosd(self, index=1, dbname="db"): + tdDnodes.stop(index) + tdDnodes.startWithoutSleep(index) + tdSql.execute(f"use pk_func") + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists pk_func") + tdSql.execute("create database if not exists pk_func") + tdSql.execute('use pk_func') + tdSql.execute('drop database IF EXISTS d1;') + + tdSql.execute('drop database IF EXISTS d2;') + + tdSql.execute('create database d1 vgroups 1') + + tdSql.execute('use d1;') + + tdSql.execute('create table st(ts timestamp, pk int primary key, f int) tags(t int);') + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select * from d1.ct1 order by ts,pk;') + tdSql.checkRows(6) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 1) + tdSql.checkData(2, 2, 1) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 5) + tdSql.checkData(4, 2, 5) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 6) + tdSql.checkData(5, 2, 6) + + tdSql.query('select * from d1.ct2 order by ts,pk;') + tdSql.checkRows(6) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(1, 2, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 2) + tdSql.checkData(2, 2, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(3, 1, 3) + tdSql.checkData(3, 2, 3) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 7) + tdSql.checkData(4, 2, 7) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 8) + tdSql.checkData(5, 2, 8) + + tdSql.query('select * from d1.st order by ts,pk;') + tdSql.checkRows(12) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(0, 3, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(1, 3, 1) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(2, 1, 3) + tdSql.checkData(2, 2, 3) + tdSql.checkData(2, 3, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(3, 3, 2) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(4, 1, 1) + tdSql.checkData(4, 2, 1) + tdSql.checkData(4, 3, 1) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(5, 1, 2) + tdSql.checkData(5, 2, 2) + tdSql.checkData(5, 3, 2) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(6, 1, 3) + tdSql.checkData(6, 2, 3) + tdSql.checkData(6, 3, 2) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(7, 1, 4) + tdSql.checkData(7, 2, 4) + tdSql.checkData(7, 3, 1) + tdSql.checkData(8, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(8, 1, 5) + tdSql.checkData(8, 2, 5) + tdSql.checkData(8, 3, 1) + tdSql.checkData(9, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(9, 1, 6) + tdSql.checkData(9, 2, 6) + tdSql.checkData(9, 3, 1) + tdSql.checkData(10, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(10, 1, 7) + tdSql.checkData(10, 2, 7) + tdSql.checkData(10, 3, 2) + tdSql.checkData(11, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(11, 1, 8) + tdSql.checkData(11, 2, 8) + tdSql.checkData(11, 3, 2) + + tdSql.query('select first(*) from d1.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + + tdSql.query('select first(*) from d1.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + + tdSql.query('select first(*) from d1.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + + tdSql.query('select last(*) from d1.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + + tdSql.query('select last(*) from d1.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last(*) from d1.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last_row(*) from d1.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + + tdSql.query('select last_row(*) from d1.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last_row(*) from d1.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select ts,diff(f) from d1.ct1;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + + tdSql.query('select ts,diff(f) from d1.ct2;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, -1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 5) + + tdSql.query('select ts,diff(f) from d1.st;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + + tdSql.query('select irate(f) from d1.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 4.0) + + tdSql.query('select irate(f) from d1.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 5.0) + + tdSql.query('select irate(f) from d1.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 4.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.ct1;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.ct2;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, -1.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 5.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.st;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + + tdSql.query('select twa(f) from d1.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2.0) + + tdSql.query('select twa(f) from d1.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 3.5) + + tdSql.query('select twa(f) from d1.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2.0) + + tdSql.query('select ts,pk,unique(f) from d1.ct1 order by ts,pk;') + tdSql.checkRows(5) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 4) + tdSql.checkData(2, 2, 4) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + tdSql.checkData(3, 2, 5) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 6) + tdSql.checkData(4, 2, 6) + + tdSql.query('select ts,pk,unique(f) from d1.ct2 order by ts,pk;') + tdSql.checkRows(5) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(1, 2, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 2) + tdSql.checkData(2, 2, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 7) + tdSql.checkData(3, 2, 7) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 8) + tdSql.checkData(4, 2, 8) + + tdSql.query('select ts,pk,unique(f) from d1.st order by ts,pk;') + tdSql.checkRows(8) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(2, 1, 3) + tdSql.checkData(2, 2, 3) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 5) + tdSql.checkData(4, 2, 5) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 6) + tdSql.checkData(5, 2, 6) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(6, 1, 7) + tdSql.checkData(6, 2, 7) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(7, 1, 8) + tdSql.checkData(7, 2, 8) + + tdSql.execute('create database d2 vgroups 2') + + tdSql.execute('use d2;') + + tdSql.execute('create table st(ts timestamp, pk int primary key, f int) tags(t int);') + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select * from d2.ct1 order by ts,pk;') + tdSql.checkRows(6) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 1) + tdSql.checkData(2, 2, 1) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 5) + tdSql.checkData(4, 2, 5) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 6) + tdSql.checkData(5, 2, 6) + + tdSql.query('select * from d2.ct2 order by ts,pk;') + tdSql.checkRows(6) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(1, 2, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 2) + tdSql.checkData(2, 2, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(3, 1, 3) + tdSql.checkData(3, 2, 3) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 7) + tdSql.checkData(4, 2, 7) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 8) + tdSql.checkData(5, 2, 8) + + tdSql.query('select * from d2.st order by ts,pk;') + tdSql.checkRows(12) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(0, 3, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(1, 3, 1) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(2, 1, 3) + tdSql.checkData(2, 2, 3) + tdSql.checkData(2, 3, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(3, 3, 2) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(4, 1, 1) + tdSql.checkData(4, 2, 1) + tdSql.checkData(4, 3, 1) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(5, 1, 2) + tdSql.checkData(5, 2, 2) + tdSql.checkData(5, 3, 2) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(6, 1, 3) + tdSql.checkData(6, 2, 3) + tdSql.checkData(6, 3, 2) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(7, 1, 4) + tdSql.checkData(7, 2, 4) + tdSql.checkData(7, 3, 1) + tdSql.checkData(8, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(8, 1, 5) + tdSql.checkData(8, 2, 5) + tdSql.checkData(8, 3, 1) + tdSql.checkData(9, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(9, 1, 6) + tdSql.checkData(9, 2, 6) + tdSql.checkData(9, 3, 1) + tdSql.checkData(10, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(10, 1, 7) + tdSql.checkData(10, 2, 7) + tdSql.checkData(10, 3, 2) + tdSql.checkData(11, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(11, 1, 8) + tdSql.checkData(11, 2, 8) + tdSql.checkData(11, 3, 2) + + tdSql.query('select first(*) from d2.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + + tdSql.query('select first(*) from d2.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + + tdSql.query('select first(*) from d2.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + + tdSql.query('select last(*) from d2.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + + tdSql.query('select last(*) from d2.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last(*) from d2.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last_row(*) from d2.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + + tdSql.query('select last_row(*) from d2.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last_row(*) from d2.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select ts,diff(f) from d2.ct1;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + + tdSql.query('select ts,diff(f) from d2.ct2;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, -1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 5) + + tdSql.query('select ts,diff(f) from d2.st;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + + tdSql.query('select irate(f) from d2.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 4.0) + + tdSql.query('select irate(f) from d2.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 5.0) + + tdSql.query('select irate(f) from d2.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 4.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d2.ct1;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d2.ct2;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, -1.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 5.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d2.st;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + + tdSql.query('select twa(f) from d2.ct1;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2.0) + + tdSql.query('select twa(f) from d2.ct2;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 3.5) + + tdSql.query('select twa(f) from d2.st;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2.0) + + tdSql.query('select ts,pk,unique(f) from d2.ct1 order by ts,pk;') + tdSql.checkRows(5) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 4) + tdSql.checkData(2, 2, 4) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + tdSql.checkData(3, 2, 5) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 6) + tdSql.checkData(4, 2, 6) + + tdSql.query('select ts,pk,unique(f) from d2.ct2 order by ts,pk;') + tdSql.checkRows(5) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 2, 3) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(1, 2, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 2) + tdSql.checkData(2, 2, 2) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 7) + tdSql.checkData(3, 2, 7) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 8) + tdSql.checkData(4, 2, 8) + + tdSql.query('select ts,pk,unique(f) from d2.st order by ts,pk;') + tdSql.checkRows(8) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(2, 1, 3) + tdSql.checkData(2, 2, 3) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 5) + tdSql.checkData(4, 2, 5) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 6) + tdSql.checkData(5, 2, 6) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(6, 1, 7) + tdSql.checkData(6, 2, 7) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(7, 1, 8) + tdSql.checkData(7, 2, 8) + + tdSql.execute('drop database pk_func') + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) From a2112625f9b62b18943e5a56ba79b3173d4df4fc Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Wed, 27 Mar 2024 15:06:51 +0800 Subject: [PATCH 23/32] fix(tsdb): set correct uid list. --- source/dnode/vnode/src/tsdb/tsdbMergeTree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c index 97194acb00..b3dd1dec0e 100644 --- a/source/dnode/vnode/src/tsdb/tsdbMergeTree.c +++ b/source/dnode/vnode/src/tsdb/tsdbMergeTree.c @@ -365,7 +365,7 @@ static int32_t loadSttStatisticsBlockData(SSttFileReader *pSttFileReader, SSttBl } if (pStatisBlkArray->data[k].maxTbid.suid == suid) { - taosArrayAddBatch(pBlockLoadInfo->info.pUid, tBufferGetDataAt(&block.suids, i * sizeof(int64_t)), rows - i); + taosArrayAddBatch(pBlockLoadInfo->info.pUid, tBufferGetDataAt(&block.uids, i * sizeof(int64_t)), rows - i); taosArrayAddBatch(pBlockLoadInfo->info.pFirstKey, tBufferGetDataAt(&block.firstKeyTimestamps, i * sizeof(int64_t)), rows - i); taosArrayAddBatch(pBlockLoadInfo->info.pLastKey, From 43cefb9d55bd615b0fbcecf40f79dafc1b60bd65 Mon Sep 17 00:00:00 2001 From: slzhou Date: Wed, 27 Mar 2024 16:26:33 +0800 Subject: [PATCH 24/32] feat: find pk col from interp func node for interp operator --- source/libs/executor/src/timesliceoperator.c | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/source/libs/executor/src/timesliceoperator.c b/source/libs/executor/src/timesliceoperator.c index abaebb1543..4b86f85d53 100644 --- a/source/libs/executor/src/timesliceoperator.c +++ b/source/libs/executor/src/timesliceoperator.c @@ -46,6 +46,8 @@ typedef struct STimeSliceOperatorInfo { SSDataBlock* pNextGroupRes; SSDataBlock* pRemainRes; // save block unfinished processing int32_t remainIndex; // the remaining index in the block to be processed + bool hasPk; + SColumn pkCol; } STimeSliceOperatorInfo; static void destroyTimeSliceOperatorInfo(void* param); @@ -953,6 +955,25 @@ _finished: return pResBlock->info.rows == 0 ? NULL : pResBlock; } +static int32_t extractPkColumnFromFuncs(SNodeList* pFuncs, bool* pHasPk, SColumn* pPkColumn) { + SNode* pNode; + FOREACH(pNode, pFuncs) { + if ((nodeType(pNode) == QUERY_NODE_TARGET) && + (nodeType(((STargetNode*)pNode)->pExpr) == QUERY_NODE_FUNCTION)) { + SFunctionNode* pFunc = (SFunctionNode*)((STargetNode*)pNode)->pExpr; + if (fmIsInterpFunc(pFunc->funcId) && pFunc->hasPk) { + SNode* pNode2 = (pFunc->pParameterList->pTail->pNode); + if ((nodeType(pNode2) == QUERY_NODE_COLUMN) && ((SColumnNode*)pNode2)->isPk) { + *pHasPk = true; + *pPkColumn = extractColumnFromColumnNode((SColumnNode*)pNode2); + break; + } + } + } + } + return TSDB_CODE_SUCCESS; +} + SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode* pPhyNode, SExecTaskInfo* pTaskInfo) { STimeSliceOperatorInfo* pInfo = taosMemoryCalloc(1, sizeof(STimeSliceOperatorInfo)); SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo)); @@ -985,6 +1006,7 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode } pInfo->tsCol = extractColumnFromColumnNode((SColumnNode*)pInterpPhyNode->pTimeSeries); + extractPkColumnFromFuncs(pInterpPhyNode->pFuncs, &pInfo->hasPk, &pInfo->pkCol); pInfo->fillType = convertFillType(pInterpPhyNode->fillMode); initResultSizeInfo(&pOperator->resultInfo, 4096); From 6202e1f501b444e7626115e7c86623e435737b28 Mon Sep 17 00:00:00 2001 From: slzhou Date: Fri, 29 Mar 2024 10:26:09 +0800 Subject: [PATCH 25/32] feat: drop pk column and update pk column is not supported for stable --- include/util/taoserror.h | 1 + source/libs/parser/src/parTranslater.c | 10 ++++++++-- source/libs/parser/src/parUtil.c | 4 +++- source/util/src/terror.c | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/util/taoserror.h b/include/util/taoserror.h index ba66cfb06a..affa1f0345 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -765,6 +765,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_TAG_IS_PRIMARY_KEY TAOS_DEF_ERROR_CODE(0, 0x2671) #define TSDB_CODE_PAR_SECOND_COL_PK TAOS_DEF_ERROR_CODE(0, 0x2672) #define TSDB_CODE_PAR_COL_PK_TYPE TAOS_DEF_ERROR_CODE(0, 0x2673) +#define TSDB_CODE_PAR_INVALID_PK_OP TAOS_DEF_ERROR_CODE(0, 0x2674) #define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF) //planner diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 3d59146d13..9fc9f28a6a 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -927,7 +927,7 @@ static bool isPrimaryKey(STempTableNode* pTable, SNode* pExpr) { return isPrimaryKeyImpl(pExpr); } -static bool hasPkInTable(STableMeta* pTableMeta) { +static bool hasPkInTable(const STableMeta* pTableMeta) { return pTableMeta->tableInfo.numOfColumns>=2 && pTableMeta->schema[1].flags & COL_IS_KEY; } @@ -6752,7 +6752,13 @@ static int32_t checkAlterSuperTableBySchema(STranslateContext* pCxt, SAlterTable : TSDB_CODE_PAR_INVALID_TAG_NAME, pStmt->colName); } - + if (hasPkInTable(pTableMeta) && (pSchema->flags & COL_IS_KEY)) { + if (TSDB_ALTER_TABLE_DROP_COLUMN == pStmt->alterType || + TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || + TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME == pStmt->alterType) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PK_OP, pStmt->colName); + } + } if ((TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || TSDB_ALTER_TABLE_UPDATE_TAG_BYTES == pStmt->alterType) && (!IS_VAR_DATA_TYPE(pSchema->type) || pSchema->type != pStmt->dataType.type || diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 39f50da9fd..7c82555e63 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -199,7 +199,9 @@ static char* getSyntaxErrFormat(int32_t errCode) { case TSDB_CODE_PAR_SECOND_COL_PK: return "primary key column must be second column"; case TSDB_CODE_PAR_COL_PK_TYPE: - return "primary key column must be of type int, uint, bigint, ubigint, and varchar"; + return "primary key column must be of type int, uint, bigint, ubigint, and varchar"; + case TSDB_CODE_PAR_INVALID_PK_OP: + return "primary key column can not be added, modified, and dropped"; default: return "Unknown error"; } diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 6df9bf0e16..a64c8642db 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -627,6 +627,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_SUPPORT_MULTI_RESULT, "Operator not suppor TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TAG_IS_PRIMARY_KEY, "tag can not be primary key") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_SECOND_COL_PK, "primary key must be second column") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_COL_PK_TYPE, "primary key column must be of type int, uint, bigint, ubigint, and varchar") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INVALID_PK_OP, "primary key column can not be added, modified, and dropped") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INTERNAL_ERROR, "Parser internal error") //planner From 1e5ef8271a3a78dd30a88d1c0dd2b7a5184e0306 Mon Sep 17 00:00:00 2001 From: slzhou Date: Fri, 29 Mar 2024 10:52:28 +0800 Subject: [PATCH 26/32] feat: update column and drop column is banned for normal table pk column --- source/libs/parser/src/parTranslater.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 9fc9f28a6a..b08552fc3d 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -10832,6 +10832,14 @@ static int32_t rewriteAlterTableImpl(STranslateContext* pCxt, SAlterTableStmt* p return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_ALTER_TABLE); } + const SSchema* pSchema = getNormalColSchema(pTableMeta, pStmt->colName); + if (hasPkInTable(pTableMeta) && pSchema && (pSchema->flags & COL_IS_KEY) && + (TSDB_ALTER_TABLE_DROP_COLUMN == pStmt->alterType || + TSDB_ALTER_TABLE_UPDATE_COLUMN_BYTES == pStmt->alterType || + TSDB_ALTER_TABLE_UPDATE_COLUMN_NAME == pStmt->alterType)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_PK_OP); + } + SVAlterTbReq req = {0}; int32_t code = buildAlterTbReq(pCxt, pStmt, pTableMeta, &req); From fe1a7e4b9c138781185d091d9e21d899a21bd4c8 Mon Sep 17 00:00:00 2001 From: slzhou Date: Fri, 29 Mar 2024 11:05:45 +0800 Subject: [PATCH 27/32] feat: add pk col to scan cols of scan logic node of delete operation --- source/libs/planner/src/planLogicCreater.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index c79fbd01f0..b5236fee9e 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -1696,6 +1696,11 @@ static int32_t createDeleteScanLogicNode(SLogicPlanContext* pCxt, SDeleteStmt* p } } + STableMeta* pMeta = ((SRealTableNode*)pDelete->pFromTable)->pMeta; + if (TSDB_CODE_SUCCESS == code && hasPkInTable(pMeta)) { + code = addPkCol(pMeta->uid, pMeta->schema + 1, &pScan->pScanCols, pMeta); + } + if (TSDB_CODE_SUCCESS == code && NULL != pDelete->pTagCond) { pScan->pTagCond = nodesCloneNode(pDelete->pTagCond); if (NULL == pScan->pTagCond) { From b50462783061cd60df5146b83d13e1de9e540eb7 Mon Sep 17 00:00:00 2001 From: slzhou Date: Fri, 29 Mar 2024 17:01:56 +0800 Subject: [PATCH 28/32] fix: new group block to reset func input iter hasPrev --- include/libs/function/function.h | 7 ++----- source/libs/executor/src/tsort.c | 5 +++-- source/libs/function/src/builtinsimpl.c | 7 ++++++- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 78bd1d807b..6c60e1c4a8 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -212,11 +212,8 @@ typedef struct SFuncInputRowIter { char* pPrevPk; SSDataBlock* pPrevRowBlock; // pre one row block - //TODO: - // int32_t prevStartOffset; // for diff, derivative. - // SPoint1 prevStartPoint; // for twa. - // int32_t startOffset; // for diff, derivative. - // SPoint1 startPoint; // for twa. + uint64_t groupId; + bool hasGroupId; bool finalRow; } SFuncInputRowIter; diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c index 271d3e05a5..44404c345e 100644 --- a/source/libs/executor/src/tsort.c +++ b/source/libs/executor/src/tsort.c @@ -1306,6 +1306,7 @@ static void appendToRowIndexDataBlock(SSortHandle* pHandle, SSDataBlock* pSource static void initRowIdSort(SSortHandle* pHandle) { SBlockOrderInfo* pkOrder = (pHandle->bSortPk) ? taosArrayGet(pHandle->aExtRowsOrders, 1) : NULL; SColumnInfoData* extPkCol = (pHandle->bSortPk) ? taosArrayGet(pHandle->pDataBlock->pDataBlock, pkOrder->slotId) : NULL; + SColumnInfoData pkCol = {0}; SSDataBlock* pSortInput = createDataBlock(); SColumnInfoData tsCol = createColumnInfoData(TSDB_DATA_TYPE_TIMESTAMP, 8, 1); @@ -1317,7 +1318,7 @@ static void initRowIdSort(SSortHandle* pHandle) { SColumnInfoData lengthCol = createColumnInfoData(TSDB_DATA_TYPE_INT, 4, 4); blockDataAppendColInfo(pSortInput, &lengthCol); if (pHandle->bSortPk) { - SColumnInfoData pkCol = createColumnInfoData(extPkCol->info.type, extPkCol->info.bytes, 5); + pkCol = createColumnInfoData(extPkCol->info.type, extPkCol->info.bytes, 5); blockDataAppendColInfo(pSortInput, &pkCol); } blockDataDestroy(pHandle->pDataBlock); @@ -1343,7 +1344,7 @@ static void initRowIdSort(SSortHandle* pHandle) { biPk.order = pkOrder->order; biPk.slotId = 4; biPk.nullFirst = (biPk.order == TSDB_ORDER_ASC); - biPk.compFn = getKeyComparFunc(extPkCol->info.type, biPk.order); + biPk.compFn = getKeyComparFunc(pkCol.info.type, biPk.order); taosArrayPush(aOrder, &biPk); } taosArrayDestroy(pHandle->pSortInfo); diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index c029a809eb..fafc313afc 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -434,7 +434,12 @@ int32_t funcInputUpdate(SqlFunctionCtx* pCtx) { pIter->pPkCol = pIter->pInput->pPrimaryKey; pIter->rowIndex = pIter->pInput->startRowIndex; pIter->inputEndIndex = pIter->rowIndex + pIter->pInput->numOfRows - 1; - pIter->pSrcBlock = pCtx->pSrcBlock; + pIter->pSrcBlock = pCtx->pSrcBlock; + if (!pIter->hasGroupId || pIter->groupId != pIter->pSrcBlock->info.id.groupId) { + pIter->hasGroupId = true; + pIter->groupId = pIter->pSrcBlock->info.id.groupId; + pIter->hasPrev = false; + } } else { pIter->finalRow = true; } From 110ac5bd161642a3250f60c234fbcc39aca1da25 Mon Sep 17 00:00:00 2001 From: slzhou Date: Fri, 29 Mar 2024 17:20:28 +0800 Subject: [PATCH 29/32] feat: add test case for pk func partition by tbname --- tests/parallel_test/cases.task | 1 + tests/system-test/2-query/pk_func_group.py | 284 +++++++++++++++++++++ 2 files changed, 285 insertions(+) create mode 100644 tests/system-test/2-query/pk_func_group.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index b33f0050d1..d15b12cfe6 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -46,6 +46,7 @@ ,,n,system-test,python3 ./test.py -f 8-stream/snode_restart_with_checkpoint.py -N 4 ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_func.py +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_func_group.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/partition_expr.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/project_group.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/tbname_vgroup.py diff --git a/tests/system-test/2-query/pk_func_group.py b/tests/system-test/2-query/pk_func_group.py new file mode 100644 index 0000000000..c6b2e0f846 --- /dev/null +++ b/tests/system-test/2-query/pk_func_group.py @@ -0,0 +1,284 @@ +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import tdDnodes +from math import inf + +class TDTestCase: + def caseDescription(self): + ''' + case1: [TD-] + ''' + return + + def init(self, conn, logSql, replicaVer=1): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + self.conn = conn + + def restartTaosd(self, index=1, dbname="db"): + tdDnodes.stop(index) + tdDnodes.startWithoutSleep(index) + tdSql.execute(f"use pk_func_group") + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists pk_func_group") + tdSql.execute("create database if not exists pk_func_group") + tdSql.execute('use pk_func_group') + tdSql.execute('drop database IF EXISTS d1;') + + tdSql.execute('drop database IF EXISTS d2;') + + tdSql.execute('create database d1 vgroups 1') + + tdSql.execute('use d1;') + + tdSql.execute('create table st(ts timestamp, pk int primary key, f int) tags(t int);') + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select first(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 3) + tdSql.checkData(1, 2, 3) + + tdSql.query('select last(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select last_row(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select ts,diff(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + + tdSql.query('select irate(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 4.0) + tdSql.checkData(1, 0, 5.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1.0) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5.0) + + tdSql.query('select twa(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 2.0) + tdSql.checkData(1, 0, 3.5) + + tdSql.query('select ts,pk,unique(f) from d1.st partition by tbname order by tbname,ts,pk;') + tdSql.checkRows(10) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 4) + tdSql.checkData(2, 2, 4) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + tdSql.checkData(3, 2, 5) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 6) + tdSql.checkData(4, 2, 6) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(5, 1, 3) + tdSql.checkData(5, 2, 3) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(6, 1, 4) + tdSql.checkData(6, 2, 4) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(7, 1, 2) + tdSql.checkData(7, 2, 2) + tdSql.checkData(8, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(8, 1, 7) + tdSql.checkData(8, 2, 7) + tdSql.checkData(9, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(9, 1, 8) + tdSql.checkData(9, 2, 8) + + tdSql.execute('create database d2 vgroups 2') + + tdSql.execute('use d2;') + + tdSql.execute('create table st(ts timestamp, pk int primary key, f int) tags(t int);') + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select first(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 3) + tdSql.checkData(1, 2, 3) + + tdSql.query('select last(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select last_row(*) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select ts,diff(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + + tdSql.query('select irate(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 4.0) + tdSql.checkData(1, 0, 5.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1.0) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5.0) + + tdSql.query('select twa(f) from d1.st partition by tbname order by tbname;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 2.0) + tdSql.checkData(1, 0, 3.5) + + tdSql.query('select ts,pk,unique(f) from d1.st partition by tbname order by tbname,ts,pk;') + tdSql.checkRows(10) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 4) + tdSql.checkData(2, 2, 4) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + tdSql.checkData(3, 2, 5) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 6) + tdSql.checkData(4, 2, 6) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(5, 1, 3) + tdSql.checkData(5, 2, 3) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(6, 1, 4) + tdSql.checkData(6, 2, 4) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(7, 1, 2) + tdSql.checkData(7, 2, 2) + tdSql.checkData(8, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(8, 1, 7) + tdSql.checkData(8, 2, 7) + tdSql.checkData(9, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(9, 1, 8) + tdSql.checkData(9, 2, 8) + + tdSql.execute('drop database pk_func_group') + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) From 55bb6ab341b524d99ac71d450331e47d3f28a052 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 29 Mar 2024 18:15:03 +0800 Subject: [PATCH 30/32] fix(tsdb): set correct initial value for compare --- include/common/tdataformat.h | 1 + source/common/src/tdataformat.c | 21 ++++++ source/dnode/vnode/src/tq/tq.c | 1 - source/dnode/vnode/src/tsdb/tsdbReadUtil.c | 30 +++++++-- source/dnode/vnode/src/tsdb/tsdbUtil.c | 21 ------ source/libs/executor/src/timesliceoperator.c | 65 +++++++++++++++---- source/libs/executor/src/timewindowoperator.c | 5 +- source/util/test/tbaseCodecTest.cpp | 5 -- 8 files changed, 101 insertions(+), 48 deletions(-) diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 73e6837475..6c8a39caf6 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -126,6 +126,7 @@ int32_t tRowMerge(SArray *aRowP, STSchema *pTSchema, int8_t flag); int32_t tRowUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aColData, int32_t nColData, int32_t flag); void tRowGetKey(SRow *pRow, SRowKey *key); int32_t tRowKeyCompare(const void *p1, const void *p2); +int32_t tRowKeyAssign(SRowKey* pDst, SRowKey* pSrc); // SRowIter ================================ int32_t tRowIterOpen(SRow *pRow, STSchema *pTSchema, SRowIter **ppIter); diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index cf8e28bf9a..ceb572edc3 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1286,6 +1286,27 @@ int32_t tRowKeyCompare(const void *p1, const void *p2) { return 0; } +int32_t tRowKeyAssign(SRowKey *pDst, SRowKey* pSrc) { + pDst->ts = pSrc->ts; + pDst->numOfPKs = pSrc->numOfPKs; + + if (pSrc->numOfPKs > 0) { + for (int32_t i = 0; i < pSrc->numOfPKs; ++i) { + SValue *pVal = &pDst->pks[i]; + pVal->type = pSrc->pks[i].type; + + if (IS_NUMERIC_TYPE(pVal->type)) { + pVal->val = pSrc->pks[i].val; + } else { + memcpy(pVal->pData, pVal->pData, pVal->nData); + pVal->nData = pSrc->pks[i].nData; + } + } + } + + return TSDB_CODE_SUCCESS; +} + // STag ======================================== static int tTagValCmprFn(const void *p1, const void *p2) { if (((STagVal *)p1)->cid < ((STagVal *)p2)->cid) { diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c index ffebd783ac..141fe88339 100644 --- a/source/dnode/vnode/src/tq/tq.c +++ b/source/dnode/vnode/src/tq/tq.c @@ -1183,7 +1183,6 @@ int32_t tqProcessTaskCheckPointSourceReq(STQ* pTq, SRpcMsg* pMsg, SRpcMsg* pRsp) return TSDB_CODE_SUCCESS; } } else { -// ASSERT(status == TASK_STATUS__HALT); if (status != TASK_STATUS__HALT) { tqError("s-task:%s should in halt status, let's halt it directly", pTask->id.idStr); // streamTaskHandleEvent(pTask->status.pSM, TASK_EVENT_HALT); diff --git a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c index 99f0e42261..86c6b70c92 100644 --- a/source/dnode/vnode/src/tsdb/tsdbReadUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbReadUtil.c @@ -130,14 +130,29 @@ STableBlockScanInfo* getTableBlockScanInfo(SSHashObj* pTableMap, uint64_t uid, c return *p; } -static int32_t initSRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, int32_t len) { +static int32_t initSRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t type, int32_t len, bool asc) { pKey->numOfPKs = numOfPks; pKey->ts = ts; if (numOfPks > 0) { pKey->pks[0].type = type; if (IS_NUMERIC_TYPE(pKey->pks[0].type)) { - pKey->pks[0].val = INT64_MIN; + char* p = (char*)&pKey->pks[0].val; + if (asc) { + switch(pKey->pks[0].type) { + case TSDB_DATA_TYPE_BIGINT:*(int64_t*)p = INT64_MIN;break; + case TSDB_DATA_TYPE_INT:*(int32_t*)p = INT32_MIN;break; + case TSDB_DATA_TYPE_SMALLINT:*(int16_t*)p = INT16_MIN;break; + case TSDB_DATA_TYPE_TINYINT:*(int8_t*)p = INT8_MIN;break; + } + } else { + switch(pKey->pks[0].type) { + case TSDB_DATA_TYPE_BIGINT:*(int64_t*)p = INT64_MAX;break; + case TSDB_DATA_TYPE_INT:*(int32_t*)p = INT32_MAX;break; + case TSDB_DATA_TYPE_SMALLINT:*(int16_t*)p = INT16_MAX;break; + case TSDB_DATA_TYPE_TINYINT:*(int8_t*)p = INT8_MAX;break; + } + } } else { pKey->pks[0].pData = taosMemoryCalloc(1, len); pKey->pks[0].nData = 0; @@ -154,22 +169,23 @@ static int32_t initSRowKey(SRowKey* pKey, int64_t ts, int32_t numOfPks, int32_t static void initLastProcKey(STableBlockScanInfo *pScanInfo, STsdbReader* pReader) { int32_t numOfPks = pReader->suppInfo.numOfPks; + bool asc = ASCENDING_TRAVERSE(pReader->info.order); SRowKey* pRowKey = &pScanInfo->lastProcKey; - if (ASCENDING_TRAVERSE(pReader->info.order)) { + if (asc) { int64_t skey = pReader->info.window.skey; int64_t ts = (skey > INT64_MIN) ? (skey - 1) : skey; - initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes); + initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes, asc); initSRowKey(&pScanInfo->sttKeyInfo.nextProcKey, skey, numOfPks, pReader->suppInfo.pk.type, - pReader->suppInfo.pk.bytes); + pReader->suppInfo.pk.bytes, asc); } else { int64_t ekey = pReader->info.window.ekey; int64_t ts = (ekey < INT64_MAX) ? (ekey + 1) : ekey; - initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes); + initSRowKey(pRowKey, ts, numOfPks, pReader->suppInfo.pk.type, pReader->suppInfo.pk.bytes, asc); initSRowKey(&pScanInfo->sttKeyInfo.nextProcKey, ekey, numOfPks, pReader->suppInfo.pk.type, - pReader->suppInfo.pk.bytes); + pReader->suppInfo.pk.bytes, asc); } } diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 59452ebb9d..2b8de9aff3 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -628,27 +628,6 @@ void tColRowGetKey(SBlockData* pBlock, int32_t irow, SRowKey* key) { } } -int32_t tRowKeyAssign(SRowKey *pDst, SRowKey* pSrc) { - pDst->ts = pSrc->ts; - pDst->numOfPKs = pSrc->numOfPKs; - - if (pSrc->numOfPKs > 0) { - for (int32_t i = 0; i < pSrc->numOfPKs; ++i) { - SValue *pVal = &pDst->pks[i]; - pVal->type = pSrc->pks[i].type; - - if (IS_NUMERIC_TYPE(pVal->type)) { - pVal->val = pSrc->pks[i].val; - } else { - memcpy(pVal->pData, pVal->pData, pVal->nData); - pVal->nData = pSrc->pks[i].nData; - } - } - } - - return TSDB_CODE_SUCCESS; -} - int32_t tsdbRowKeyCmpr(const STsdbRowKey *key1, const STsdbRowKey *key2) { int32_t c = tRowKeyCompare(&key1->key, &key2->key); diff --git a/source/libs/executor/src/timesliceoperator.c b/source/libs/executor/src/timesliceoperator.c index 4b86f85d53..9b28a203b8 100644 --- a/source/libs/executor/src/timesliceoperator.c +++ b/source/libs/executor/src/timesliceoperator.c @@ -39,7 +39,7 @@ typedef struct STimeSliceOperatorInfo { SColumn tsCol; // primary timestamp column SExprSupp scalarSup; // scalar calculation struct SFillColInfo* pFillColInfo; // fill column info - int64_t prevTs; + SRowKey prevKey; bool prevTsSet; uint64_t groupId; SGroupKeys* pPrevGroupKey; @@ -178,22 +178,49 @@ static bool isIsfilledPseudoColumn(SExprInfo* pExprInfo) { return (IS_BOOLEAN_TYPE(pExprInfo->base.resSchema.type) && strcasecmp(name, "_isfilled") == 0); } +static void tRowGetKeyFromColData(int64_t ts, SColumnInfoData* pPkCol, int32_t rowIndex, SRowKey* pKey) { + pKey->ts = ts; + pKey->numOfPKs = 1; + + int8_t t = pPkCol->info.type; + + pKey->pks[0].type = t; + if (IS_NUMERIC_TYPE(t)) { + GET_TYPED_DATA(pKey->pks[0].val, int64_t, t, colDataGetNumData(pPkCol, rowIndex)); + } else { + char* p = colDataGetVarData(pPkCol, rowIndex); + pKey->pks[0].pData = (uint8_t*)varDataVal(p); + pKey->pks[0].nData = varDataLen(p); + } +} + static bool checkDuplicateTimestamps(STimeSliceOperatorInfo* pSliceInfo, SColumnInfoData* pTsCol, - int32_t curIndex, int32_t rows) { - - + SColumnInfoData* pPkCol, int32_t curIndex, int32_t rows) { int64_t currentTs = *(int64_t*)colDataGetData(pTsCol, curIndex); if (currentTs > pSliceInfo->win.ekey) { return false; } - if ((pSliceInfo->prevTsSet == true) && (currentTs == pSliceInfo->prevTs)) { - return true; + SRowKey cur = {.ts = currentTs, .numOfPKs = (pPkCol != NULL)? 1:0}; + if (pPkCol != NULL) { + cur.pks[0].type = pPkCol->info.type; + } + + if ((pSliceInfo->prevTsSet == true) && (currentTs == pSliceInfo->prevKey.ts)) { +// if (pPkCol == NULL) { + return true; + /* } else { + tRowGetKeyFromColData(currentTs, pPkCol, curIndex, &cur); + if (tRowKeyCompare(&cur, &pSliceInfo->prevKey) == 0) { + return true; + } + }*/ } pSliceInfo->prevTsSet = true; - pSliceInfo->prevTs = currentTs; + tRowKeyAssign(&pSliceInfo->prevKey, &cur); + // todo handle next if (currentTs == pSliceInfo->win.ekey && curIndex < rows - 1) { int64_t nextTs = *(int64_t*)colDataGetData(pTsCol, curIndex + 1); if (currentTs == nextTs) { @@ -695,14 +722,20 @@ static void doTimesliceImpl(SOperatorInfo* pOperator, STimeSliceOperatorInfo* pS SInterval* pInterval = &pSliceInfo->interval; SColumnInfoData* pTsCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->tsCol.slotId); + SColumnInfoData* pPkCol = NULL; + + if (pSliceInfo->hasPk) { + pPkCol = taosArrayGet(pBlock->pDataBlock, pSliceInfo->pkCol.slotId); + } int32_t i = (pSliceInfo->pRemainRes == NULL) ? 0 : pSliceInfo->remainIndex; for (; i < pBlock->info.rows; ++i) { int64_t ts = *(int64_t*)colDataGetData(pTsCol, i); // check for duplicate timestamps - if (checkDuplicateTimestamps(pSliceInfo, pTsCol, i, pBlock->info.rows)) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_FUNC_DUP_TIMESTAMP); + if (checkDuplicateTimestamps(pSliceInfo, pTsCol, pPkCol, i, pBlock->info.rows)) { + continue; +// T_LONG_JMP(pTaskInfo->env, TSDB_CODE_FUNC_DUP_TIMESTAMP); } if (checkNullRow(&pOperator->exprSupp, pBlock, i, ignoreNull)) { @@ -875,11 +908,9 @@ static SSDataBlock* doTimeslice(SOperatorInfo* pOperator) { return NULL; } - SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; STimeSliceOperatorInfo* pSliceInfo = pOperator->info; SSDataBlock* pResBlock = pSliceInfo->pRes; - SOperatorInfo* downstream = pOperator->pDownstream[0]; blockDataCleanup(pResBlock); while (1) { @@ -1017,13 +1048,23 @@ SOperatorInfo* createTimeSliceOperatorInfo(SOperatorInfo* downstream, SPhysiNode pInfo->interval.interval = pInterpPhyNode->interval; pInfo->current = pInfo->win.skey; pInfo->prevTsSet = false; - pInfo->prevTs = 0; + pInfo->prevKey.ts = INT64_MIN; pInfo->groupId = 0; pInfo->pPrevGroupKey = NULL; pInfo->pNextGroupRes = NULL; pInfo->pRemainRes = NULL; pInfo->remainIndex = 0; + if (pInfo->hasPk) { + pInfo->prevKey.numOfPKs = 1; + pInfo->prevKey.ts = INT64_MIN; + pInfo->prevKey.pks[0].type = pInfo->pkCol.type; + + if (IS_VAR_DATA_TYPE(pInfo->pkCol.type)) { + pInfo->prevKey.pks[0].pData = taosMemoryCalloc(1, pInfo->pkCol.bytes); + } + } + if (downstream->operatorType == QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN) { STableScanInfo* pScanInfo = (STableScanInfo*)downstream->info; pScanInfo->base.cond.twindows = pInfo->win; diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index 57c038e75a..57cc0e82d2 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -658,11 +658,12 @@ static bool isCalculatedWin(SIntervalAggOperatorInfo* pInfo, const STimeWindow* */ static bool filterWindowWithLimit(SIntervalAggOperatorInfo* pOperatorInfo, STimeWindow* win, uint64_t groupId) { if (!pOperatorInfo->limited // if no limit info, no filter will be applied - || pOperatorInfo->binfo.inputTsOrder != - pOperatorInfo->binfo.outputTsOrder // if input/output ts order mismatch, no filter + || pOperatorInfo->binfo.inputTsOrder != pOperatorInfo->binfo.outputTsOrder + // if input/output ts order mismatch, no filter ) { return false; } + if (pOperatorInfo->limit == 0) return true; if (pOperatorInfo->pBQ == NULL) { diff --git a/source/util/test/tbaseCodecTest.cpp b/source/util/test/tbaseCodecTest.cpp index 4c56979885..63bbfcaa68 100644 --- a/source/util/test/tbaseCodecTest.cpp +++ b/source/util/test/tbaseCodecTest.cpp @@ -17,11 +17,6 @@ using namespace std; #pragma GCC diagnostic ignored "-Wunused-variable" #pragma GCC diagnostic ignored "-Wsign-compare" -int main(int argc, char **argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} - static void checkBase58Codec(uint8_t *pRaw, int32_t rawLen, int32_t index) { int64_t start = taosGetTimestampUs(); char *pEnc = base58_encode((const uint8_t *)pRaw, rawLen); From dd2f6287ec96214176a506df136f821bad0e483b Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Fri, 29 Mar 2024 18:59:29 +0800 Subject: [PATCH 31/32] fix(tsdb): fix rowkey assign error. --- source/common/src/tdataformat.c | 2 +- source/dnode/vnode/src/tsdb/tsdbRead2.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index ceb572edc3..991c17c5cc 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -1298,7 +1298,7 @@ int32_t tRowKeyAssign(SRowKey *pDst, SRowKey* pSrc) { if (IS_NUMERIC_TYPE(pVal->type)) { pVal->val = pSrc->pks[i].val; } else { - memcpy(pVal->pData, pVal->pData, pVal->nData); + memcpy(pVal->pData, pSrc->pks[i].pData, pVal->nData); pVal->nData = pSrc->pks[i].nData; } } diff --git a/source/dnode/vnode/src/tsdb/tsdbRead2.c b/source/dnode/vnode/src/tsdb/tsdbRead2.c index c7164d43de..5469eae1cd 100644 --- a/source/dnode/vnode/src/tsdb/tsdbRead2.c +++ b/source/dnode/vnode/src/tsdb/tsdbRead2.c @@ -2068,8 +2068,8 @@ static int32_t initMemDataIterator(STableBlockScanInfo* pBlockScanInfo, STsdbRea return TSDB_CODE_SUCCESS; } - STsdbRowKey startKey = {0}; - tRowKeyAssign(&startKey.key, &pBlockScanInfo->lastProcKey); + STsdbRowKey startKey; + startKey.key = pBlockScanInfo->lastProcKey; startKey.version = asc ? pReader->info.verRange.minVer : pReader->info.verRange.maxVer; if ((asc && (startKey.key.ts < pWindow->skey)) || ((!asc) && startKey.key.ts > pWindow->ekey)) { startKey.key.ts = asc? pWindow->skey:pWindow->ekey; From 719b8439f073d538888d2e6eab5f440f054ec00c Mon Sep 17 00:00:00 2001 From: slzhou Date: Mon, 1 Apr 2024 08:58:43 +0800 Subject: [PATCH 32/32] feat: add test for pk modification --- tests/parallel_test/cases.task | 1 + tests/system-test/2-query/pk_error.py | 267 ++++++++++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 tests/system-test/2-query/pk_error.py diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task index d15b12cfe6..0cdac26a3a 100644 --- a/tests/parallel_test/cases.task +++ b/tests/parallel_test/cases.task @@ -45,6 +45,7 @@ #,,n,system-test,python3 ./test.py -f 8-stream/snode_restart.py -N 4 ,,n,system-test,python3 ./test.py -f 8-stream/snode_restart_with_checkpoint.py -N 4 +,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_error.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_func.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/pk_func_group.py ,,y,system-test,./pytest.sh python3 ./test.py -f 2-query/partition_expr.py diff --git a/tests/system-test/2-query/pk_error.py b/tests/system-test/2-query/pk_error.py new file mode 100644 index 0000000000..7aa1d81942 --- /dev/null +++ b/tests/system-test/2-query/pk_error.py @@ -0,0 +1,267 @@ +import sys +from util.log import * +from util.cases import * +from util.sql import * +from util.dnodes import tdDnodes +from math import inf + +class TDTestCase: + def caseDescription(self): + ''' + case1: [TD-] + ''' + return + + def init(self, conn, logSql, replicaVer=1): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor(), True) + self.conn = conn + + def restartTaosd(self, index=1, dbname="db"): + tdDnodes.stop(index) + tdDnodes.startWithoutSleep(index) + tdSql.execute(f"use pk_error") + + def run(self): + print("running {}".format(__file__)) + tdSql.execute("drop database if exists pk_error") + tdSql.execute("create database if not exists pk_error") + tdSql.execute('use pk_error') + tdSql.execute('drop database IF EXISTS d1;') + + tdSql.execute('drop database IF EXISTS d2;') + + tdSql.execute('create database d1 vgroups 1') + + tdSql.execute('use d1;') + + tdSql.execute('create table st(ts timestamp, pk int primary key, f int) tags(t int);') + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into ct1 using st tags(1) values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into ct2 using st tags(2) values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select first(*) from d1.st partition by t order by t;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 3) + tdSql.checkData(1, 2, 3) + + tdSql.query('select last(*) from d1.st partition by t order by t;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select last_row(*) from d1.st partition by t order by t;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 6) + tdSql.checkData(0, 2, 6) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 8) + tdSql.checkData(1, 2, 8) + + tdSql.query('select ts,diff(f) from d1.st partition by t order by t;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + + tdSql.query('select irate(f) from d1.st partition by t order by t;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 4.0) + tdSql.checkData(1, 0, 5.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.st partition by t order by t;') + tdSql.checkRows(4) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, -1.0) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5.0) + + tdSql.query('select twa(f) from d1.st partition by t order by t;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, 2.0) + tdSql.checkData(1, 0, 3.5) + + tdSql.query('select ts,pk,unique(f) from d1.st partition by t order by t,ts,pk;') + tdSql.checkRows(10) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(2, 1, 4) + tdSql.checkData(2, 2, 4) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(3, 1, 5) + tdSql.checkData(3, 2, 5) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 6) + tdSql.checkData(4, 2, 6) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(5, 1, 3) + tdSql.checkData(5, 2, 3) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(6, 1, 4) + tdSql.checkData(6, 2, 4) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(7, 1, 2) + tdSql.checkData(7, 2, 2) + tdSql.checkData(8, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(8, 1, 7) + tdSql.checkData(8, 2, 7) + tdSql.checkData(9, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(9, 1, 8) + tdSql.checkData(9, 2, 8) + + tdSql.execute('create table nt(ts timestamp, pk int primary key, f int);') + + tdSql.execute("insert into nt values('2021-04-19 00:00:00', 1, 1);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:00', 2, 2);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:00', 3, 3);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:00', 4, 4);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:01', 1, 1);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:01', 4, 4);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:01', 3, 3);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:01', 2, 2);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:02', 6, 6);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:02', 5, 5);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:02', 8, 8);") + + tdSql.execute("insert into nt values('2021-04-19 00:00:02', 7, 7);") + + tdSql.query('select first(*) from d1.nt;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + + tdSql.query('select last(*) from d1.nt;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select last_row(*) from d1.nt;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(0, 1, 8) + tdSql.checkData(0, 2, 8) + + tdSql.query('select ts,diff(f) from d1.nt;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4) + + tdSql.query('select irate(f) from d1.nt;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 4.0) + + tdSql.query('select ts,derivative(f, 1s, 0) from d1.nt;') + tdSql.checkRows(2) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0, 1)) + tdSql.checkData(0, 1, 0.0) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(1, 1, 4.0) + + tdSql.query('select twa(f) from d1.nt;') + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2.0) + + tdSql.query('select ts,pk,unique(f) from d1.nt order by ts,pk;') + tdSql.checkRows(8) + tdSql.checkData(0, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(0, 1, 1) + tdSql.checkData(0, 2, 1) + tdSql.checkData(1, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(1, 1, 2) + tdSql.checkData(1, 2, 2) + tdSql.checkData(2, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(2, 1, 3) + tdSql.checkData(2, 2, 3) + tdSql.checkData(3, 0, datetime.datetime(2021, 4, 19, 0, 0)) + tdSql.checkData(3, 1, 4) + tdSql.checkData(3, 2, 4) + tdSql.checkData(4, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(4, 1, 5) + tdSql.checkData(4, 2, 5) + tdSql.checkData(5, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(5, 1, 6) + tdSql.checkData(5, 2, 6) + tdSql.checkData(6, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(6, 1, 7) + tdSql.checkData(6, 2, 7) + tdSql.checkData(7, 0, datetime.datetime(2021, 4, 19, 0, 0, 2)) + tdSql.checkData(7, 1, 8) + tdSql.checkData(7, 2, 8) + + tdSql.execute('create table st2(ts timestamp, vcpk varchar(64) primary key, f int);') + + tdSql.error('alter table st drop column pk;') + + tdSql.error('alter table nt drop column pk;') + + tdSql.error('alter table st modify column pk bigint;') + + tdSql.error('alter table nt modify column pk bigint;') + + tdSql.error('alter table st2 modify column vcpk varchar(32)') + + tdSql.execute('drop database pk_error') + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase())